001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2001-2005 Julian Hyde
008// Copyright (C) 2005-2013 Pentaho and others
009// All Rights Reserved.
010//
011// jhyde, 12 September, 2002
012*/
013package mondrian.olap;
014
015import mondrian.spi.PropertyFormatter;
016
017import java.util.*;
018
019/**
020 * <code>Property</code> is the definition of a member property.
021 *
022 * <p>The following properties are mandatory for members:<ul>
023 * <li>{@link #CATALOG_NAME}</li>
024 * <li>{@link #SCHEMA_NAME}</li>
025 * <li>{@link #CUBE_NAME}</li>
026 * <li>{@link #DIMENSION_UNIQUE_NAME}</li>
027 * <li>{@link #HIERARCHY_UNIQUE_NAME}</li>
028 * <li>{@link #LEVEL_UNIQUE_NAME}</li>
029 * <li>{@link #LEVEL_NUMBER}</li>
030 * <li>{@link #MEMBER_UNIQUE_NAME}</li>
031 * <li>{@link #MEMBER_NAME}</li>
032 * <li>{@link #MEMBER_TYPE}</li>
033 * <li>{@link #MEMBER_GUID}</li>
034 * <li>{@link #MEMBER_CAPTION}</li>
035 * <li>{@link #MEMBER_ORDINAL}</li>
036 * <li>{@link #CHILDREN_CARDINALITY}</li>
037 * <li>{@link #PARENT_LEVEL}</li>
038 * <li>{@link #PARENT_UNIQUE_NAME}</li>
039 * <li>{@link #PARENT_COUNT}</li>
040 * <li>{@link #DESCRIPTION}</li>
041 * </ul>
042 *
043 * The following propertiess are mandatory for cells:<ul>
044 * <li>{@link #BACK_COLOR}</li>
045 * <li>{@link #CELL_EVALUATION_LIST}</li>
046 * <li>{@link #CELL_ORDINAL}</li>
047 * <li>{@link #FORE_COLOR}</li>
048 * <li>{@link #FONT_NAME}</li>
049 * <li>{@link #FONT_SIZE}</li>
050 * <li>{@link #FONT_FLAGS}</li>
051 * <li>{@link #FORMAT_STRING}</li>
052 * <li>{@link #FORMATTED_VALUE}</li>
053 * <li>{@link #NON_EMPTY_BEHAVIOR}</li>
054 * <li>{@link #SOLVE_ORDER}</li>
055 * <li>{@link #VALUE}</li>
056 * </ul>
057 *
058 * @author jhyde
059 */
060public class Property extends EnumeratedValues.BasicValue {
061
062    public enum Datatype {
063        TYPE_STRING,
064        TYPE_NUMERIC,
065        TYPE_BOOLEAN,
066        TYPE_DATE,
067        TYPE_TIME,
068        TYPE_TIMESTAMP,
069        TYPE_OTHER
070    }
071
072    /**
073     * For properties which have synonyms, maps from the synonym to the
074     * property.
075     */
076    private static final Map<String, Property> synonyms =
077        new HashMap<String, Property>();
078
079    /**
080     * Map of upper-case names to property definitions, for case-insensitive
081     * match. Also contains synonyms.
082     */
083    public static final Map<String, Property> mapUpperNameToProperties =
084        new HashMap<String, Property>();
085
086    public static final int FORMAT_EXP_PARSED_ORDINAL = 0;
087    /**
088     * Definition of the internal property which
089     * holds the parsed format string (an object of type {@link Exp}).
090     */
091    public static final Property FORMAT_EXP_PARSED =
092        new Property(
093            "$format_exp", Datatype.TYPE_OTHER,
094            FORMAT_EXP_PARSED_ORDINAL, true, false,
095            false, null);
096
097    public static final int AGGREGATION_TYPE_ORDINAL = 1;
098    /**
099     * Definition of the internal property which
100     * holds the aggregation type. This is automatically set for stored
101     * measures, based upon their SQL aggregation.
102     */
103    public static final Property AGGREGATION_TYPE =
104        new Property(
105            "$aggregation_type", Datatype.TYPE_OTHER, AGGREGATION_TYPE_ORDINAL,
106            true, false, false, null);
107
108    public static final int NAME_ORDINAL = 2;
109    /**
110     * Definition of the internal property which
111     * holds a member's name.
112     */
113    public static final Property NAME =
114        new Property(
115            "$name", Datatype.TYPE_STRING, NAME_ORDINAL, true, false, false,
116            null);
117
118    public static final int CAPTION_ORDINAL = 3;
119    /**
120     * Definition of the internal property which
121     * holds a member's caption.
122     */
123    public static final Property CAPTION =
124        new Property(
125            "$caption", Datatype.TYPE_STRING, CAPTION_ORDINAL, true, false,
126            false, null);
127
128    public static final int CONTRIBUTING_CHILDREN_ORDINAL = 4;
129
130    /**
131     * Definition of the internal property which
132     * holds, for a member of a  parent-child hierarchy, a
133     * {@link java.util.List} containing the member's data
134     * member and all of its children (including non-visible children).
135     *
136     * @deprecated Property is not used and will be removed in mondrian-4.0;
137     * use {@link mondrian.olap.SchemaReader#getParentChildContributingChildren}
138     */
139    public static final Property CONTRIBUTING_CHILDREN =
140        new Property(
141            "$contributingChildren", Datatype.TYPE_OTHER,
142            CONTRIBUTING_CHILDREN_ORDINAL, true, false, false, null);
143
144    public static final int FORMULA_ORDINAL = 5;
145    /**
146     * Definition of the internal property which
147     * returns a calculated member's {@link Formula} object.
148     */
149    public static final Property FORMULA =
150        new Property(
151            "$formula", Datatype.TYPE_OTHER, FORMULA_ORDINAL, true, false,
152            false, null);
153
154    public static final int MEMBER_SCOPE_ORDINAL = 6;
155    /**
156     * Definition of the internal property which
157     * describes whether a calculated member belongs to a query or a cube.
158     */
159    public static final Property MEMBER_SCOPE =
160        new Property(
161            "$member_scope", Datatype.TYPE_OTHER, MEMBER_SCOPE_ORDINAL, true,
162            true, false, null);
163
164    public static final int CATALOG_NAME_ORDINAL = 10;
165    /**
166     * Definition of the property which
167     * holds the name of the current catalog.
168     */
169    public static final Property CATALOG_NAME =
170        new Property(
171            "CATALOG_NAME", Datatype.TYPE_STRING, CATALOG_NAME_ORDINAL, false,
172            true, false,
173            "Optional. The name of the catalog to which this member belongs. "
174            + "NULL if the provider does not support catalogs.");
175
176    public static final int SCHEMA_NAME_ORDINAL = 11;
177    /**
178     * Definition of the property which
179     * holds the name of the current schema.
180     */
181    public static final Property SCHEMA_NAME =
182        new Property(
183            "SCHEMA_NAME", Datatype.TYPE_STRING, SCHEMA_NAME_ORDINAL, false,
184            true, false,
185            "Optional. The name of the schema to which this member belongs. "
186            + "NULL if the provider does not support schemas.");
187
188    public static final int CUBE_NAME_ORDINAL = 12;
189    /**
190     * Definition of the property which
191     * holds the name of the current cube.
192     */
193    public static final Property CUBE_NAME =
194        new Property(
195            "CUBE_NAME", Datatype.TYPE_STRING, CUBE_NAME_ORDINAL, false, true,
196            false, "Required. Name of the cube to which this member belongs.");
197
198    public static final int DIMENSION_UNIQUE_NAME_ORDINAL = 13;
199    /**
200     * Definition of the property which
201     * holds the unique name of the current dimension.
202     */
203    public static final Property DIMENSION_UNIQUE_NAME =
204        new Property(
205            "DIMENSION_UNIQUE_NAME", Datatype.TYPE_STRING,
206            DIMENSION_UNIQUE_NAME_ORDINAL, false, true, false,
207            "Required. Unique name of the dimension to which this member "
208            + "belongs. For providers that generate unique names by "
209            + "qualification, each component of this name is delimited.");
210
211    public static final int HIERARCHY_UNIQUE_NAME_ORDINAL = 14;
212    /**
213     * Definition of the property which
214     * holds the unique name of the current hierarchy.
215     */
216    public static final Property HIERARCHY_UNIQUE_NAME =
217        new Property(
218            "HIERARCHY_UNIQUE_NAME", Datatype.TYPE_STRING,
219            HIERARCHY_UNIQUE_NAME_ORDINAL, false, true, false,
220            "Required. Unique name of the hierarchy. If the member belongs "
221            + "to more than one hierarchy, there is one row for each hierarchy "
222            + "to which it belongs. For providers that generate unique names "
223            + "by qualification, each component of this name is delimited.");
224
225    public static final int LEVEL_UNIQUE_NAME_ORDINAL = 15;
226    /**
227     * Definition of the property which
228     * holds the unique name of the current level.
229     */
230    public static final Property LEVEL_UNIQUE_NAME =
231        new Property(
232            "LEVEL_UNIQUE_NAME", Datatype.TYPE_STRING,
233            LEVEL_UNIQUE_NAME_ORDINAL, false, true, false,
234            "Required. Unique name of the level to which the member belongs. "
235            + "For providers that generate unique names by qualification, "
236            + "each component of this name is delimited.");
237
238    public static final int LEVEL_NUMBER_ORDINAL = 16;
239    /**
240     * Definition of the property which
241     * holds the ordinal of the current level.
242     */
243    public static final Property LEVEL_NUMBER =
244        new Property(
245            "LEVEL_NUMBER", Datatype.TYPE_STRING, LEVEL_NUMBER_ORDINAL, false,
246            true, false,
247            "Required. The distance of the member from the root of the "
248            + "hierarchy. The root level is zero.");
249
250    public static final int MEMBER_ORDINAL_ORDINAL = 17;
251    /**
252     * Definition of the property which
253     * holds the ordinal of the current member.
254     */
255    public static final Property MEMBER_ORDINAL =
256        new Property(
257            "MEMBER_ORDINAL", Datatype.TYPE_NUMERIC, MEMBER_ORDINAL_ORDINAL,
258            false, true, false,
259            "Required. Ordinal number of the member. Sort rank of the member "
260            + "when members of this dimension are sorted in their natural sort "
261            + "order. If providers do not have the concept of natural "
262            + "ordering, this should be the rank when sorted by MEMBER_NAME.");
263
264    public static final int MEMBER_NAME_ORDINAL = 18;
265    /**
266     * Definition of the property which
267     * holds the name of the current member.
268     */
269    public static final Property MEMBER_NAME =
270        new Property(
271            "MEMBER_NAME", Datatype.TYPE_STRING, MEMBER_NAME_ORDINAL, false,
272            true, false, "Required. Name of the member.");
273
274    public static final int MEMBER_UNIQUE_NAME_ORDINAL = 19;
275    /**
276     * Definition of the property which
277     * holds the unique name of the current member.
278     */
279    public static final Property MEMBER_UNIQUE_NAME =
280        new Property(
281            "MEMBER_UNIQUE_NAME", Datatype.TYPE_STRING,
282            MEMBER_UNIQUE_NAME_ORDINAL, false, true, false,
283            "Required. Unique name of the member. For providers that "
284            + "generate unique names by qualification, each component of "
285            + "this name is delimited.");
286
287    public static final int MEMBER_TYPE_ORDINAL = 20;
288    /**
289     * Definition of the property which
290     * holds the type of the member.
291     */
292    public static final Property MEMBER_TYPE =
293        new Property(
294            "MEMBER_TYPE", Datatype.TYPE_NUMERIC, MEMBER_TYPE_ORDINAL, false,
295            true, false,
296            "Required. Type of the member. Can be one of the following values: "
297            + "MDMEMBER_TYPE_REGULAR, MDMEMBER_TYPE_ALL, "
298            + "MDMEMBER_TYPE_FORMULA, MDMEMBER_TYPE_MEASURE, "
299            + "MDMEMBER_TYPE_UNKNOWN. MDMEMBER_TYPE_FORMULA takes precedence "
300            + "over MDMEMBER_TYPE_MEASURE. Therefore, if there is a formula "
301            + "(calculated) member on the Measures dimension, it is listed as "
302            + "MDMEMBER_TYPE_FORMULA.");
303
304    public static final int MEMBER_GUID_ORDINAL = 21;
305    /**
306     * Definition of the property which
307     * holds the GUID of the member
308     */
309    public static final Property MEMBER_GUID =
310        new Property(
311            "MEMBER_GUID", Datatype.TYPE_STRING, MEMBER_GUID_ORDINAL, false,
312            true, false, "Optional. Member GUID. NULL if no GUID exists.");
313
314    public static final int MEMBER_CAPTION_ORDINAL = 22;
315    /**
316     * Definition of the property which
317     * holds the label or caption associated with the member, or the
318     * member's name if no caption is defined.
319     *
320     * <p>"CAPTION" is a synonym for this property.
321     */
322    public static final Property MEMBER_CAPTION =
323        new Property(
324            "MEMBER_CAPTION", Datatype.TYPE_STRING, MEMBER_CAPTION_ORDINAL,
325            false, true, false,
326            "Required. A label or caption associated with the member. Used "
327            + "primarily for display purposes. If a caption does not exist, "
328            + "MEMBER_NAME is returned.");
329
330    public static final int CHILDREN_CARDINALITY_ORDINAL = 23;
331    /**
332     * Definition of the property which holds the
333     * number of children this member has.
334     */
335    public static final Property CHILDREN_CARDINALITY = new Property(
336        "CHILDREN_CARDINALITY", Datatype.TYPE_NUMERIC,
337        CHILDREN_CARDINALITY_ORDINAL, false, true, false,
338        "Required. Number of children that the member has. This can be an "
339        + "estimate, so consumers should not rely on this to be the exact "
340        + "count. Providers should return the best estimate possible.");
341
342    public static final int PARENT_LEVEL_ORDINAL = 24;
343    /**
344     * Definition of the property which holds the
345     * distance from the root of the hierarchy of this member's parent.
346     */
347    public static final Property PARENT_LEVEL =
348        new Property(
349            "PARENT_LEVEL", Datatype.TYPE_NUMERIC, PARENT_LEVEL_ORDINAL, false,
350            true, false,
351            "Required. The distance of the member's parent from the root level "
352            + "of the hierarchy. The root level is zero.");
353
354    public static final int PARENT_UNIQUE_NAME_ORDINAL = 25;
355    /**
356     * Definition of the property which holds the
357     * Name of the current catalog.
358     */
359    public static final Property PARENT_UNIQUE_NAME =
360        new Property(
361            "PARENT_UNIQUE_NAME", Datatype.TYPE_STRING,
362            PARENT_UNIQUE_NAME_ORDINAL, false, true, false,
363            "Required. Unique name of the member's parent. NULL is returned "
364            + "for any members at the root level. For providers that generate "
365            + "unique names by qualification, each component of this name is "
366            + "delimited.");
367
368    public static final int PARENT_COUNT_ORDINAL = 26;
369    /**
370     * Definition of the property which holds the
371     * number of parents that this member has. Generally 1, or 0 for root
372     * members.
373     */
374    public static final Property PARENT_COUNT =
375        new Property(
376            "PARENT_COUNT", Datatype.TYPE_NUMERIC, PARENT_COUNT_ORDINAL, false,
377            true, false, "Required. Number of parents that this member has.");
378
379    public static final int DESCRIPTION_ORDINAL = 27;
380    /**
381     * Definition of the property which holds the
382     * description of this member.
383     */
384    public static final Property DESCRIPTION =
385        new Property(
386            "DESCRIPTION", Datatype.TYPE_STRING, DESCRIPTION_ORDINAL, false,
387            true, false,
388            "Optional. A human-readable description of the member.");
389
390    public static final int VISIBLE_ORDINAL = 28;
391    /**
392     * Definition of the internal property which holds the
393     * name of the system property which determines whether to show a member
394     * (especially a measure or calculated member) in a user interface such as
395     * JPivot.
396     */
397    public static final Property VISIBLE =
398        new Property(
399            "$visible", Datatype.TYPE_BOOLEAN, VISIBLE_ORDINAL, true, false,
400            false, null);
401
402    public static final int CELL_FORMATTER_ORDINAL = 29;
403    /**
404     * Definition of the property which holds the
405     * name of the class which formats cell values of this member.
406     *
407     * <p>The class must implement the {@link mondrian.spi.CellFormatter}
408     * interface.
409     *
410     * <p>Despite its name, this is a member property.
411     */
412    public static final Property CELL_FORMATTER =
413        new Property(
414            "CELL_FORMATTER", Datatype.TYPE_STRING, CELL_FORMATTER_ORDINAL,
415            false, true, false,
416            "Name of the class which formats cell values of this member.");
417
418    public static final int CELL_FORMATTER_SCRIPT_LANGUAGE_ORDINAL = 51;
419    /**
420     * Definition of the property which holds the
421     * name of the scripting language in which a scripted cell formatter is
422     * implemented, e.g. 'JavaScript'.
423     *
424     * <p>Despite its name, this is a member property.
425     */
426    public static final Property CELL_FORMATTER_SCRIPT_LANGUAGE =
427        new Property(
428            "CELL_FORMATTER_SCRIPT_LANGUAGE", Datatype.TYPE_STRING,
429            CELL_FORMATTER_SCRIPT_LANGUAGE_ORDINAL,
430            false, true, false,
431            "Name of the scripting language in which a scripted cell formatter"
432            + "is implemented, e.g. 'JavaScript'.");
433
434    public static final int CELL_FORMATTER_SCRIPT_ORDINAL = 52;
435    /**
436     * Definition of the property which holds the
437     * script with which to format cell values of this member.
438     *
439     * <p>Despite its name, this is a member property.
440     */
441    public static final Property CELL_FORMATTER_SCRIPT =
442        new Property(
443            "CELL_FORMATTER_SCRIPT", Datatype.TYPE_STRING,
444            CELL_FORMATTER_SCRIPT_ORDINAL,
445            false, true, false,
446            "Name of the class which formats cell values of this member.");
447
448    // Cell properties
449
450
451    public static final int BACK_COLOR_ORDINAL = 30;
452    public static final Property BACK_COLOR =
453        new Property(
454            "BACK_COLOR", Datatype.TYPE_STRING, BACK_COLOR_ORDINAL, false,
455            false, true,
456            "The background color for displaying the VALUE or FORMATTED_VALUE "
457            + "property. For more information, see FORE_COLOR and BACK_COLOR "
458            + "Contents.");
459
460    public static final int CELL_EVALUATION_LIST_ORDINAL = 31;
461    public static final Property CELL_EVALUATION_LIST =
462        new Property(
463            "CELL_EVALUATION_LIST", Datatype.TYPE_STRING,
464            CELL_EVALUATION_LIST_ORDINAL, false, false, true,
465            "The semicolon-delimited list of evaluated formulas applicable to "
466            + "the cell, in order from lowest to highest solve order. For more "
467            + "information about solve order, see Understanding Pass Order and "
468            + "Solve Order");
469
470    public static final int CELL_ORDINAL_ORDINAL = 32;
471    public static final Property CELL_ORDINAL =
472        new Property(
473            "CELL_ORDINAL", Datatype.TYPE_NUMERIC, CELL_ORDINAL_ORDINAL, false,
474            false, true, "The ordinal number of the cell in the dataset.");
475
476    public static final int FORE_COLOR_ORDINAL = 33;
477    public static final Property FORE_COLOR =
478        new Property(
479            "FORE_COLOR", Datatype.TYPE_STRING, FORE_COLOR_ORDINAL, false,
480            false, true,
481            "The foreground color for displaying the VALUE or FORMATTED_VALUE "
482            + "property. For more information, see FORE_COLOR and BACK_COLOR "
483            + "Contents.");
484
485    public static final int FONT_NAME_ORDINAL = 34;
486    public static final Property FONT_NAME =
487        new Property(
488            "FONT_NAME", Datatype.TYPE_STRING, FONT_NAME_ORDINAL, false, false,
489            true,
490            "The font to be used to display the VALUE or FORMATTED_VALUE "
491            + "property.");
492
493    public static final int FONT_SIZE_ORDINAL = 35;
494    public static final Property FONT_SIZE =
495        new Property(
496            "FONT_SIZE", Datatype.TYPE_STRING, FONT_SIZE_ORDINAL, false, false,
497            true,
498            "Font size to be used to display the VALUE or FORMATTED_VALUE "
499            + "property.");
500
501    public static final int FONT_FLAGS_ORDINAL = 36;
502    public static final Property FONT_FLAGS =
503        new Property(
504            "FONT_FLAGS", Datatype.TYPE_NUMERIC, FONT_FLAGS_ORDINAL, false,
505            false, true,
506            "The bitmask detailing effects on the font. The value is the "
507            + "result of a bitwise OR operation of one or more of the "
508            + "following constants: MDFF_BOLD  = 1, MDFF_ITALIC = 2, "
509            + "MDFF_UNDERLINE = 4, MDFF_STRIKEOUT = 8. For example, the value "
510            + "5 represents the combination of bold (MDFF_BOLD) and underline "
511            + "(MDFF_UNDERLINE) font effects.");
512
513    public static final int FORMATTED_VALUE_ORDINAL = 37;
514    /**
515     * Definition of the property which
516     * holds the formatted value of a cell.
517     */
518    public static final Property FORMATTED_VALUE =
519        new Property(
520            "FORMATTED_VALUE", Datatype.TYPE_STRING, FORMATTED_VALUE_ORDINAL,
521            false, false, true,
522            "The character string that represents a formatted display of the "
523            + "VALUE property.");
524
525    public static final int FORMAT_STRING_ORDINAL = 38;
526    /**
527     * Definition of the property which
528     * holds the format string used to format cell values.
529     */
530    public static final Property FORMAT_STRING =
531        new Property(
532            "FORMAT_STRING", Datatype.TYPE_STRING, FORMAT_STRING_ORDINAL, false,
533            false, true,
534            "The format string used to create the FORMATTED_VALUE property "
535            + "value. For more information, see FORMAT_STRING Contents.");
536
537    public static final int NON_EMPTY_BEHAVIOR_ORDINAL = 39;
538    public static final Property NON_EMPTY_BEHAVIOR =
539        new Property(
540            "NON_EMPTY_BEHAVIOR", Datatype.TYPE_STRING,
541            NON_EMPTY_BEHAVIOR_ORDINAL, false, false, true,
542            "The measure used to determine the behavior of calculated members "
543            + "when resolving empty cells.");
544
545    public static final int SOLVE_ORDER_ORDINAL = 40;
546    /**
547     * Definition of the property which
548     * determines the solve order of a calculated member with respect to other
549     * calculated members.
550     */
551    public static final Property SOLVE_ORDER =
552        new Property(
553            "SOLVE_ORDER", Datatype.TYPE_NUMERIC, SOLVE_ORDER_ORDINAL, false,
554            false, true, "The solve order of the cell.");
555
556    public static final int VALUE_ORDINAL = 41;
557    /**
558     * Definition of the property which
559     * holds the value of a cell. Is usually numeric (since most measures are
560     * numeric) but is occasionally another type.
561     *
562     * <p>It is also applicable to members.
563     */
564    public static final Property VALUE =
565        new Property(
566            "VALUE", Datatype.TYPE_NUMERIC, VALUE_ORDINAL, false, true, true,
567            "The unformatted value of the cell.");
568
569    public static final int DATATYPE_ORDINAL = 42;
570    /**
571     * Definition of the property which
572     * holds the datatype of a cell. Valid values are "String",
573     * "Numeric", "Integer". The property's value derives from the
574     * "datatype" attribute of the "Measure" element; if the datatype attribute
575     * is not specified, the datatype is "Numeric" by default, except measures
576     * whose aggregator is "Count", whose datatype is "Integer".
577     */
578    public static final Property DATATYPE =
579        new Property(
580            "DATATYPE", Datatype.TYPE_STRING, DATATYPE_ORDINAL, false, false,
581            true, "The datatype of the cell.");
582
583    public static final int DEPTH_ORDINAL = 43;
584    /**
585     * Definition of the property which
586     * holds the level depth of a member.
587     *
588     * <p>Caution: Level depth of members in parent-child hierarchy isn't from
589     * their levels. It's calculated from the underlying data dynamically.
590     */
591    public static final Property DEPTH =
592        new Property(
593            "DEPTH", Datatype.TYPE_NUMERIC, DEPTH_ORDINAL, true, true, false,
594            "The level depth of a member");
595
596    public static final int DISPLAY_INFO_ORDINAL = 44;
597
598    /**
599     * Definition of the property which
600     * holds the DISPLAY_INFO required by XML/A.
601     * Caution: This property's value is calculated based on a specified MDX
602     * query, so it's value is dynamic at runtime.
603     */
604    public static final Property DISPLAY_INFO =
605        new Property(
606            "DISPLAY_INFO", Datatype.TYPE_NUMERIC, DISPLAY_INFO_ORDINAL, false,
607            true, false, "Display instruction of a member for XML/A");
608
609     public static final int MEMBER_KEY_ORDINAL = 45;
610    /**
611     * Definition of the property which
612     * holds the member key of the current member.
613     */
614    public static final Property MEMBER_KEY =
615        new Property(
616            "MEMBER_KEY", Datatype.TYPE_STRING, MEMBER_KEY_ORDINAL, false, true,
617            false, "Member key.");
618
619     public static final int KEY_ORDINAL = 46;
620    /**
621     * Definition of the property which
622     * holds the key of the current member.
623     */
624    public static final Property KEY =
625        new Property(
626            "KEY", Datatype.TYPE_STRING, KEY_ORDINAL, false, true, false,
627            "Key.");
628
629    public static final int SCENARIO_ORDINAL = 48;
630    /**
631     * Definition of the internal property which
632     * holds the scenario object underlying a member of the scenario hierarchy.
633     */
634    public static final Property SCENARIO =
635        new Property(
636            "$scenario", Datatype.TYPE_OTHER,
637            SCENARIO_ORDINAL, true, true, false, null);
638
639    public static final int DISPLAY_FOLDER_ORDINAL = 49;
640    /**
641     * Definition of the property which
642     * holds the DISPLAY_FOLDER. For measures, a client tool may use this
643     * folder to display measures in groups. This property has no meaning for
644     * other members.
645     */
646    public static final Property DISPLAY_FOLDER =
647        new Property(
648            "DISPLAY_FOLDER", Datatype.TYPE_STRING, DISPLAY_FOLDER_ORDINAL,
649            false, true, false, "Folder in which to display a measure");
650
651    public static final int LANGUAGE_ORDINAL = 50;
652
653    /**
654     * Definition of the property which
655     * holds the translation expressed as an LCID.
656     * Only valid for property translations.
657     */
658    public static final Property LANGUAGE =
659        new Property(
660            "LANGUAGE", Datatype.TYPE_NUMERIC, LANGUAGE_ORDINAL,
661            false, false, true,
662            "The translation expressed as an LCID. Only valid for property translations.");
663
664    public static final int FORMAT_EXP_ORDINAL = 53;
665
666    /**
667     * Definition of the property which
668     * holds the format string.
669     */
670    public static final Property FORMAT_EXP =
671        new Property(
672            "FORMAT_EXP", Datatype.TYPE_STRING, FORMAT_EXP_ORDINAL, true, true,
673            false, null);
674
675    public static final int ACTION_TYPE_ORDINAL = 54;
676
677    /**
678     * Definition of the property which
679     * holds the format string.
680     */
681    public static final Property ACTION_TYPE =
682        new Property(
683            "ACTION_TYPE", Datatype.TYPE_NUMERIC, ACTION_TYPE_ORDINAL, false,
684            false, true, null);
685
686    public static final int DRILLTHROUGH_COUNT_ORDINAL = 55;
687
688    /**
689     * Definition of the property that
690     * holds the number of fact rows that contributed to this cell.
691     * If the cell is not drillable, returns -1.
692     *
693     * <p>Note that this property may be expensive to compute for some
694     * cubes.</p>
695     */
696    public static final Property DRILLTHROUGH_COUNT =
697        new Property(
698            "DRILLTHROUGH_COUNT", Datatype.TYPE_NUMERIC,
699            DRILLTHROUGH_COUNT_ORDINAL, false,
700            false, true,
701            "Number of fact rows that contributed to this cell. If the cell is "
702            + "not drillable, value is -1.");
703
704    /**
705     * The various property names which define a format string.
706     */
707    static final Set<String> FORMAT_PROPERTIES =
708        new HashSet<String>(
709            Arrays.asList(
710                "format", "format_string", "FORMAT", FORMAT_STRING.name));
711
712    // ~ Data members ---------------------------------------------------------
713
714    /**
715     * The datatype of the property.
716     */
717    private final Datatype type;
718
719    /**
720     * Whether the property is internal.
721     */
722    private final boolean internal;
723    private final boolean member;
724    private final boolean cell;
725
726    private static int nextOrdinal = 100;
727
728    // ~ Methods --------------------------------------------------------------
729
730    /**
731     * Creates a property definition. If ordinal is negative, generates a
732     * unique positive ordinal.
733     */
734    protected Property(
735        String name,
736        Datatype type,
737        int ordinal,
738        boolean internal,
739        boolean member,
740        boolean cell,
741        String description)
742    {
743        super(name, ordinal < 0 ? nextOrdinal++ : ordinal, description);
744        this.type = type;
745        this.internal = internal;
746        this.member = member;
747        this.cell = cell;
748    }
749
750    /**
751     * Returns the datatype of the property.
752     */
753    public Datatype getType() {
754        return type;
755    }
756
757    public PropertyFormatter getFormatter() {
758        return null;
759    }
760
761    /**
762     * Returns the caption of this property.
763     */
764    public String getCaption() {
765        return name;
766    }
767
768    /**
769     * Returns whether this property is for system use only.
770     */
771    public boolean isInternal() {
772        return internal;
773    }
774
775    /**
776     * Returns whether this property is a standard member property.
777     */
778    public boolean isMemberProperty() {
779        return member;
780    }
781
782    /**
783     * Returns whether this property is a standard cell property.
784     */
785    public boolean isCellProperty() {
786        return cell && isStandard();
787    }
788
789    /**
790     * Returns whether this property is standard.
791     */
792    public boolean isStandard() {
793        return ordinal < MAX_ORDINAL;
794    }
795
796    public static final EnumeratedValues<Property> enumeration =
797        new EnumeratedValues<Property>(
798            new Property[] {
799                FORMAT_EXP_PARSED,
800                AGGREGATION_TYPE,
801                NAME,
802                CAPTION,
803                CONTRIBUTING_CHILDREN,
804                FORMULA,
805                CATALOG_NAME,
806                SCHEMA_NAME,
807                CUBE_NAME,
808                DIMENSION_UNIQUE_NAME,
809                HIERARCHY_UNIQUE_NAME,
810                LEVEL_UNIQUE_NAME,
811                LEVEL_NUMBER,
812                MEMBER_UNIQUE_NAME,
813                MEMBER_NAME,
814                MEMBER_TYPE,
815                MEMBER_GUID,
816                MEMBER_CAPTION,
817                MEMBER_ORDINAL,
818                CHILDREN_CARDINALITY,
819                PARENT_LEVEL,
820                PARENT_UNIQUE_NAME,
821                PARENT_COUNT,
822                DESCRIPTION,
823                VISIBLE,
824                CELL_FORMATTER,
825                CELL_FORMATTER_SCRIPT,
826                CELL_FORMATTER_SCRIPT_LANGUAGE,
827                BACK_COLOR,
828                CELL_EVALUATION_LIST,
829                CELL_ORDINAL,
830                FORE_COLOR,
831                FONT_NAME,
832                FONT_SIZE,
833                FONT_FLAGS,
834                FORMAT_STRING,
835                FORMATTED_VALUE,
836                NON_EMPTY_BEHAVIOR,
837                SOLVE_ORDER,
838                VALUE,
839                DATATYPE,
840                MEMBER_KEY,
841                KEY,
842                SCENARIO,
843                DISPLAY_FOLDER,
844                FORMAT_EXP,
845                ACTION_TYPE,
846                DRILLTHROUGH_COUNT,
847            });
848
849    private static final int MAX_ORDINAL = 56;
850
851    static {
852        // Populate synonyms.
853        synonyms.put("CAPTION", MEMBER_CAPTION);
854        synonyms.put("FORMAT", FORMAT_STRING);
855
856        // Populate map of upper-case property names.
857        for (String propertyName : enumeration.getNames()) {
858            final Property property = enumeration.getValue(propertyName, true);
859            mapUpperNameToProperties.put(
860                propertyName.toUpperCase(), property);
861            assert property.getOrdinal() < MAX_ORDINAL;
862        }
863
864        // Add synonyms.
865        for (Map.Entry<String, Property> entry : synonyms.entrySet()) {
866            mapUpperNameToProperties.put(
867                entry.getKey().toUpperCase(), entry.getValue());
868        }
869    }
870
871    /**
872     * Looks up a Property with a given ordinal.
873     * Returns null if not found.
874     */
875    public static Property lookup(int ordinal) {
876        return enumeration.getValue(ordinal);
877    }
878
879    /**
880     * Looks up a Property with a given name.
881     *
882     * @param name Name of property
883     * @param matchCase Whether to perform case-sensitive match
884     * @return Property with given name, or null if not found.
885     */
886    public static Property lookup(String name, boolean matchCase) {
887        if (matchCase) {
888            Property property = enumeration.getValue(name, false);
889            if (property != null) {
890                return property;
891            }
892            return synonyms.get(name);
893        } else {
894            // No need to check synonyms separately - the map contains them.
895            return mapUpperNameToProperties.get(name.toUpperCase());
896        }
897    }
898}
899
900// End Property.java