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