001    /*
002    // $Id: Property.java 253 2009-06-30 03:06:10Z 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 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 253 2009-06-30 03:06:10Z 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(
171                Datatype.STRING,
172                10,
173                false,
174                "Optional. The name of the catalog to which this member belongs. NULL if the provider does not support catalogs."),
175    
176            /**
177             * Definition of the property which
178             * holds the name of the current schema.
179             */
180            SCHEMA_NAME(
181                Datatype.STRING,
182                11,
183                false,
184                "Optional. The name of the schema to which this member belongs. NULL if the provider does not support schemas."),
185    
186            /**
187             * Definition of the property which
188             * holds the name of the current cube.
189             */
190            CUBE_NAME(
191                Datatype.STRING,
192                12,
193                false,
194                "Required. Name of the cube to which this member belongs."),
195    
196            /**
197             * Definition of the property which
198             * holds the unique name of the current dimension.
199             */
200            DIMENSION_UNIQUE_NAME(
201                Datatype.STRING,
202                13,
203                false,
204                "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."),
205    
206            /**
207             * Definition of the property which
208             * holds the unique name of the current hierarchy.
209             */
210            HIERARCHY_UNIQUE_NAME(
211                Datatype.STRING,
212                14,
213                false,
214                "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."),
215    
216            /**
217             * Definition of the property which
218             * holds the unique name of the current level.
219             */
220            LEVEL_UNIQUE_NAME(
221                Datatype.STRING,
222                15,
223                false,
224                "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."),
225    
226            /**
227             * Definition of the property which
228             * holds the ordinal of the current level.
229             */
230            LEVEL_NUMBER(
231                Datatype.UNSIGNED_INTEGER,
232                16,
233                false,
234                "Required. The distance of the member from the root of the hierarchy. The root level is zero."),
235    
236            /**
237             * Definition of the property which
238             * holds the ordinal of the current member.
239             */
240            MEMBER_ORDINAL(
241                Datatype.UNSIGNED_INTEGER,
242                17,
243                false,
244                "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."),
245    
246            /**
247             * Definition of the property which
248             * holds the name of the current member.
249             */
250            MEMBER_NAME(
251                Datatype.STRING,
252                18,
253                false,
254                "Required. Name of the member."),
255    
256            /**
257             * Definition of the property which
258             * holds the unique name of the current member.
259             */
260            MEMBER_UNIQUE_NAME(
261                Datatype.STRING,
262                19,
263                false,
264                "Required. Unique name of the member. For providers that generate unique names by qualification, each component of this name is delimited."),
265    
266            /**
267             * Definition of the property which
268             * holds the type of the member.
269             */
270            MEMBER_TYPE(
271                Datatype.STRING,
272                20,
273                false,
274                "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."),
275    
276            /**
277             * Definition of the property which
278             * holds the GUID of the member
279             */
280            MEMBER_GUID(
281                Datatype.STRING,
282                21,
283                false,
284                "Optional. Member GUID. NULL if no GUID exists."),
285    
286            /**
287             * Definition of the property which
288             * holds the label or caption associated with the member, or the
289             * member's name if no caption is defined.
290             */
291            MEMBER_CAPTION(
292                Datatype.STRING,
293                22,
294                false,
295                "Required. A label or caption associated with the member. Used primarily for display purposes. If a caption does not exist, MEMBER_NAME is returned."),
296    
297            /**
298             * Definition of the property which holds the
299             * number of children this member has.
300             */
301            CHILDREN_CARDINALITY(
302                Datatype.UNSIGNED_INTEGER,
303                23,
304                false,
305                "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."),
306    
307            /**
308             * Definition of the property which holds the
309             * distance from the root of the hierarchy of this member's parent.
310             */
311            PARENT_LEVEL(
312                Datatype.UNSIGNED_INTEGER,
313                24,
314                false,
315                "Required. The distance of the member's parent from the root level of the hierarchy. The root level is zero."),
316    
317            /**
318             * Definition of the property which holds the
319             * Name of the current catalog.
320             */
321            PARENT_UNIQUE_NAME(
322                Datatype.STRING,
323                25,
324                false,
325                "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."),
326    
327            /**
328             * Definition of the property which holds the
329             * number of parents that this member has. Generally 1, or 0
330             * for root members.
331             */
332            PARENT_COUNT(
333                Datatype.UNSIGNED_INTEGER,
334                26,
335                false,
336                "Required. Number of parents that this member has."),
337    
338            /**
339             * Definition of the property which holds the
340             * description of this member.
341             */
342            DESCRIPTION(
343                Datatype.STRING,
344                27,
345                false,
346                "Optional. A human-readable description of the member."),
347    
348            /**
349             * Definition of the internal property which holds the
350             * name of the system property which determines whether to show a member
351             * (especially a measure or calculated member) in a user interface such
352             * as JPivot.
353             */
354            $visible(
355                Datatype.BOOLEAN,
356                28,
357                true,
358                null),
359    
360            /**
361             * Definition of the internal property which holds the
362             * value of the member key in the original data type. MEMBER_KEY is for
363             * backward-compatibility.  MEMBER_KEY has the same value as KEY0 for
364             * non-composite keys, and MEMBER_KEY property is null for composite
365             * keys.
366             */
367            MEMBER_KEY(
368                Datatype.VARIANT,
369                29,
370                true,
371                "Optional. The value of the member key. Null for composite keys."),
372    
373            /**
374             * Definition of the boolean property that indicates whether
375             * a member is a placeholder member for an empty position in a
376             * dimension hierarchy.
377             */
378            IS_PLACEHOLDERMEMBER(
379                Datatype.BOOLEAN,
380                30,
381                false,
382                "Required. Whether the member is a placeholder member for an empty position in a dimension hierarchy."),
383    
384            /**
385             * Definition of the property that indicates whether the member is a
386             * data member.
387             */
388            IS_DATAMEMBER(
389                Datatype.BOOLEAN,
390                31,
391                false,
392                "Required. whether the member is a data member"),
393    
394            /**
395             * Definition of the property which
396             * holds the level depth of a member.
397             *
398             * <p>Caution: Level depth of members in parent-child hierarchy isn't
399             * from their levels.  It's calculated from the underlying data
400             * dynamically.
401             */
402            DEPTH(
403                Datatype.UNSIGNED_INTEGER,
404                43,
405                true,
406                "The level depth of a member"),
407    
408            /**
409             * Definition of the property which
410             * holds the DISPLAY_INFO required by XML/A.
411             *
412             * <p>Caution: This property's value is calculated based on a specified
413             * MDX query, so its value is dynamic at runtime.
414             */
415            DISPLAY_INFO(
416                Datatype.UNSIGNED_INTEGER,
417                44,
418                false,
419                "Display instruction of a member for XML/A"),
420    
421            /**
422             * Definition of the property which
423             * holds the value of a cell. Is usually numeric (since most measures
424             * are numeric) but is occasionally another type.
425             */
426            VALUE(
427                Datatype.VARIANT,
428                41,
429                false,
430                "The unformatted value of the cell.");
431    
432            private final Datatype type;
433            private final String description;
434            private final boolean internal;
435    
436            private StandardMemberProperty(
437                Datatype type,
438                int ordinal,
439                boolean internal,
440                String description)
441            {
442    //            assert ordinal == ordinal();
443                this.internal = internal;
444                this.type = type;
445                this.description = description;
446            }
447    
448            public String getName() {
449                return name();
450            }
451    
452            public String getUniqueName() {
453                return name();
454            }
455    
456            public String getDescription(Locale locale) {
457                return description;
458            }
459    
460            public String getCaption(Locale locale) {
461                return name();
462            }
463    
464            public Datatype getDatatype() {
465                return type;
466            }
467    
468            public Set<TypeFlag> getType() {
469                return TypeFlag.forMask(TypeFlag.MEMBER.xmlaOrdinal);
470            }
471    
472            public ContentType getContentType() {
473                return ContentType.REGULAR;
474            }
475    
476            public boolean isInternal() {
477                return internal;
478            }
479        }
480    
481        /**
482         * Enumeration of the system properties available for every
483         * {@link org.olap4j.Cell}.
484         *
485         * <p>The following propertiess are mandatory for cells:<ul>
486         * <li>{@link #BACK_COLOR}</li>
487         * <li>{@link #CELL_EVALUATION_LIST}</li>
488         * <li>{@link #CELL_ORDINAL}</li>
489         * <li>{@link #FORE_COLOR}</li>
490         * <li>{@link #FONT_NAME}</li>
491         * <li>{@link #FONT_SIZE}</li>
492         * <li>{@link #FONT_FLAGS}</li>
493         * <li>{@link #FORMAT_STRING}</li>
494         * <li>{@link #FORMATTED_VALUE}</li>
495         * <li>{@link #NON_EMPTY_BEHAVIOR}</li>
496         * <li>{@link #SOLVE_ORDER}</li>
497         * <li>{@link #VALUE}</li>
498         * </ul>
499         */
500        enum StandardCellProperty implements Property {
501            BACK_COLOR(
502                Datatype.STRING,
503                30,
504                false,
505                "The background color for displaying the VALUE or FORMATTED_VALUE property. For more information, see FORE_COLOR and BACK_COLOR Contents."),
506    
507            CELL_EVALUATION_LIST(
508                Datatype.STRING,
509                31,
510                false,
511                "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"),
512    
513            CELL_ORDINAL(
514                Datatype.UNSIGNED_INTEGER,
515                32,
516                false,
517                "The ordinal number of the cell in the dataset."),
518    
519            FORE_COLOR(
520                Datatype.STRING,
521                33,
522                false,
523                "The foreground color for displaying the VALUE or FORMATTED_VALUE property. For more information, see FORE_COLOR and BACK_COLOR Contents."),
524    
525            FONT_NAME(
526                Datatype.STRING,
527                34,
528                false,
529                "The font to be used to display the VALUE or FORMATTED_VALUE property."),
530    
531            FONT_SIZE(
532                Datatype.STRING,
533                35,
534                false,
535                "Font size to be used to display the VALUE or FORMATTED_VALUE property."),
536    
537            FONT_FLAGS(
538                Datatype.UNSIGNED_INTEGER,
539                36,
540                false,
541                "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."),
542    
543            /**
544             * Definition of the property which
545             * holds the formatted value of a cell.
546             */
547            FORMATTED_VALUE(
548                Datatype.STRING,
549                37,
550                false,
551                "The character string that represents a formatted display of the VALUE property."),
552    
553            /**
554             * Definition of the property which
555             * holds the format string used to format cell values.
556             */
557            FORMAT_STRING(
558                Datatype.STRING,
559                38,
560                false,
561                "The format string used to create the FORMATTED_VALUE property value. For more information, see FORMAT_STRING Contents."),
562    
563            NON_EMPTY_BEHAVIOR(
564                Datatype.STRING,
565                39,
566                false,
567                "The measure used to determine the behavior of calculated members when resolving empty cells."),
568    
569            /**
570             * Definition of the property which
571             * determines the solve order of a calculated member with respect to
572             * other calculated members.
573             */
574            SOLVE_ORDER(
575                Datatype.INTEGER,
576                40,
577                false,
578                "The solve order of the cell."),
579    
580            /**
581             * Definition of the property which
582             * holds the value of a cell. Is usually numeric (since most measures
583             * are numeric) but is occasionally another type.
584             */
585            VALUE(
586                Datatype.VARIANT,
587                41,
588                false,
589                "The unformatted value of the cell."),
590    
591            /**
592             * Definition of the property which
593             * holds the datatype of a cell. Valid values are "String",
594             * "Numeric", "Integer". The property's value derives from the
595             * "datatype" attribute of the "Measure" element; if the
596             * datatype attribute is not specified, the datatype is
597             * "Numeric" by default, except measures whose aggregator is
598             * "Count", whose datatype is "Integer".
599             */
600            DATATYPE(
601                Datatype.STRING,
602                42,
603                false,
604                "The datatype of the cell.");
605    
606            /**
607             * The datatype of the property.
608             */
609            private final Datatype type;
610            private final String description;
611            private final boolean internal;
612    
613            private StandardCellProperty(
614                Datatype type,
615                int ordinal,
616                boolean internal,
617                String description)
618            {
619                this.type = type;
620                this.internal = internal;
621                this.description = description;
622            }
623    
624            public Datatype getDatatype() {
625                return type;
626            }
627    
628            public Set<TypeFlag> getType() {
629                return TypeFlag.forMask(TypeFlag.CELL.xmlaOrdinal);
630            }
631    
632            public String getName() {
633                return name();
634            }
635    
636            public String getUniqueName() {
637                return name();
638            }
639    
640            public String getCaption(Locale locale) {
641                return name();
642            }
643    
644            public String getDescription(Locale locale) {
645                return description;
646            }
647    
648            public boolean isInternal() {
649                return internal;
650            }
651    
652            public ContentType getContentType() {
653                return ContentType.REGULAR;
654            }
655        }
656    
657        /**
658         * Enumeration of the types of a <code>Property</code>.
659         *
660         * <p>The values are as specified by XMLA.
661         * For example, XMLA specifies MD_PROPTYPE_CAPTION with ordinal 0x21,
662         * which corresponds to the value {@link #CAPTION},
663         * whose {@link #xmlaOrdinal} is 0x21.
664         */
665        enum ContentType {
666            REGULAR(0x00),
667            ID(0x01),
668            RELATION_TO_PARENT(0x02),
669            ROLLUP_OPERATOR(0x03),
670            ORG_TITLE(0x11),
671            CAPTION(0x21),
672            CAPTION_SHORT(0x22),
673            CAPTION_DESCRIPTION(0x23),
674            CAPTION_ABREVIATION(0x24),
675            WEB_URL(0x31),
676            WEB_HTML(0x32),
677            WEB_XML_OR_XSL(0x33),
678            WEB_MAIL_ALIAS(0x34),
679            ADDRESS(0x41),
680            ADDRESS_STREET(0x42),
681            ADDRESS_HOUSE(0x43),
682            ADDRESS_CITY(0x44),
683            ADDRESS_STATE_OR_PROVINCE(0x45),
684            ADDRESS_ZIP(0x46),
685            ADDRESS_QUARTER(0x47),
686            ADDRESS_COUNTRY(0x48),
687            ADDRESS_BUILDING(0x49),
688            ADDRESS_ROOM(0x4A),
689            ADDRESS_FLOOR(0x4B),
690            ADDRESS_FAX(0x4C),
691            ADDRESS_PHONE(0x4D),
692            GEO_CENTROID_X(0x61),
693            GEO_CENTROID_Y(0x62),
694            GEO_CENTROID_Z(0x63),
695            GEO_BOUNDARY_TOP(0x64),
696            GEO_BOUNDARY_LEFT(0x65),
697            GEO_BOUNDARY_BOTTOM(0x66),
698            GEO_BOUNDARY_RIGHT(0x67),
699            GEO_BOUNDARY_FRONT(0x68),
700            GEO_BOUNDARY_REAR(0x69),
701            GEO_BOUNDARY_POLYGON(0x6A),
702            PHYSICAL_SIZE(0x71),
703            PHYSICAL_COLOR(0x72),
704            PHYSICAL_WEIGHT(0x73),
705            PHYSICAL_HEIGHT(0x74),
706            PHYSICAL_WIDTH(0x75),
707            PHYSICAL_DEPTH(0x76),
708            PHYSICAL_VOLUME(0x77),
709            PHYSICAL_DENSITY(0x78),
710            PERSON_FULL_NAME(0x82),
711            PERSON_FIRST_NAME(0x83),
712            PERSON_LAST_NAME(0x84),
713            PERSON_MIDDLE_NAME(0x85),
714            PERSON_DEMOGRAPHIC(0x86),
715            PERSON_CONTACT(0x87),
716            QTY_RANGE_LOW(0x91),
717            QTY_RANGE_HIGH(0x92),
718            FORMATTING_COLOR(0xA1),
719            FORMATTING_ORDER(0xA2),
720            FORMATTING_FONT(0xA3),
721            FORMATTING_FONT_EFFECTS(0xA4),
722            FORMATTING_FONT_SIZE(0xA5),
723            FORMATTING_SUB_TOTAL(0xA6),
724            DATE(0xB1),
725            DATE_START(0xB2),
726            DATE_ENDED(0xB3),
727            DATE_CANCELED(0xB4),
728            DATE_MODIFIED(0xB5),
729            DATE_DURATION(0xB6),
730            VERSION(0xC1);
731    
732            private final int xmlaOrdinal;
733    
734            private static final Map<Integer, ContentType> xmlaMap =
735                new HashMap<Integer, ContentType>();
736    
737            static {
738                for (ContentType contentType : values()) {
739                    xmlaMap.put(contentType.xmlaOrdinal, contentType);
740                }
741            }
742    
743            /**
744             * Returns the ordinal code as specified by XMLA.
745             *
746             * <p>For example, the XMLA specification says that the ordinal of
747             * {@link #FORMATTING_FONT_EFFECTS} is 0xA4.
748             *
749             * @return ordinal code as specified by XMLA.
750             */
751            public int xmlaOrdinal() {
752                return xmlaOrdinal;
753            }
754    
755            private ContentType(int xmlaOrdinal) {
756                this.xmlaOrdinal = xmlaOrdinal;
757            }
758    
759            /**
760             * Looks up a ContentType by its XMLA ordinal.
761             *
762             * @param xmlaOrdinal Ordinal of a ContentType according to the XMLA
763             * specification.
764             *
765             * @return ContentType with the given ordinal, or null if there is no
766             * such ContentType
767             */
768            public static ContentType forXmlaOrdinal(int xmlaOrdinal) {
769                return xmlaMap.get(xmlaOrdinal);
770            }
771        }
772    }
773    
774    // End Property.java