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) 2007-2012 Pentaho
008// All Rights Reserved.
009*/
010package mondrian.olap4j;
011
012import mondrian.olap.*;
013import mondrian.rolap.RolapConnection;
014import mondrian.server.Locus;
015
016import org.olap4j.OlapException;
017import org.olap4j.impl.ArrayNamedListImpl;
018import org.olap4j.impl.Named;
019import org.olap4j.metadata.Dimension;
020import org.olap4j.metadata.Hierarchy;
021import org.olap4j.metadata.Level;
022import org.olap4j.metadata.Member;
023import org.olap4j.metadata.*;
024import org.olap4j.metadata.Property;
025
026import java.util.*;
027
028/**
029 * Implementation of {@link Level}
030 * for the Mondrian OLAP engine.
031 *
032 * @author jhyde
033 * @since May 25, 2007
034 */
035class MondrianOlap4jLevel
036    extends MondrianOlap4jMetadataElement
037    implements Level, Named
038{
039    final MondrianOlap4jSchema olap4jSchema;
040    final mondrian.olap.Level level;
041
042    /**
043     * Creates a MondrianOlap4jLevel.
044     *
045     * @param olap4jSchema Schema
046     * @param level Mondrian level
047     */
048    MondrianOlap4jLevel(
049        MondrianOlap4jSchema olap4jSchema,
050        mondrian.olap.Level level)
051    {
052        this.olap4jSchema = olap4jSchema;
053        this.level = level;
054    }
055
056    public boolean equals(Object obj) {
057        return obj instanceof MondrianOlap4jLevel
058            && level.equals(((MondrianOlap4jLevel) obj).level);
059    }
060
061    public int hashCode() {
062        return level.hashCode();
063    }
064
065    public int getDepth() {
066        return level.getDepth() - getDepthOffset();
067    }
068
069    private int getDepthOffset() {
070        final Role.HierarchyAccess accessDetails =
071            olap4jSchema.olap4jCatalog.olap4jDatabaseMetaData.olap4jConnection
072                .getMondrianConnection2().getRole().getAccessDetails(
073                    level.getHierarchy());
074        if (accessDetails == null) {
075            return 0;
076        }
077        return accessDetails.getTopLevelDepth();
078    }
079
080    public Hierarchy getHierarchy() {
081        return new MondrianOlap4jHierarchy(olap4jSchema, level.getHierarchy());
082    }
083
084    public Dimension getDimension() {
085        return new MondrianOlap4jDimension(olap4jSchema, level.getDimension());
086    }
087
088    public boolean isCalculated() {
089        return false;
090    }
091
092    public Type getLevelType() {
093        if (level.isAll()) {
094            return Type.ALL;
095        }
096        switch (level.getLevelType()) {
097        case Regular:
098            return Type.REGULAR;
099        case TimeDays:
100            return Type.TIME_DAYS;
101        case TimeHalfYears:
102            return Type.TIME_HALF_YEAR;
103        case TimeHours:
104            return Type.TIME_HOURS;
105        case TimeMinutes:
106            return Type.TIME_MINUTES;
107        case TimeMonths:
108            return Type.TIME_MONTHS;
109        case TimeQuarters:
110            return Type.TIME_QUARTERS;
111        case TimeSeconds:
112            return Type.TIME_SECONDS;
113        case TimeUndefined:
114            return Type.TIME_UNDEFINED;
115        case TimeWeeks:
116            return Type.TIME_WEEKS;
117        case TimeYears:
118            return Type.TIME_YEARS;
119        case Null:
120        default:
121            throw Util.unexpected(level.getLevelType());
122        }
123    }
124
125    public NamedList<Property> getProperties() {
126        return getProperties(true);
127    }
128
129    /**
130     * Returns a list of this level's properties, optionally including standard
131     * properties that are available on every level.
132     *
133     * <p>NOTE: Not part of the olap4j API.
134     *
135     * @param includeStandard Whether to include standard properties
136     * @return List of properties
137     */
138    NamedList<Property> getProperties(boolean includeStandard) {
139        final NamedList<Property> list = new ArrayNamedListImpl<Property>() {
140            public String getName(Object property) {
141                return ((Property)property).getName();
142            }
143        };
144        // standard properties first
145        if (includeStandard) {
146            list.addAll(
147                Arrays.asList(Property.StandardMemberProperty.values()));
148            list.addAll(MondrianOlap4jProperty.MEMBER_EXTENSIONS.values());
149        }
150        // then level-specific properties
151        for (mondrian.olap.Property property : level.getProperties()) {
152            list.add(new MondrianOlap4jProperty(property));
153        }
154        return list;
155    }
156
157    public List<Member> getMembers() throws OlapException {
158        final MondrianOlap4jConnection olap4jConnection =
159            olap4jSchema.olap4jCatalog.olap4jDatabaseMetaData.olap4jConnection;
160        final RolapConnection mondrianConnection =
161            olap4jConnection.getMondrianConnection();
162        return Locus.execute(
163            mondrianConnection,
164            "Reading members of level",
165            new Locus.Action<List<Member>>() {
166                public List<Member> execute() {
167                    final mondrian.olap.SchemaReader schemaReader =
168                        mondrianConnection.getSchemaReader().withLocus();
169                    final List<mondrian.olap.Member> levelMembers =
170                        schemaReader.getLevelMembers(level, true);
171                    return new AbstractList<Member>() {
172                        public Member get(int index) {
173                            return olap4jConnection.toOlap4j(
174                                levelMembers.get(index));
175                        }
176
177                        public int size() {
178                            return levelMembers.size();
179                        }
180                    };
181                }
182            });
183    }
184
185    public String getName() {
186        return level.getName();
187    }
188
189    public String getUniqueName() {
190        return level.getUniqueName();
191    }
192
193    public String getCaption() {
194        return level.getLocalized(
195            OlapElement.LocalizedProperty.CAPTION,
196            olap4jSchema.getLocale());
197    }
198
199    public String getDescription() {
200        return level.getLocalized(
201            OlapElement.LocalizedProperty.DESCRIPTION,
202            olap4jSchema.getLocale());
203    }
204
205    public int getCardinality() {
206        return level.getApproxRowCount();
207    }
208
209    public boolean isVisible() {
210        return level.isVisible();
211    }
212
213    protected OlapElement getOlapElement() {
214        return level;
215    }
216}
217
218// End MondrianOlap4jLevel.java