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 level.
017 *
018 * @author jhyde
019 * @since Feb 17, 2005
020 */
021public class LevelType implements Type {
022    private final Dimension dimension;
023    private final Hierarchy hierarchy;
024    private final Level level;
025    private final String digest;
026
027    public static final LevelType Unknown = new LevelType(null, null, null);
028
029    /**
030     * Creates a type representing a level.
031     *
032     * @param dimension Dimension which values of this type must belong to, or
033     *   null if not known
034     * @param hierarchy Hierarchy which values of this type must belong to, or
035     *   null if not known
036     * @param level Level which values of this type must belong to, or null if
037     */
038    public LevelType(Dimension dimension, Hierarchy hierarchy, Level level) {
039        this.dimension = dimension;
040        this.hierarchy = hierarchy;
041        this.level = level;
042        if (level != null) {
043            Util.assertPrecondition(hierarchy != null, "hierarchy != null");
044            Util.assertPrecondition(
045                level.getHierarchy() == hierarchy,
046                "level.getHierarchy() == hierarchy");
047        }
048        if (hierarchy != null) {
049            Util.assertPrecondition(dimension != null, "dimension != null");
050            Util.assertPrecondition(
051                hierarchy.getDimension() == dimension,
052                "hierarchy.getDimension() == dimension");
053        }
054        StringBuilder buf = new StringBuilder("LevelType<");
055        if (level != null) {
056            buf.append("level=").append(level.getUniqueName());
057        } else if (hierarchy != null) {
058            buf.append("hierarchy=").append(hierarchy.getUniqueName());
059        } else if (dimension != null) {
060            buf.append("dimension=").append(dimension.getUniqueName());
061        }
062        buf.append(">");
063        this.digest = buf.toString();
064    }
065
066    public static LevelType forType(Type type) {
067        return new LevelType(
068            type.getDimension(),
069            type.getHierarchy(),
070            type.getLevel());
071    }
072
073    public static LevelType forLevel(Level level) {
074        return new LevelType(
075            level.getDimension(),
076            level.getHierarchy(),
077            level);
078    }
079
080    public boolean usesDimension(Dimension dimension, boolean definitely) {
081        return this.dimension == dimension
082            || (!definitely && this.dimension == null);
083    }
084
085    public boolean usesHierarchy(Hierarchy hierarchy, boolean definitely) {
086        return this.hierarchy == hierarchy
087            || (!definitely
088                && this.hierarchy == null
089                && (this.dimension == null
090                    || this.dimension == hierarchy.getDimension()));
091    }
092
093    public Dimension getDimension() {
094        return dimension;
095    }
096
097    public Hierarchy getHierarchy() {
098        return hierarchy;
099    }
100
101    public Level getLevel() {
102        return level;
103    }
104
105    public String toString() {
106        return digest;
107    }
108
109    public int hashCode() {
110        return digest.hashCode();
111    }
112
113    public boolean equals(Object obj) {
114        if (obj instanceof LevelType) {
115            LevelType that = (LevelType) obj;
116            return Util.equals(this.level, that.level)
117                && Util.equals(this.hierarchy, that.hierarchy)
118                && Util.equals(this.dimension, that.dimension);
119        }
120        return false;
121    }
122
123    public Type computeCommonType(Type type, int[] conversionCount) {
124        if (!(type instanceof LevelType)) {
125            return null;
126        }
127        LevelType that = (LevelType) type;
128        if (this.getLevel() != null
129            && this.getLevel().equals(that.getLevel()))
130        {
131            return this;
132        }
133        if (this.getHierarchy() != null
134            && this.getHierarchy().equals(that.getHierarchy()))
135        {
136            return new LevelType(
137                this.getDimension(),
138                this.getHierarchy(),
139                null);
140        }
141        if (this.getDimension() != null
142            && this.getDimension().equals(that.getDimension()))
143        {
144            return new LevelType(
145                this.getDimension(),
146                null,
147                null);
148        }
149        return LevelType.Unknown;
150    }
151
152    public boolean isInstance(Object value) {
153        return value instanceof Level
154            && (level == null
155                || value.equals(level))
156            && (hierarchy == null
157                || ((Level) value).getHierarchy().equals(hierarchy))
158            && (dimension == null
159                || ((Level) value).getDimension().equals(dimension));
160    }
161
162    public int getArity() {
163        return 1;
164    }
165}
166
167// End LevelType.java