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