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