001/* 002// This software is subject to the terms of the Eclipse Public License v1.0 003// Agreement, available at the following URL: 004// http://www.eclipse.org/legal/epl-v10.html. 005// You must accept the terms of that agreement to use this software. 006// 007// Copyright (C) 2005-2005 Julian Hyde 008// Copyright (C) 2005-2011 Pentaho 009// All Rights Reserved. 010*/ 011package mondrian.olap.type; 012 013import mondrian.olap.*; 014 015/** 016 * The type of an expression which represents a member. 017 * 018 * @author jhyde 019 * @since Feb 17, 2005 020 */ 021public class MemberType implements Type { 022 private final Hierarchy hierarchy; 023 private final Dimension dimension; 024 private final Level level; 025 private final Member member; 026 private final String digest; 027 028 public static final MemberType Unknown = 029 new MemberType(null, null, null, null); 030 031 /** 032 * Creates a type representing a member. 033 * 034 * @param dimension Dimension the member belongs to, or null if not known 035 * @param hierarchy Hierarchy the member belongs to, or null if not known 036 * @param level Level the member belongs to, or null if not known 037 * @param member The precise member, or null if not known 038 */ 039 public MemberType( 040 Dimension dimension, 041 Hierarchy hierarchy, 042 Level level, 043 Member member) 044 { 045 this.dimension = dimension; 046 this.hierarchy = hierarchy; 047 this.level = level; 048 this.member = member; 049 if (member != null) { 050 Util.assertPrecondition(level != null); 051 Util.assertPrecondition(member.getLevel() == level); 052 } 053 if (level != null) { 054 Util.assertPrecondition(hierarchy != null); 055 Util.assertPrecondition(level.getHierarchy() == hierarchy); 056 } 057 if (hierarchy != null) { 058 Util.assertPrecondition(dimension != null); 059 Util.assertPrecondition(hierarchy.getDimension() == dimension); 060 } 061 StringBuilder buf = new StringBuilder("MemberType<"); 062 if (member != null) { 063 buf.append("member=").append(member.getUniqueName()); 064 } else if (level != null) { 065 buf.append("level=").append(level.getUniqueName()); 066 } else if (hierarchy != null) { 067 buf.append("hierarchy=").append(hierarchy.getUniqueName()); 068 } else if (dimension != null) { 069 buf.append("dimension=").append(dimension.getUniqueName()); 070 } 071 buf.append(">"); 072 this.digest = buf.toString(); 073 } 074 075 public static MemberType forDimension(Dimension dimension) { 076 return new MemberType(dimension, null, null, null); 077 } 078 079 public static MemberType forHierarchy(Hierarchy hierarchy) { 080 final Dimension dimension; 081 if (hierarchy == null) { 082 dimension = null; 083 } else { 084 dimension = hierarchy.getDimension(); 085 } 086 return new MemberType(dimension, hierarchy, null, null); 087 } 088 089 public static MemberType forLevel(Level level) { 090 final Dimension dimension; 091 final Hierarchy hierarchy; 092 if (level == null) { 093 dimension = null; 094 hierarchy = null; 095 } else { 096 dimension = level.getDimension(); 097 hierarchy = level.getHierarchy(); 098 } 099 return new MemberType(dimension, hierarchy, level, null); 100 } 101 102 public static MemberType forMember(Member member) { 103 final Dimension dimension; 104 final Hierarchy hierarchy; 105 final Level level; 106 if (member == null) { 107 dimension = null; 108 hierarchy = null; 109 level = null; 110 } else { 111 dimension = member.getDimension(); 112 hierarchy = member.getHierarchy(); 113 level = member.getLevel(); 114 } 115 return new MemberType(dimension, hierarchy, level, member); 116 } 117 118 public String toString() { 119 return digest; 120 } 121 122 public Hierarchy getHierarchy() { 123 return hierarchy; 124 } 125 126 public Level getLevel() { 127 return level; 128 } 129 130 public Member getMember() { 131 return member; 132 } 133 134 public boolean usesDimension(Dimension dimension, boolean definitely) { 135 return this.dimension == dimension 136 || (!definitely && this.dimension == null); 137 } 138 139 public boolean usesHierarchy(Hierarchy hierarchy, boolean definitely) { 140 return this.hierarchy == hierarchy 141 || (!definitely 142 && this.hierarchy == null 143 && (this.dimension == null 144 || this.dimension == hierarchy.getDimension())); 145 } 146 147 public Type getValueType() { 148 // todo: when members have more type information (double vs. integer 149 // vs. string), return better type if member != null. 150 return new ScalarType(); 151 } 152 153 public Dimension getDimension() { 154 return dimension; 155 } 156 157 public static MemberType forType(Type type) { 158 if (type instanceof MemberType) { 159 return (MemberType) type; 160 } else { 161 return new MemberType( 162 type.getDimension(), 163 type.getHierarchy(), 164 type.getLevel(), 165 null); 166 } 167 } 168 169 public Type computeCommonType(Type type, int[] conversionCount) { 170 if (type instanceof ScalarType) { 171 return getValueType().computeCommonType(type, conversionCount); 172 } 173 if (type instanceof TupleType) { 174 return type.computeCommonType(this, conversionCount); 175 } 176 if (!(type instanceof MemberType)) { 177 return null; 178 } 179 MemberType that = (MemberType) type; 180 if (this.getMember() != null 181 && this.getMember().equals(that.getMember())) 182 { 183 return this; 184 } 185 if (this.getLevel() != null 186 && this.getLevel().equals(that.getLevel())) 187 { 188 return new MemberType( 189 this.getDimension(), 190 this.getHierarchy(), 191 this.getLevel(), 192 null); 193 } 194 if (this.getHierarchy() != null 195 && this.getHierarchy().equals(that.getHierarchy())) 196 { 197 return new MemberType( 198 this.getDimension(), 199 this.getHierarchy(), 200 null, 201 null); 202 } 203 if (this.getDimension() != null 204 && this.getDimension().equals(that.getDimension())) 205 { 206 return new MemberType( 207 this.getDimension(), 208 null, 209 null, 210 null); 211 } 212 return MemberType.Unknown; 213 } 214 215 public boolean isInstance(Object value) { 216 return value instanceof Member 217 && (level == null 218 || ((Member) value).getLevel().equals(level)) 219 && (hierarchy == null 220 || ((Member) value).getHierarchy().equals(hierarchy)) 221 && (dimension == null 222 || ((Member) value).getDimension().equals(dimension)); 223 } 224 225 public int getArity() { 226 return 1; 227 } 228} 229 230// End MemberType.java