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