001/*
002// $Id: Level.java 485 2012-01-17 06:57:57Z jhyde $
003//
004// Licensed to Julian Hyde under one or more contributor license
005// agreements. See the NOTICE file distributed with this work for
006// additional information regarding copyright ownership.
007//
008// Julian Hyde licenses this file to you under the Apache License,
009// Version 2.0 (the "License"); you may not use this file except in
010// compliance with the License. You may obtain a copy of the License at:
011//
012// http://www.apache.org/licenses/LICENSE-2.0
013//
014// Unless required by applicable law or agreed to in writing, software
015// distributed under the License is distributed on an "AS IS" BASIS,
016// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017// See the License for the specific language governing permissions and
018// limitations under the License.
019*/
020package org.olap4j.metadata;
021
022import org.olap4j.OlapException;
023
024import java.util.List;
025
026/**
027 * Group of {@link Member} objects in a {@link Hierarchy},
028 * all with the same attributes and at the same depth in the hierarchy.
029 *
030 * @author jhyde
031 * @version $Id: Level.java 485 2012-01-17 06:57:57Z jhyde $
032 * @since Aug 23, 2006
033 */
034public interface Level extends MetadataElement {
035    /**
036     * Returns the depth of this <code>Level</code>.
037     *
038     * <p>Note #1: In an access-controlled context, the first visible level of
039     * a hierarchy may not have a depth of 0.</p>
040     *
041     * <p>Note #2: In a parent-child hierarchy, the depth of a member (as
042     * returned by may not be the same as the depth of its level.
043     *
044     * @return depth of this level
045     */
046    int getDepth();
047
048    /**
049     * Returns the {@link Hierarchy} this <code>Level</code> belongs to.
050     *
051     * @return hierarchy this level belongs to
052     */
053    Hierarchy getHierarchy();
054
055    /**
056     * Returns the Dimension this <code>Level</code> belongs to.
057     * (Always equivalent to <code>getHierarchy().getDimension()</code>.)
058     *
059     * @return dimension this level belongs to
060     */
061    Dimension getDimension();
062
063    /**
064     * Returns the type of this <code>Level</code>.
065     *
066     * @return level type
067     */
068    Level.Type getLevelType();
069
070    /**
071     * Returns whether the level is calculated.
072     *
073     * @return Whether this level is calculated
074     */
075    boolean isCalculated();
076
077    /**
078     * Returns a list of definitions for the properties available to members
079     * of this <code>Level</code>.
080     *
081     * <p>The caller should assume that the list is immutable;
082     * if the caller modifies the list, behavior is undefined.</p>
083     *
084     * @see org.olap4j.OlapDatabaseMetaData#getProperties
085     *
086     * @return properties of this Level
087     */
088    NamedList<Property> getProperties();
089
090    /**
091     * Returns a list of {@link Member} objects that belong to this Level.
092     *
093     * <p>The list does not include calculated members.</p>
094     *
095     * <p>Some levels have a very many members. In this case, calling this
096     * method may be expensive in space and/or time and is not recommended.</p>
097     *
098     * <p>If you need to include calculated members, or if you need to query
099     * specific members or subsets of members in a level, consider instead
100     * generating and executing an MDX query with a single axis. MDX functions
101     * {@code AddCalculatedMembers}, {@code Filter} and {@code Order} are
102     * especially useful. For example,
103     *
104     * <pre>with member [Measures].[Zero] as 0
105     * select AddCalculatedMembers([Time].[Month].Members) on 0
106     * from [Sales]
107     * where [Measures].[Zero]</pre>
108     *
109     * returns the {@code [Month]} level including calculated members. The
110     * {@code [Measures].[Zero]} calculated member saves the OLAP server the
111     * effort of retrieving cell values.</p>
112     *
113     * <p>The members of a level do not have unique names, so unlike
114     * {@link Hierarchy#getRootMembers()} and
115     * {@link Member#getChildMembers()} the result type
116     * is a {@link List} not a {@link NamedList}.
117     *
118     * @return List of members in this Level
119     *
120     * @throws OlapException if database error occurs
121     */
122    List<Member> getMembers() throws OlapException;
123
124    /**
125     * Returns the number of members in this Level.
126     *
127     * @return number of members
128     */
129    int getCardinality();
130
131    /**
132     * Enumeration of the types of a {@link Level}.
133     *
134     * <p>Several of the values are defined by OLE DB for OLAP and/or XML/A,
135     * sans the "MDLEVEL_TYPE_" prefix to their name. For example,
136     * {@link #GEO_CONTINENT} corresponds to
137     * the value <code>MDLEVEL_TYPE_GEO_CONTINENT</code> for the
138     * <code>LEVEL_TYPE</code> property in the <code>MDSCHEMA_LEVELS</code>
139     * schema rowset.
140     *
141     * <p>Some of the values are specified by OLE DB for OLAP:
142     * <ul>
143     * <li>MDLEVEL_TYPE_REGULAR         (0x0000)
144     * <li>MDLEVEL_TYPE_ALL             (0x0001)
145     * <li>MDLEVEL_TYPE_TIME_YEARS      (0x0014)
146     * <li>MDLEVEL_TYPE_TIME_HALF_YEAR  (0x0024)
147     * <li>MDLEVEL_TYPE_TIME_QUARTERS   (0x0044)
148     * <li>MDLEVEL_TYPE_TIME_MONTHS     (0x0084)
149     * <li>MDLEVEL_TYPE_TIME_WEEKS      (0x0104)
150     * <li>MDLEVEL_TYPE_TIME_DAYS       (0x0204)
151     * <li>MDLEVEL_TYPE_TIME_HOURS      (0x0304)
152     * <li>MDLEVEL_TYPE_TIME_MINUTES    (0x0404)
153     * <li>MDLEVEL_TYPE_TIME_SECONDS    (0x0804)
154     * <li>MDLEVEL_TYPE_TIME_UNDEFINED  (0x1004)
155     * </ul>
156     *
157     * Some of the OLE DB for OLAP values are as flags, and do not become
158     * values of the enumeration:
159     * <ul>
160     * <li>MDLEVEL_TYPE_UNKNOWN (0x0000) signals that no other flags are set.
161     *     Use {@link #REGULAR}
162     * <li>MDLEVEL_TYPE_CALCULATED (0x0002) indicates that the level is
163     *     calculated. Use {@link Level#isCalculated}.
164     * <li>MDLEVEL_TYPE_TIME (0x0004) indicates that the level is time-related.
165     *     Use {@link #isTime}.
166     * <li>MDLEVEL_TYPE_RESERVED1 (0x0008) is reserved for future use.
167     * </ul>
168     *
169     * <p>Some of the values are specified by XMLA:
170     * <ul>
171     * <li>MDLEVEL_TYPE_GEO_CONTINENT (0x2001)
172     * <li>MDLEVEL_TYPE_GEO_REGION (0x2002)
173     * <li>MDLEVEL_TYPE_GEO_COUNTRY (0x2003)
174     * <li>MDLEVEL_TYPE_GEO_STATE_OR_PROVINCE (0x2004)
175     * <li>MDLEVEL_TYPE_GEO_COUNTY (0x2005)
176     * <li>MDLEVEL_TYPE_GEO_CITY (0x2006)
177     * <li>MDLEVEL_TYPE_GEO_POSTALCODE (0x2007)
178     * <li>MDLEVEL_TYPE_GEO_POINT (0x2008)
179     * <li>MDLEVEL_TYPE_ORG_UNIT (0x1011)
180     * <li>MDLEVEL_TYPE_BOM_RESOURCE (0x1012)
181     * <li>MDLEVEL_TYPE_QUANTITATIVE (0x1013)
182     * <li>MDLEVEL_TYPE_ACCOUNT (0x1014)
183     * <li>MDLEVEL_TYPE_CUSTOMER (0x1021)
184     * <li>MDLEVEL_TYPE_CUSTOMER_GROUP (0x1022)
185     * <li>MDLEVEL_TYPE_CUSTOMER_HOUSEHOLD (0x1023)
186     * <li>MDLEVEL_TYPE_PRODUCT (0x1031)
187     * <li>MDLEVEL_TYPE_PRODUCT_GROUP (0x1032)
188     * <li>MDLEVEL_TYPE_SCENARIO (0x1015)
189     * <li>MDLEVEL_TYPE_UTILITY (0x1016)
190     * <li>MDLEVEL_TYPE_PERSON (0x1041)
191     * <li>MDLEVEL_TYPE_COMPANY (0x1042)
192     * <li>MDLEVEL_TYPE_CURRENCY_SOURCE (0x1051)
193     * <li>MDLEVEL_TYPE_CURRENCY_DESTINATION (0x1052)
194     * <li>MDLEVEL_TYPE_CHANNEL (0x1061)
195     * <li>MDLEVEL_TYPE_REPRESENTATIVE (0x1062)
196     * <li>MDLEVEL_TYPE_PROMOTION (0x1071)
197     * </ul>
198     *
199     * @see Level#getLevelType
200     * @see org.olap4j.OlapDatabaseMetaData#getLevels
201     */
202    public enum Type implements XmlaConstant {
203
204        /**
205         * Indicates that the level is not related to time.
206         */
207        REGULAR(0x0000),
208
209        /**
210         * Indicates that the level contains the 'all' member of its hierarchy.
211         */
212        ALL(0x0001),
213
214        /**
215         * Indicates that a level holds the null member. Does not correspond to
216         * an XMLA or OLE DB value.
217         */
218        NULL(-1),
219
220        /**
221         * Indicates that a level refers to years.
222         * It must be used in a dimension whose type is
223         * {@link org.olap4j.metadata.Dimension.Type#TIME}.
224         */
225        TIME_YEARS(0x0014),
226
227        /**
228         * Indicates that a level refers to half years.
229         * It must be used in a dimension whose type is
230         * {@link org.olap4j.metadata.Dimension.Type#TIME}.
231         */
232        TIME_HALF_YEAR(0x0024),
233
234        /**
235         * Indicates that a level refers to quarters.
236         * It must be used in a dimension whose type is
237         * {@link org.olap4j.metadata.Dimension.Type#TIME}.
238         */
239        TIME_QUARTERS(0x0044),
240
241        /**
242         * Indicates that a level refers to months.
243         * It must be used in a dimension whose type is
244         * {@link org.olap4j.metadata.Dimension.Type#TIME}.
245         */
246        TIME_MONTHS(0x0084),
247
248        /**
249         * Indicates that a level refers to weeks.
250         * It must be used in a dimension whose type is
251         * {@link org.olap4j.metadata.Dimension.Type#TIME}.
252         */
253        TIME_WEEKS(0x0104),
254
255        /**
256         * Indicates that a level refers to days.
257         * It must be used in a dimension whose type is
258         * {@link org.olap4j.metadata.Dimension.Type#TIME}.
259         */
260        TIME_DAYS(0x0204),
261
262        /**
263         * Indicates that a level refers to hours.
264         * It must be used in a dimension whose type is
265         * {@link org.olap4j.metadata.Dimension.Type#TIME}.
266         */
267        TIME_HOURS(0x0304),
268
269        /**
270         * Indicates that a level refers to minutes.
271         * It must be used in a dimension whose type is
272         * {@link org.olap4j.metadata.Dimension.Type#TIME}.
273         */
274        TIME_MINUTES(0x0404),
275
276        /**
277         * Indicates that a level refers to seconds.
278         * It must be used in a dimension whose type is
279         * {@link org.olap4j.metadata.Dimension.Type#TIME}.
280         */
281        TIME_SECONDS(0x0804),
282
283        /**
284         * Indicates that a level refers to days.
285         * It must be used in a dimension whose type is
286         * {@link org.olap4j.metadata.Dimension.Type#TIME}.
287         */
288        TIME_UNDEFINED(0x1004),
289
290        GEO_CONTINENT(0x2001),
291        GEO_REGION(0x2002),
292        GEO_COUNTRY(0x2003),
293        GEO_STATE_OR_PROVINCE(0x2004),
294        GEO_COUNTY(0x2005),
295        GEO_CITY(0x2006),
296        GEO_POSTALCODE(0x2007),
297        GEO_POINT(0x2008),
298        ORG_UNIT(0x1011),
299        BOM_RESOURCE(0x1012),
300        QUANTITATIVE(0x1013),
301        ACCOUNT(0x1014),
302        CUSTOMER(0x1021),
303        CUSTOMER_GROUP(0x1022),
304        CUSTOMER_HOUSEHOLD(0x1023),
305        PRODUCT(0x1031),
306        PRODUCT_GROUP(0x1032),
307        SCENARIO(0x1015),
308        UTILITY(0x1016),
309        PERSON(0x1041),
310        COMPANY(0x1042),
311        CURRENCY_SOURCE(0x1051),
312        CURRENCY_DESTINATION(0x1052),
313        CHANNEL(0x1061),
314        REPRESENTATIVE(0x1062),
315        PROMOTION(0x1071);
316
317        private final int xmlaOrdinal;
318
319        private static final Dictionary<Type> DICTIONARY =
320            DictionaryImpl.forClass(Type.class);
321
322        /**
323         * Per {@link org.olap4j.metadata.XmlaConstant}, returns a dictionary
324         * of all values of this enumeration.
325         *
326         * @return Dictionary of all values
327         */
328        public static Dictionary<Type> getDictionary() {
329            return DICTIONARY;
330        }
331
332        /**
333         * Creates a level type.
334         *
335         * @param xmlaOrdinal Ordinal code in XMLA or OLE DB for OLAP
336         * specification
337         */
338        private Type(int xmlaOrdinal) {
339            this.xmlaOrdinal = xmlaOrdinal;
340        }
341
342        public String xmlaName() {
343            return "MDLEVEL_TYPE_" + name();
344        }
345
346        public String getDescription() {
347            return "";
348        }
349
350        public int xmlaOrdinal() {
351            return xmlaOrdinal;
352        }
353
354        /**
355         * Returns whether this is a time-related level
356         * ({@link #TIME_YEARS},
357         * {@link #TIME_HALF_YEAR},
358         * {@link #TIME_QUARTERS},
359         * {@link #TIME_MONTHS},
360         * {@link #TIME_WEEKS},
361         * {@link #TIME_DAYS},
362         * {@link #TIME_HOURS},
363         * {@link #TIME_MINUTES},
364         * {@link #TIME_SECONDS},
365         * {@link #TIME_UNDEFINED}).
366         *
367         * @return whether this is a time-related level
368         */
369        public boolean isTime() {
370            switch (this) {
371            case TIME_YEARS:
372            case TIME_HALF_YEAR:
373            case TIME_QUARTERS:
374            case TIME_MONTHS:
375            case TIME_WEEKS:
376            case TIME_DAYS:
377            case TIME_HOURS:
378            case TIME_MINUTES:
379            case TIME_SECONDS:
380            case TIME_UNDEFINED:
381                return true;
382            default:
383                return false;
384            }
385        }
386    }
387}
388
389// End Level.java