001 /*
002 // $Id: Property.java 124 2008-11-02 07:34:39Z jhyde $
003 // This software is subject to the terms of the Common Public License
004 // Agreement, available at the following URL:
005 // http://www.opensource.org/licenses/cpl.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 java.util.*;
013
014 /**
015 * Definition of a property of a {@link Member} or
016 * {@link org.olap4j.Cell}.
017 *
018 * @author jhyde
019 * @version $Id: Property.java 124 2008-11-02 07:34:39Z jhyde $
020 * @since Aug 23, 2006
021 */
022 public interface Property extends MetadataElement {
023 /**
024 * Returns the datatype of this Property.
025 *
026 * @return datatype of this Property
027 */
028 Datatype getDatatype();
029
030 /**
031 * Returns a set of flags which describe the type of this Property.
032 *
033 * @return type of this Property
034 */
035 Set<TypeFlag> getType();
036
037 /**
038 * Returns the content type of this Property.
039 *
040 * @return content type
041 */
042 ContentType getContentType();
043
044 /**
045 * Enumeration of aspects of the type of a Property. In particular, whether
046 * it belongs to a member or a cell.
047 *
048 * <p>The values are as specified by XMLA for the PROPERTY_TYPE attribute
049 * of the MDSCHEMA_PROPERTIES data set.
050 * For example, XMLA specifies that the value 9 (0x1 | 0x8) means that a
051 * property belongs to a member and is a binary large object (BLOB).
052 * In this case, {@link Property#getType} will return the {@link Set}
053 * {{@link #MEMBER}, {@link #BLOB}}.
054 */
055 enum TypeFlag {
056 /**
057 * Identifies a property of a member. This property can be used in the
058 * DIMENSION PROPERTIES clause of the SELECT statement.
059 */
060 MEMBER(1),
061
062 /**
063 * Identifies a property of a cell. This property can be used in the
064 * CELL PROPERTIES clause that occurs at the end of the SELECT
065 * statement.
066 */
067 CELL(2),
068
069 /**
070 * Identifies an internal property.
071 */
072 SYSTEM(4),
073
074 /**
075 * Identifies a property which contains a binary large object (blob).
076 */
077 BLOB(8);
078
079 public final int xmlaOrdinal;
080 private static final Map<Integer, TypeFlag> xmlaMap =
081 new HashMap<Integer, TypeFlag>();
082
083 static {
084 for (TypeFlag typeFlag : values()) {
085 xmlaMap.put(typeFlag.xmlaOrdinal, typeFlag);
086 }
087 }
088
089 private static final Set<TypeFlag> CELL_TYPE_FLAG =
090 Collections.unmodifiableSet(EnumSet.of(TypeFlag.CELL));
091 private static final Set<TypeFlag> MEMBER_TYPE_FLAG =
092 Collections.unmodifiableSet(EnumSet.of(TypeFlag.MEMBER));
093
094 private TypeFlag(int xmlaOrdinal) {
095 this.xmlaOrdinal = xmlaOrdinal;
096 }
097
098 /**
099 * Looks up a TypeFlag by its XMLA ordinal.
100 *
101 * @param xmlaOrdinal Ordinal of a TypeFlag according to the XMLA
102 * specification.
103 *
104 * @return TypeFlag with the given ordinal, or null if there is no
105 * such TypeFlag
106 */
107 public static TypeFlag forXmlaOrdinal(int xmlaOrdinal) {
108 return xmlaMap.get(xmlaOrdinal);
109 }
110
111 /**
112 * Creates a set of TypeFlag values by parsing a mask.
113 *
114 * <p>For example, <code>forMask(9)</code> returns the set
115 * {{@link #MEMBER}, {@link #BLOB}} because 9 = MEMBER (1) | BLOB (8).
116 *
117 * @param xmlaOrdinalMask Bit mask
118 * @return Set of TypeFlag values
119 */
120 public static Set<TypeFlag> forMask(int xmlaOrdinalMask) {
121 switch (xmlaOrdinalMask) {
122 // Optimize common cases {MEMBER} and {CELL}.
123 case 1:
124 return MEMBER_TYPE_FLAG;
125 case 2:
126 return CELL_TYPE_FLAG;
127 default:
128 Set<TypeFlag> type =
129 EnumSet.noneOf(TypeFlag.class);
130 for (TypeFlag typeFlag : values()) {
131 if ((xmlaOrdinalMask & typeFlag.xmlaOrdinal) != 0) {
132 type.add(typeFlag);
133 }
134 }
135 return type;
136 }
137 }
138 }
139
140 /**
141 * Enumeration of the system properties available for every {@link Member}.
142 *
143 * <p>The following properties are mandatory for members:<ul>
144 * <li>{@link #CATALOG_NAME}</li>
145 * <li>{@link #SCHEMA_NAME}</li>
146 * <li>{@link #CUBE_NAME}</li>
147 * <li>{@link #DIMENSION_UNIQUE_NAME}</li>
148 * <li>{@link #HIERARCHY_UNIQUE_NAME}</li>
149 * <li>{@link #LEVEL_UNIQUE_NAME}</li>
150 * <li>{@link #LEVEL_NUMBER}</li>
151 * <li>{@link #MEMBER_UNIQUE_NAME}</li>
152 * <li>{@link #MEMBER_NAME}</li>
153 * <li>{@link #MEMBER_TYPE}</li>
154 * <li>{@link #MEMBER_GUID}</li>
155 * <li>{@link #MEMBER_CAPTION}</li>
156 * <li>{@link #MEMBER_ORDINAL}</li>
157 * <li>{@link #CHILDREN_CARDINALITY}</li>
158 * <li>{@link #PARENT_LEVEL}</li>
159 * <li>{@link #PARENT_UNIQUE_NAME}</li>
160 * <li>{@link #PARENT_COUNT}</li>
161 * <li>{@link #DESCRIPTION}</li>
162 * </ul>
163 */
164 enum StandardMemberProperty implements Property {
165
166 /**
167 * Definition of the property which
168 * holds the name of the current catalog.
169 */
170 CATALOG_NAME(Datatype.STRING, 10, false, "Optional. The name of the catalog to which this member belongs. NULL if the provider does not support catalogs."),
171
172 /**
173 * Definition of the property which
174 * holds the name of the current schema.
175 */
176 SCHEMA_NAME(Datatype.STRING, 11, false, "Optional. The name of the schema to which this member belongs. NULL if the provider does not support schemas."),
177
178 /**
179 * Definition of the property which
180 * holds the name of the current cube.
181 */
182 CUBE_NAME(Datatype.STRING, 12, false, "Required. Name of the cube to which this member belongs."),
183
184 /**
185 * Definition of the property which
186 * holds the unique name of the current dimension.
187 */
188 DIMENSION_UNIQUE_NAME(Datatype.STRING, 13, false, "Required. Unique name of the dimension to which this member belongs. For providers that generate unique names by qualification, each component of this name is delimited."),
189
190 /**
191 * Definition of the property which
192 * holds the unique name of the current hierarchy.
193 */
194 HIERARCHY_UNIQUE_NAME(Datatype.STRING, 14, false, "Required. Unique name of the hierarchy. If the member belongs to more than one hierarchy, there is one row for each hierarchy to which it belongs. For providers that generate unique names by qualification, each component of this name is delimited."),
195
196 /**
197 * Definition of the property which
198 * holds the unique name of the current level.
199 */
200 LEVEL_UNIQUE_NAME(Datatype.STRING, 15, false, "Required. Unique name of the level to which the member belongs. For providers that generate unique names by qualification, each component of this name is delimited."),
201
202 /**
203 * Definition of the property which
204 * holds the ordinal of the current level.
205 */
206 LEVEL_NUMBER(Datatype.UNSIGNED_INTEGER, 16, false, "Required. The distance of the member from the root of the hierarchy. The root level is zero."),
207
208 /**
209 * Definition of the property which
210 * holds the ordinal of the current member.
211 */
212 MEMBER_ORDINAL(Datatype.UNSIGNED_INTEGER, 17, false, "Required. Ordinal number of the member. Sort rank of the member when members of this dimension are sorted in their natural sort order. If providers do not have the concept of natural ordering, this should be the rank when sorted by MEMBER_NAME."),
213
214 /**
215 * Definition of the property which
216 * holds the name of the current member.
217 */
218 MEMBER_NAME(Datatype.STRING, 18, false, "Required. Name of the member."),
219
220 /**
221 * Definition of the property which
222 * holds the unique name of the current member.
223 */
224 MEMBER_UNIQUE_NAME(Datatype.STRING, 19, false, "Required. Unique name of the member. For providers that generate unique names by qualification, each component of this name is delimited."),
225
226 /**
227 * Definition of the property which
228 * holds the type of the member.
229 */
230 MEMBER_TYPE(Datatype.STRING, 20, false, "Required. Type of the member. Can be one of the following values: MDMEMBER_Datatype.TYPE_REGULAR, MDMEMBER_Datatype.TYPE_ALL, MDMEMBER_Datatype.TYPE_FORMULA, MDMEMBER_Datatype.TYPE_MEASURE, MDMEMBER_Datatype.TYPE_UNKNOWN. MDMEMBER_Datatype.TYPE_FORMULA takes precedence over MDMEMBER_Datatype.TYPE_MEASURE. Therefore, if there is a formula (calculated) member on the Measures dimension, it is listed as MDMEMBER_Datatype.TYPE_FORMULA."),
231
232 /**
233 * Definition of the property which
234 * holds the GUID of the member
235 */
236 MEMBER_GUID(Datatype.STRING, 21, false, "Optional. Member GUID. NULL if no GUID exists."),
237
238 /**
239 * Definition of the property which
240 * holds the label or caption associated with the member, or the
241 * member's name if no caption is defined.
242 */
243 MEMBER_CAPTION(Datatype.STRING, 22, false, "Required. A label or caption associated with the member. Used primarily for display purposes. If a caption does not exist, MEMBER_NAME is returned."),
244
245 /**
246 * Definition of the property which holds the
247 * number of children this member has.
248 */
249 CHILDREN_CARDINALITY(Datatype.UNSIGNED_INTEGER, 23, false, "Required. Number of children that the member has. This can be an estimate, so consumers should not rely on this to be the exact count. Providers should return the best estimate possible."),
250
251 /**
252 * Definition of the property which holds the
253 * distance from the root of the hierarchy of this member's parent.
254 */
255 PARENT_LEVEL(Datatype.UNSIGNED_INTEGER, 24, false, "Required. The distance of the member's parent from the root level of the hierarchy. The root level is zero."),
256
257 /**
258 * Definition of the property which holds the
259 * Name of the current catalog.
260 */
261 PARENT_UNIQUE_NAME(Datatype.STRING, 25, false, "Required. Unique name of the member's parent. NULL is returned for any members at the root level. For providers that generate unique names by qualification, each component of this name is delimited."),
262
263 /**
264 * Definition of the property which holds the
265 * number of parents that this member has. Generally 1, or 0 for root members.
266 */
267 PARENT_COUNT(Datatype.UNSIGNED_INTEGER, 26, false, "Required. Number of parents that this member has."),
268
269 /**
270 * Definition of the property which holds the
271 * description of this member.
272 */
273 DESCRIPTION(Datatype.STRING, 27, false, "Optional. A human-readable description of the member."),
274
275 /**
276 * Definition of the internal property which holds the
277 * name of the system property which determines whether to show a member
278 * (especially a measure or calculated member) in a user interface such as
279 * JPivot.
280 */
281 $visible(Datatype.BOOLEAN, 28, true, null),
282
283 /**
284 * Definition of the internal property which holds the
285 * value of the member key in the original data type. MEMBER_KEY is for
286 * backward-compatibility. MEMBER_KEY has the same value as KEY0 for
287 * non-composite keys, and MEMBER_KEY property is null for composite
288 * keys.
289 */
290 MEMBER_KEY(Datatype.VARIANT, 29, true, "Optional. The value of the member key. Null for composite keys."),
291
292 /**
293 * Definition of the boolean property that indicates whether
294 * a member is a placeholder member for an empty position in a
295 * dimension hierarchy.
296 */
297 IS_PLACEHOLDERMEMBER(Datatype.BOOLEAN, 30, false, "Required. Whether the member is a placeholder member for an empty position in a dimension hierarchy."),
298
299 /**
300 * Definition of the property that indicates whether the member is a
301 * data member.
302 */
303 IS_DATAMEMBER(Datatype.BOOLEAN, 31, false, "Required. whether the member is a data member"),
304
305 /**
306 * Definition of the property which
307 * holds the level depth of a member.
308 *
309 * <p>Caution: Level depth of members in parent-child hierarchy isn't from their levels.
310 * It's calculated from the underlying data dynamically.
311 */
312 DEPTH(Datatype.UNSIGNED_INTEGER, 43, true, "The level depth of a member"),
313
314 /**
315 * Definition of the property which
316 * holds the DISPLAY_INFO required by XML/A.
317 *
318 * <p>Caution: This property's value is calculated based on a specified MDX query, so its value is dynamic at runtime.
319 */
320 DISPLAY_INFO(Datatype.UNSIGNED_INTEGER, 44, false, "Display instruction of a member for XML/A"),
321
322 /**
323 * Definition of the property which
324 * holds the value of a cell. Is usually numeric (since most measures are
325 * numeric) but is occasionally another type.
326 */
327 VALUE(Datatype.VARIANT, 41, false, "The unformatted value of the cell.");
328
329 private final Datatype type;
330 private final String description;
331 private final boolean internal;
332
333 private StandardMemberProperty(
334 Datatype type,
335 int ordinal,
336 boolean internal,
337 String description)
338 {
339 // assert ordinal == ordinal();
340 this.internal = internal;
341 this.type = type;
342 this.description = description;
343 }
344
345 public String getName() {
346 return name();
347 }
348
349 public String getUniqueName() {
350 return name();
351 }
352
353 public String getDescription(Locale locale) {
354 return description;
355 }
356
357 public String getCaption(Locale locale) {
358 return name();
359 }
360
361 public Datatype getDatatype() {
362 return type;
363 }
364
365 public Set<TypeFlag> getType() {
366 return TypeFlag.forMask(TypeFlag.MEMBER.xmlaOrdinal);
367 }
368
369 public ContentType getContentType() {
370 return ContentType.REGULAR;
371 }
372
373 public boolean isInternal() {
374 return internal;
375 }
376 }
377
378 /**
379 * Enumeration of the system properties available for every
380 * {@link org.olap4j.Cell}.
381 *
382 * <p>The following propertiess are mandatory for cells:<ul>
383 * <li>{@link #BACK_COLOR}</li>
384 * <li>{@link #CELL_EVALUATION_LIST}</li>
385 * <li>{@link #CELL_ORDINAL}</li>
386 * <li>{@link #FORE_COLOR}</li>
387 * <li>{@link #FONT_NAME}</li>
388 * <li>{@link #FONT_SIZE}</li>
389 * <li>{@link #FONT_FLAGS}</li>
390 * <li>{@link #FORMAT_STRING}</li>
391 * <li>{@link #FORMATTED_VALUE}</li>
392 * <li>{@link #NON_EMPTY_BEHAVIOR}</li>
393 * <li>{@link #SOLVE_ORDER}</li>
394 * <li>{@link #VALUE}</li>
395 * </ul>
396 */
397 enum StandardCellProperty implements Property {
398 BACK_COLOR(Datatype.STRING, 30, false, "The background color for displaying the VALUE or FORMATTED_VALUE property. For more information, see FORE_COLOR and BACK_COLOR Contents."),
399
400 CELL_EVALUATION_LIST(Datatype.STRING, 31, false, "The semicolon-delimited list of evaluated formulas applicable to the cell, in order from lowest to highest solve order. For more information about solve order, see Understanding Pass Order and Solve Order"),
401
402 CELL_ORDINAL(Datatype.UNSIGNED_INTEGER, 32, false, "The ordinal number of the cell in the dataset."),
403
404 FORE_COLOR(Datatype.STRING, 33, false, "The foreground color for displaying the VALUE or FORMATTED_VALUE property. For more information, see FORE_COLOR and BACK_COLOR Contents."),
405
406 FONT_NAME(Datatype.STRING, 34, false, "The font to be used to display the VALUE or FORMATTED_VALUE property."),
407
408 FONT_SIZE(Datatype.STRING, 35, false, "Font size to be used to display the VALUE or FORMATTED_VALUE property."),
409
410 FONT_FLAGS(Datatype.UNSIGNED_INTEGER, 36, false, "The bitmask detailing effects on the font. The value is the result of a bitwise OR operation of one or more of the following constants: MDFF_BOLD = 1, MDFF_ITALIC = 2, MDFF_UNDERLINE = 4, MDFF_STRIKEOUT = 8. For example, the value 5 represents the combination of bold (MDFF_BOLD) and underline (MDFF_UNDERLINE) font effects."),
411
412 /**
413 * Definition of the property which
414 * holds the formatted value of a cell.
415 */
416 FORMATTED_VALUE(Datatype.STRING, 37, false, "The character string that represents a formatted display of the VALUE property."),
417
418 /**
419 * Definition of the property which
420 * holds the format string used to format cell values.
421 */
422 FORMAT_STRING(Datatype.STRING, 38, false, "The format string used to create the FORMATTED_VALUE property value. For more information, see FORMAT_STRING Contents."),
423
424 NON_EMPTY_BEHAVIOR(Datatype.STRING, 39, false, "The measure used to determine the behavior of calculated members when resolving empty cells."),
425
426 /**
427 * Definition of the property which
428 * determines the solve order of a calculated member with respect to other
429 * calculated members.
430 */
431 SOLVE_ORDER(Datatype.INTEGER, 40, false, "The solve order of the cell."),
432
433 /**
434 * Definition of the property which
435 * holds the value of a cell. Is usually numeric (since most measures are
436 * numeric) but is occasionally another type.
437 */
438 VALUE(Datatype.VARIANT, 41, false, "The unformatted value of the cell."),
439
440 /**
441 * Definition of the property which
442 * holds the datatype of a cell. Valid values are "String",
443 * "Numeric", "Integer". The property's value derives from the
444 * "datatype" attribute of the "Measure" element; if the datatype attribute
445 * is not specified, the datatype is "Numeric" by default, except measures
446 * whose aggregator is "Count", whose datatype is "Integer".
447 */
448 DATATYPE(Datatype.STRING, 42, false, "The datatype of the cell.");
449
450 /**
451 * The datatype of the property.
452 */
453 private final Datatype type;
454 private final String description;
455 private final boolean internal;
456
457 private StandardCellProperty(
458 Datatype type,
459 int ordinal,
460 boolean internal,
461 String description)
462 {
463 // assert ordinal == ordinal();
464 this.type = type;
465 this.internal = internal;
466 this.description = description;
467 }
468
469 public Datatype getDatatype() {
470 return type;
471 }
472
473 public Set<TypeFlag> getType() {
474 return TypeFlag.forMask(TypeFlag.CELL.xmlaOrdinal);
475 }
476
477 public String getName() {
478 return name();
479 }
480
481 public String getUniqueName() {
482 return name();
483 }
484
485 public String getCaption(Locale locale) {
486 return name();
487 }
488
489 public String getDescription(Locale locale) {
490 return description;
491 }
492
493 public boolean isInternal() {
494 return internal;
495 }
496
497 public ContentType getContentType() {
498 return ContentType.REGULAR;
499 }
500 }
501
502 /**
503 * Enumeration of the types of a <code>Property</code>.
504 *
505 * <p>The values are as specified by XMLA.
506 * For example, XMLA specifies MD_PROPTYPE_CAPTION with ordinal 0x21,
507 * which corresponds to the value {@link #CAPTION},
508 * whose {@link #xmlaOrdinal} is 0x21.
509 */
510 enum ContentType {
511 REGULAR(0x00),
512 ID(0x01),
513 RELATION_TO_PARENT(0x02),
514 ROLLUP_OPERATOR(0x03),
515 ORG_TITLE(0x11),
516 CAPTION(0x21),
517 CAPTION_SHORT(0x22),
518 CAPTION_DESCRIPTION(0x23),
519 CAPTION_ABREVIATION(0x24),
520 WEB_URL(0x31),
521 WEB_HTML(0x32),
522 WEB_XML_OR_XSL(0x33),
523 WEB_MAIL_ALIAS(0x34),
524 ADDRESS(0x41),
525 ADDRESS_STREET(0x42),
526 ADDRESS_HOUSE(0x43),
527 ADDRESS_CITY(0x44),
528 ADDRESS_STATE_OR_PROVINCE(0x45),
529 ADDRESS_ZIP(0x46),
530 ADDRESS_QUARTER(0x47),
531 ADDRESS_COUNTRY(0x48),
532 ADDRESS_BUILDING(0x49),
533 ADDRESS_ROOM(0x4A),
534 ADDRESS_FLOOR(0x4B),
535 ADDRESS_FAX(0x4C),
536 ADDRESS_PHONE(0x4D),
537 GEO_CENTROID_X(0x61),
538 GEO_CENTROID_Y(0x62),
539 GEO_CENTROID_Z(0x63),
540 GEO_BOUNDARY_TOP(0x64),
541 GEO_BOUNDARY_LEFT(0x65),
542 GEO_BOUNDARY_BOTTOM(0x66),
543 GEO_BOUNDARY_RIGHT(0x67),
544 GEO_BOUNDARY_FRONT(0x68),
545 GEO_BOUNDARY_REAR(0x69),
546 GEO_BOUNDARY_POLYGON(0x6A),
547 PHYSICAL_SIZE(0x71),
548 PHYSICAL_COLOR(0x72),
549 PHYSICAL_WEIGHT(0x73),
550 PHYSICAL_HEIGHT(0x74),
551 PHYSICAL_WIDTH(0x75),
552 PHYSICAL_DEPTH(0x76),
553 PHYSICAL_VOLUME(0x77),
554 PHYSICAL_DENSITY(0x78),
555 PERSON_FULL_NAME(0x82),
556 PERSON_FIRST_NAME(0x83),
557 PERSON_LAST_NAME(0x84),
558 PERSON_MIDDLE_NAME(0x85),
559 PERSON_DEMOGRAPHIC(0x86),
560 PERSON_CONTACT(0x87),
561 QTY_RANGE_LOW(0x91),
562 QTY_RANGE_HIGH(0x92),
563 FORMATTING_COLOR(0xA1),
564 FORMATTING_ORDER(0xA2),
565 FORMATTING_FONT(0xA3),
566 FORMATTING_FONT_EFFECTS(0xA4),
567 FORMATTING_FONT_SIZE(0xA5),
568 FORMATTING_SUB_TOTAL(0xA6),
569 DATE(0xB1),
570 DATE_START(0xB2),
571 DATE_ENDED(0xB3),
572 DATE_CANCELED(0xB4),
573 DATE_MODIFIED(0xB5),
574 DATE_DURATION(0xB6),
575 VERSION(0xC1);
576
577 private final int xmlaOrdinal;
578
579 private static final Map<Integer, ContentType> xmlaMap =
580 new HashMap<Integer, ContentType>();
581
582 static {
583 for (ContentType contentType : values()) {
584 xmlaMap.put(contentType.xmlaOrdinal, contentType);
585 }
586 }
587
588 /**
589 * Returns the ordinal code as specified by XMLA.
590 *
591 * <p>For example, the XMLA specification says that the ordinal of
592 * {@link #FORMATTING_FONT_EFFECTS} is 0xA4.
593 *
594 * @return ordinal code as specified by XMLA.
595 */
596 public int xmlaOrdinal() {
597 return xmlaOrdinal;
598 }
599
600 private ContentType(int xmlaOrdinal) {
601 this.xmlaOrdinal = xmlaOrdinal;
602 }
603
604 /**
605 * Looks up a ContentType by its XMLA ordinal.
606 *
607 * @param xmlaOrdinal Ordinal of a ContentType according to the XMLA
608 * specification.
609 *
610 * @return ContentType with the given ordinal, or null if there is no
611 * such ContentType
612 */
613 public static ContentType forXmlaOrdinal(int xmlaOrdinal) {
614 return xmlaMap.get(xmlaOrdinal);
615 }
616 }
617 }
618
619 // End Property.java