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