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