001 /* 002 // $Id: TypeUtil.java 247 2009-06-20 05:52:40Z jhyde $ 003 // This software is subject to the terms of the Eclipse Public License v1.0 004 // Agreement, available at the following URL: 005 // http://www.eclipse.org/legal/epl-v10.html. 006 // Copyright (C) 2005-2009 Julian Hyde 007 // All Rights Reserved. 008 // You must accept the terms of that agreement to use this software. 009 */ 010 package org.olap4j.type; 011 012 import org.olap4j.metadata.Hierarchy; 013 import org.olap4j.OlapException; 014 015 /** 016 * Utility methods relating to types. 017 * 018 * <p>NOTE: This class is experimental. Not part of the public olap4j API. 019 * 020 * @author jhyde 021 * @since Feb 17, 2005 022 * @version $Id: TypeUtil.java 247 2009-06-20 05:52:40Z jhyde $ 023 */ 024 public class TypeUtil { 025 026 /** 027 * Given a set type, returns the element type. Or its element type, if it 028 * is a set type. And so on. 029 */ 030 private static Type stripSetType(Type type) { 031 while (type instanceof SetType) { 032 type = ((SetType) type).getElementType(); 033 } 034 return type; 035 } 036 037 /** 038 * Converts a type to a member or tuple type. 039 * If it cannot, returns null. 040 */ 041 private static Type toMemberOrTupleType(Type type) throws OlapException { 042 type = stripSetType(type); 043 if (type instanceof TupleType) { 044 return (TupleType) type; 045 } else { 046 return toMemberType(type); 047 } 048 } 049 050 /** 051 * Converts a type to a member type. 052 * If it is a set, strips the set. 053 * If it is a member type, returns the type unchanged. 054 * If it is a dimension, hierarchy or level type, converts it to 055 * a member type. 056 * If it is a tuple, number, string, or boolean, returns null. 057 */ 058 static MemberType toMemberType(Type type) throws OlapException { 059 type = stripSetType(type); 060 if (type instanceof MemberType) { 061 return (MemberType) type; 062 } else if (type instanceof DimensionType 063 || type instanceof HierarchyType 064 || type instanceof LevelType) 065 { 066 return MemberType.forType(type); 067 } else { 068 return null; 069 } 070 } 071 072 /** 073 * Returns whether this type is union-compatible with another. 074 * In general, to be union-compatible, types must have the same 075 * dimensionality. 076 * 077 * @param type1 First type 078 * @param type2 Second type 079 * @return Whether types are union-compatible 080 * @throws OlapException on error 081 */ 082 static boolean isUnionCompatible( 083 Type type1, 084 Type type2) 085 throws OlapException 086 { 087 if (type1 instanceof TupleType) { 088 return type2 instanceof TupleType 089 && ((TupleType) type1).isUnionCompatibleWith( 090 (TupleType) type2); 091 } else { 092 final MemberType memberType1 = toMemberType(type1); 093 if (memberType1 == null) { 094 return false; 095 } 096 final MemberType memberType2 = toMemberType(type2); 097 if (memberType2 == null) { 098 return false; 099 } 100 final Hierarchy hierarchy1 = memberType1.getHierarchy(); 101 final Hierarchy hierarchy2 = memberType2.getHierarchy(); 102 return equal(hierarchy1, hierarchy2); 103 } 104 } 105 106 private static boolean equal( 107 final Hierarchy hierarchy1, final Hierarchy hierarchy2) 108 { 109 if (hierarchy1 == null 110 || hierarchy2 == null 111 || hierarchy2.getUniqueName().equals( 112 hierarchy1.getUniqueName())) 113 { 114 // They are compatible. 115 return true; 116 } else { 117 return false; 118 } 119 } 120 121 /** 122 * Returns whether a value of a given type can be evaluated to a scalar 123 * value. 124 * 125 * <p>The rules are as follows:<ul> 126 * <li>Clearly boolean, numeric and string expressions can be evaluated. 127 * <li>Member and tuple expressions can be interpreted as a scalar value. 128 * The expression is evaluated to establish the context where a measure 129 * can be evaluated. 130 * <li>Hierarchy and dimension expressions are implicitly 131 * converted into the current member, and evaluated as above. 132 * <li>Level expressions cannot be evaluated 133 * <li>Cube and Set (even sets with a single member) cannot be evaluated. 134 * </ul> 135 * 136 * @param type Type 137 * @return Whether an expression of this type can be evaluated to yield a 138 * scalar value. 139 */ 140 public static boolean canEvaluate(Type type) { 141 return ! (type instanceof SetType 142 || type instanceof CubeType 143 || type instanceof LevelType); 144 } 145 146 /** 147 * Returns whether a type is a set type. 148 * 149 * @param type Type 150 * @return Whether a value of this type can be evaluated to yield a set. 151 */ 152 public static boolean isSet(Type type) { 153 return type instanceof SetType; 154 } 155 156 private static boolean couldBeMember(Type type) { 157 return type instanceof MemberType 158 || type instanceof HierarchyType 159 || type instanceof DimensionType; 160 } 161 162 static boolean equal(Object o, Object p) { 163 return o == null ? p == null : p != null && o.equals(p); 164 } 165 } 166 167 // End TypeUtil.java