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    */
020    package org.olap4j.metadata;
021    
022    import org.olap4j.OlapException;
023    
024    import 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     */
034    public 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