001/* 002// $Id: TypeUtil.java 482 2012-01-05 23:27:27Z jhyde $ 003// 004// Licensed to Julian Hyde under one or more contributor license 005// agreements. See the NOTICE file distributed with this work for 006// additional information regarding copyright ownership. 007// 008// Julian Hyde licenses this file to you under the Apache License, 009// Version 2.0 (the "License"); you may not use this file except in 010// compliance with the License. You may obtain a copy of the License at: 011// 012// http://www.apache.org/licenses/LICENSE-2.0 013// 014// Unless required by applicable law or agreed to in writing, software 015// distributed under the License is distributed on an "AS IS" BASIS, 016// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017// See the License for the specific language governing permissions and 018// limitations under the License. 019*/ 020package org.olap4j.type; 021 022import org.olap4j.OlapException; 023import org.olap4j.metadata.Hierarchy; 024 025/** 026 * Utility methods relating to types. 027 * 028 * <p>NOTE: This class is experimental. Not part of the public olap4j API. 029 * 030 * @author jhyde 031 * @since Feb 17, 2005 032 * @version $Id: TypeUtil.java 482 2012-01-05 23:27:27Z jhyde $ 033 */ 034public class TypeUtil { 035 036 /** 037 * Given a set type, returns the element type. Or its element type, if it 038 * is a set type. And so on. 039 */ 040 private static Type stripSetType(Type type) { 041 while (type instanceof SetType) { 042 type = ((SetType) type).getElementType(); 043 } 044 return type; 045 } 046 047 /** 048 * Converts a type to a member or tuple type. 049 * If it cannot, returns null. 050 */ 051 private static Type toMemberOrTupleType(Type type) throws OlapException { 052 type = stripSetType(type); 053 if (type instanceof TupleType) { 054 return (TupleType) type; 055 } else { 056 return toMemberType(type); 057 } 058 } 059 060 /** 061 * Converts a type to a member type. 062 * If it is a set, strips the set. 063 * If it is a member type, returns the type unchanged. 064 * If it is a dimension, hierarchy or level type, converts it to 065 * a member type. 066 * If it is a tuple, number, string, or boolean, returns null. 067 */ 068 static MemberType toMemberType(Type type) throws OlapException { 069 type = stripSetType(type); 070 if (type instanceof MemberType) { 071 return (MemberType) type; 072 } else if (type instanceof DimensionType 073 || type instanceof HierarchyType 074 || type instanceof LevelType) 075 { 076 return MemberType.forType(type); 077 } else { 078 return null; 079 } 080 } 081 082 /** 083 * Returns whether this type is union-compatible with another. 084 * In general, to be union-compatible, types must have the same 085 * dimensionality. 086 * 087 * @param type1 First type 088 * @param type2 Second type 089 * @return Whether types are union-compatible 090 * @throws OlapException on error 091 */ 092 static boolean isUnionCompatible( 093 Type type1, 094 Type type2) 095 throws OlapException 096 { 097 if (type1 instanceof TupleType) { 098 return type2 instanceof TupleType 099 && ((TupleType) type1).isUnionCompatibleWith( 100 (TupleType) type2); 101 } else { 102 final MemberType memberType1 = toMemberType(type1); 103 if (memberType1 == null) { 104 return false; 105 } 106 final MemberType memberType2 = toMemberType(type2); 107 if (memberType2 == null) { 108 return false; 109 } 110 final Hierarchy hierarchy1 = memberType1.getHierarchy(); 111 final Hierarchy hierarchy2 = memberType2.getHierarchy(); 112 return equal(hierarchy1, hierarchy2); 113 } 114 } 115 116 private static boolean equal( 117 final Hierarchy hierarchy1, final Hierarchy hierarchy2) 118 { 119 if (hierarchy1 == null 120 || hierarchy2 == null 121 || hierarchy2.getUniqueName().equals( 122 hierarchy1.getUniqueName())) 123 { 124 // They are compatible. 125 return true; 126 } else { 127 return false; 128 } 129 } 130 131 /** 132 * Returns whether a value of a given type can be evaluated to a scalar 133 * value. 134 * 135 * <p>The rules are as follows:<ul> 136 * <li>Clearly boolean, numeric and string expressions can be evaluated. 137 * <li>Member and tuple expressions can be interpreted as a scalar value. 138 * The expression is evaluated to establish the context where a measure 139 * can be evaluated. 140 * <li>Hierarchy and dimension expressions are implicitly 141 * converted into the current member, and evaluated as above. 142 * <li>Level expressions cannot be evaluated 143 * <li>Cube and Set (even sets with a single member) cannot be evaluated. 144 * </ul> 145 * 146 * @param type Type 147 * @return Whether an expression of this type can be evaluated to yield a 148 * scalar value. 149 */ 150 public static boolean canEvaluate(Type type) { 151 return ! (type instanceof SetType 152 || type instanceof CubeType 153 || type instanceof LevelType); 154 } 155 156 /** 157 * Returns whether a type is a set type. 158 * 159 * @param type Type 160 * @return Whether a value of this type can be evaluated to yield a set. 161 */ 162 public static boolean isSet(Type type) { 163 return type instanceof SetType; 164 } 165 166 private static boolean couldBeMember(Type type) { 167 return type instanceof MemberType 168 || type instanceof HierarchyType 169 || type instanceof DimensionType; 170 } 171 172 static boolean equal(Object o, Object p) { 173 return o == null ? p == null : p != null && o.equals(p); 174 } 175} 176 177// End TypeUtil.java 178