001 /* 002 // $Id: //open/mondrian/src/main/mondrian/olap/type/MemberType.java#11 $ 003 // This software is subject to the terms of the Common Public License 004 // Agreement, available at the following URL: 005 // http://www.opensource.org/licenses/cpl.html. 006 // Copyright (C) 2005-2008 Julian Hyde 007 // All Rights Reserved. 008 // You must accept the terms of that agreement to use this software. 009 */ 010 package mondrian.olap.type; 011 012 import mondrian.olap.*; 013 014 /** 015 * The type of an expression which represents a member. 016 * 017 * @author jhyde 018 * @since Feb 17, 2005 019 * @version $Id: //open/mondrian/src/main/mondrian/olap/type/MemberType.java#11 $ 020 */ 021 public 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 this.dimension = dimension; 045 this.hierarchy = hierarchy; 046 this.level = level; 047 this.member = member; 048 if (member != null) { 049 Util.assertPrecondition(level != null); 050 Util.assertPrecondition(member.getLevel() == level); 051 } 052 if (level != null) { 053 Util.assertPrecondition(hierarchy != null); 054 Util.assertPrecondition(level.getHierarchy() == hierarchy); 055 } 056 if (hierarchy != null) { 057 Util.assertPrecondition(dimension != null); 058 Util.assertPrecondition(hierarchy.getDimension() == dimension); 059 } 060 StringBuilder buf = new StringBuilder("MemberType<"); 061 if (member != null) { 062 buf.append("member=").append(member.getUniqueName()); 063 } else if (level != null) { 064 buf.append("level=").append(level.getUniqueName()); 065 } else if (hierarchy != null) { 066 buf.append("hierarchy=").append(hierarchy.getUniqueName()); 067 } else if (dimension != null) { 068 buf.append("dimension=").append(dimension.getUniqueName()); 069 } 070 buf.append(">"); 071 this.digest = buf.toString(); 072 } 073 074 public static MemberType forDimension(Dimension dimension) { 075 return new MemberType(dimension, null, null, null); 076 } 077 078 public static MemberType forHierarchy(Hierarchy hierarchy) { 079 final Dimension dimension; 080 if (hierarchy == null) { 081 dimension = null; 082 } else { 083 dimension = hierarchy.getDimension(); 084 } 085 return new MemberType(dimension, hierarchy, null, null); 086 } 087 088 public static MemberType forLevel(Level level) { 089 final Dimension dimension; 090 final Hierarchy hierarchy; 091 if (level == null) { 092 dimension = null; 093 hierarchy = null; 094 } else { 095 dimension = level.getDimension(); 096 hierarchy = level.getHierarchy(); 097 } 098 return new MemberType(dimension, hierarchy, level, null); 099 } 100 101 public static MemberType forMember(Member member) { 102 final Dimension dimension; 103 final Hierarchy hierarchy; 104 final Level level; 105 if (member == null) { 106 dimension = null; 107 hierarchy = null; 108 level = null; 109 } else { 110 dimension = member.getDimension(); 111 hierarchy = member.getHierarchy(); 112 level = member.getLevel(); 113 } 114 return new MemberType(dimension, hierarchy, level, member); 115 } 116 117 public String toString() { 118 return digest; 119 } 120 121 public Hierarchy getHierarchy() { 122 return hierarchy; 123 } 124 125 public Level getLevel() { 126 return level; 127 } 128 129 public Member getMember() { 130 return member; 131 } 132 133 public boolean usesDimension(Dimension dimension, boolean definitely) { 134 return this.dimension == dimension || 135 (!definitely && this.dimension == null); 136 } 137 138 public Type getValueType() { 139 // todo: when members have more type information (double vs. integer 140 // vs. string), return better type if member != null. 141 return new ScalarType(); 142 } 143 144 public Dimension getDimension() { 145 return dimension; 146 } 147 148 public static MemberType forType(Type type) { 149 if (type instanceof MemberType) { 150 return (MemberType) type; 151 } else { 152 return new MemberType( 153 type.getDimension(), 154 type.getHierarchy(), 155 type.getLevel(), 156 null); 157 } 158 } 159 160 public Type computeCommonType(Type type, int[] conversionCount) { 161 if (type instanceof ScalarType) { 162 return getValueType().computeCommonType(type, conversionCount); 163 } 164 if (type instanceof TupleType) { 165 return type.computeCommonType(this,conversionCount); 166 } 167 if (!(type instanceof MemberType)) { 168 return null; 169 } 170 MemberType that = (MemberType) type; 171 if (this.getMember() != null 172 && this.getMember().equals(that.getMember())) { 173 return this; 174 } 175 if (this.getLevel() != null 176 && this.getLevel().equals(that.getLevel())) { 177 return new MemberType( 178 this.getDimension(), 179 this.getHierarchy(), 180 this.getLevel(), 181 null); 182 } 183 if (this.getHierarchy() != null 184 && this.getHierarchy().equals(that.getHierarchy())) { 185 return new MemberType( 186 this.getDimension(), 187 this.getHierarchy(), 188 null, 189 null); 190 } 191 if (this.getDimension() != null 192 && this.getDimension().equals(that.getDimension())) { 193 return new MemberType( 194 this.getDimension(), 195 null, 196 null, 197 null); 198 } 199 return MemberType.Unknown; 200 } 201 } 202 203 // End MemberType.java