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