001    /*
002    // This java file was automatically generated
003    // from XOM model 'aggregates'
004    // on Tue Mar 06 01:13:59 PST 2007
005    // Do not edit this file by hand.
006    */
007    
008    package mondrian.rolap.aggmatcher;
009    /**
010     * This is the XML model for defining default aggregate table recognition
011     * and level/measure mapping.
012     * Revision is $Id: //open/mondrian/src/main/mondrian/rolap/aggmatcher/DefaultRulesSchema.xml#9 $
013     * <p>This class was generated from XOM model 'aggregates' on Tue Mar 06 01:13:59 PST 2007
014     */
015    public class DefaultDef {
016    
017            public static java.lang.Class getXMLDefClass()
018            {
019                    return DefaultDef.class;
020            }
021    
022            public static String[] _elements = {
023                    "AggRules",
024                    "Base",
025                    "CaseMatcher",
026                    "NameMatcher",
027                    "FactCountMatch",
028                    "ForeignKeyMatch",
029                    "TableMatch",
030                    "Mapper",
031                    "Regex",
032                    "RegexMapper",
033                    "Ref",
034                    "LevelMapRef",
035                    "MeasureMapRef",
036                    "IgnoreMapRef",
037                    "FactCountMatchRef",
038                    "ForeignKeyMatchRef",
039                    "TableMatchRef",
040                    "LevelMap",
041                    "MeasureMap",
042                    "IgnoreMap",
043                    "AggRule"
044            };
045    
046            /**
047             * The set of "named" rules for matching aggregate tables.
048             * Only one rule can be applied to a given connection. In
049             * addition, one rule must be set as the default - this rule
050             * is always the choice when not selecting by name.
051             * It is very important that the AggRules validate method is called
052             * prior to using any of the object.
053             */
054            public static class AggRules extends org.eigenbase.xom.ElementDef
055            {
056                    public AggRules()
057                    {
058                    }
059    
060                    public AggRules(org.eigenbase.xom.DOMWrapper _def)
061                            throws org.eigenbase.xom.XOMException
062                    {
063                            try {
064                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
065                                    _parser = _parser;
066                                    org.eigenbase.xom.NodeDef[] _tempArray = null;
067                                    _tempArray = _tempArray;
068                                    tag = (String)_parser.getAttribute("tag", "String", null, null, true);
069                                    _tempArray = _parser.getArray(TableMatch.class, 0, 0);
070                                    tableMatches = new TableMatch[_tempArray.length];
071                                    for(int _i=0; _i<tableMatches.length; _i++)
072                                            tableMatches[_i] = (TableMatch)_tempArray[_i];
073                                    _tempArray = _parser.getArray(FactCountMatch.class, 0, 0);
074                                    factCountMatches = new FactCountMatch[_tempArray.length];
075                                    for(int _i=0; _i<factCountMatches.length; _i++)
076                                            factCountMatches[_i] = (FactCountMatch)_tempArray[_i];
077                                    _tempArray = _parser.getArray(ForeignKeyMatch.class, 0, 0);
078                                    foreignKeyMatches = new ForeignKeyMatch[_tempArray.length];
079                                    for(int _i=0; _i<foreignKeyMatches.length; _i++)
080                                            foreignKeyMatches[_i] = (ForeignKeyMatch)_tempArray[_i];
081                                    _tempArray = _parser.getArray(LevelMap.class, 0, 0);
082                                    levelMaps = new LevelMap[_tempArray.length];
083                                    for(int _i=0; _i<levelMaps.length; _i++)
084                                            levelMaps[_i] = (LevelMap)_tempArray[_i];
085                                    _tempArray = _parser.getArray(MeasureMap.class, 0, 0);
086                                    measureMaps = new MeasureMap[_tempArray.length];
087                                    for(int _i=0; _i<measureMaps.length; _i++)
088                                            measureMaps[_i] = (MeasureMap)_tempArray[_i];
089                                    _tempArray = _parser.getArray(IgnoreMap.class, 0, 0);
090                                    ignoreMaps = new IgnoreMap[_tempArray.length];
091                                    for(int _i=0; _i<ignoreMaps.length; _i++)
092                                            ignoreMaps[_i] = (IgnoreMap)_tempArray[_i];
093                                    _tempArray = _parser.getArray(AggRule.class, 1, 0);
094                                    aggRules = new AggRule[_tempArray.length];
095                                    for(int _i=0; _i<aggRules.length; _i++)
096                                            aggRules[_i] = (AggRule)_tempArray[_i];
097                            } catch(org.eigenbase.xom.XOMException _ex) {
098                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
099                            }
100                    }
101    
102                    public String tag;  // required attribute
103    
104                    /**
105                     * All shared TableMatches.
106                     */
107                    public TableMatch[] tableMatches;  //optional array
108                    /**
109                     * All shared FactCountMatches.
110                     */
111                    public FactCountMatch[] factCountMatches;  //optional array
112                    /**
113                     * All shared ForeignKeyMatches.
114                     */
115                    public ForeignKeyMatch[] foreignKeyMatches;  //optional array
116                    /**
117                     * All shared LevelMap.
118                     */
119                    public LevelMap[] levelMaps;  //optional array
120                    /**
121                     * All shared MeasureMap.
122                     */
123                    public MeasureMap[] measureMaps;  //optional array
124                    /**
125                     * All shared IgnoreMap.
126                     */
127                    public IgnoreMap[] ignoreMaps;  //optional array
128                    /**
129                     * All AggRules (at least one).
130                     * Also, one of them must be marked with default=true.
131                     */
132                    public AggRule[] aggRules;  //min 1
133    
134                    public String getName()
135                    {
136                            return "AggRules";
137                    }
138    
139                    public void display(java.io.PrintWriter _out, int _indent)
140                    {
141                            _out.println(getName());
142                            displayAttribute(_out, "tag", tag, _indent+1);
143                            displayElementArray(_out, "tableMatches", tableMatches, _indent+1);
144                            displayElementArray(_out, "factCountMatches", factCountMatches, _indent+1);
145                            displayElementArray(_out, "foreignKeyMatches", foreignKeyMatches, _indent+1);
146                            displayElementArray(_out, "levelMaps", levelMaps, _indent+1);
147                            displayElementArray(_out, "measureMaps", measureMaps, _indent+1);
148                            displayElementArray(_out, "ignoreMaps", ignoreMaps, _indent+1);
149                            displayElementArray(_out, "aggRules", aggRules, _indent+1);
150                    }
151                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
152                    {
153                            _out.beginTag("AggRules", new org.eigenbase.xom.XMLAttrVector()
154                                    .add("tag", tag)
155                                    );
156                            displayXMLElementArray(_out, tableMatches);
157                            displayXMLElementArray(_out, factCountMatches);
158                            displayXMLElementArray(_out, foreignKeyMatches);
159                            displayXMLElementArray(_out, levelMaps);
160                            displayXMLElementArray(_out, measureMaps);
161                            displayXMLElementArray(_out, ignoreMaps);
162                            displayXMLElementArray(_out, aggRules);
163                            _out.endTag("AggRules");
164                    }
165                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
166                    {
167                            boolean _diff = true;
168                            AggRules _cother = (AggRules)_other;
169                            _diff = _diff && displayAttributeDiff("tag", tag, _cother.tag, _out, _indent+1);
170                            _diff = _diff && displayElementArrayDiff("tableMatches", tableMatches, _cother.tableMatches, _out, _indent+1);
171                            _diff = _diff && displayElementArrayDiff("factCountMatches", factCountMatches, _cother.factCountMatches, _out, _indent+1);
172                            _diff = _diff && displayElementArrayDiff("foreignKeyMatches", foreignKeyMatches, _cother.foreignKeyMatches, _out, _indent+1);
173                            _diff = _diff && displayElementArrayDiff("levelMaps", levelMaps, _cother.levelMaps, _out, _indent+1);
174                            _diff = _diff && displayElementArrayDiff("measureMaps", measureMaps, _cother.measureMaps, _out, _indent+1);
175                            _diff = _diff && displayElementArrayDiff("ignoreMaps", ignoreMaps, _cother.ignoreMaps, _out, _indent+1);
176                            _diff = _diff && displayElementArrayDiff("aggRules", aggRules, _cother.aggRules, _out, _indent+1);
177                            return _diff;
178                    }
179                    // BEGIN pass-through code block ---
180    private static final org.apache.log4j.Logger LOGGER =
181                    org.apache.log4j.Logger.getLogger(DefaultDef.class);
182    
183                protected static org.apache.log4j.Logger getLogger() {
184                    return LOGGER;
185                }
186    
187                public String getTag() {
188                    return tag;
189                }
190    
191                public AggRule getAggRule(String tag) {
192                    for (int i = 0; i < aggRules.length; i++) {
193                        AggRule aggRule = aggRules[i];
194                        if (aggRule.isEnabled() && aggRule.getTag().equals(tag)) {
195                            return aggRule;
196                        }
197                    }
198                    return null;
199                }
200    
201                public void validate(final mondrian.recorder.MessageRecorder msgRecorder) {
202                    msgRecorder.pushContextName(getName());
203                    try {
204                        validate(factCountMatches, msgRecorder);
205                        validate(tableMatches, msgRecorder);
206                        validate(levelMaps, msgRecorder);
207                        validate(measureMaps, msgRecorder);
208                        validate(ignoreMaps, msgRecorder);
209                        validate(aggRules, msgRecorder);
210                    } finally {
211                        msgRecorder.popContextName();
212                    }
213                }
214                private void validate(final Base[] bases,
215                                      final mondrian.recorder.MessageRecorder msgRecorder) {
216                    for (int i = 0; i < bases.length; i++) {
217                        Base base = bases[i];
218                        if (base.isEnabled()) {
219                            base.validate(this, msgRecorder);
220                        }
221                    }
222                }
223    
224                public boolean hasIgnoreMap(String id) {
225                    return (lookupIgnoreMap(id) != null);
226                }
227                public IgnoreMap lookupIgnoreMap(String id) {
228                    return (IgnoreMap) lookupBase(id, ignoreMaps);
229                }
230    
231                public boolean hasFactCountMatch(String id) {
232                    return (lookupFactCountMatch(id) != null);
233                }
234                public FactCountMatch lookupFactCountMatch(String id) {
235                    return (FactCountMatch) lookupBase(id, factCountMatches);
236                }
237    
238                public boolean hasForeignKeyMatch(String id) {
239                    return (lookupForeignKeyMatch(id) != null);
240                }
241                public ForeignKeyMatch lookupForeignKeyMatch(String id) {
242                    return (ForeignKeyMatch) lookupBase(id, foreignKeyMatches);
243                }
244    
245                public boolean hasTableMatch(String id) {
246                    return (lookupTableMatch(id) != null);
247                }
248                public TableMatch lookupTableMatch(String id) {
249                    return (TableMatch) lookupBase(id, tableMatches);
250                }
251    
252                public boolean hasLevelMap(String id) {
253                    return (lookupLevelMap(id) != null);
254                }
255                public LevelMap lookupLevelMap(String id) {
256                    return (LevelMap) lookupBase(id, levelMaps);
257                }
258    
259                public boolean hasMeasureMap(String id) {
260                    return (lookupMeasureMap(id) != null);
261                }
262                public MeasureMap lookupMeasureMap(String id) {
263                    return (MeasureMap) lookupBase(id, measureMaps);
264                }
265    
266                public boolean hasAggRule(String id) {
267                    return (lookupAggRule(id) != null);
268                }
269                public AggRule lookupAggRule(String id) {
270                    return (AggRule) lookupBase(id, aggRules);
271                }
272    
273                private Base lookupBase(String tag, Base[] bases) {
274                    for (int i = 0; i < bases.length; i++) {
275                        Base base = bases[i];
276                        if (base.isEnabled() && base.getTag().equals(tag)) {
277                            return base;
278                        }
279                    }
280                    return null;
281                }
282    
283                public IgnoreMap[] getIgnoreMaps() {
284                    return ignoreMaps;
285                }
286                public FactCountMatch[] getFactCountMatches() {
287                    return factCountMatches;
288                }
289                public ForeignKeyMatch[] getForeignKeyMatches() {
290                    return foreignKeyMatches;
291                }
292                public TableMatch[] getTableMatches() {
293                    return tableMatches;
294                }
295                public LevelMap[] getLevelMaps() {
296                    return levelMaps;
297                }
298                public MeasureMap[] getMeasureMaps() {
299                    return measureMaps;
300                }
301                public AggRule[] getAggRules() {
302                    return aggRules;
303                }
304                    // END pass-through code block ---
305            }
306    
307            /**
308             * Base is the base class for all of the elements.
309             * All elements can be enabled or not, have a tag, and
310             * can be validated.
311             */
312            public static abstract class Base extends org.eigenbase.xom.ElementDef
313            {
314                    public Base()
315                    {
316                    }
317    
318                    public Base(org.eigenbase.xom.DOMWrapper _def)
319                            throws org.eigenbase.xom.XOMException
320                    {
321                            try {
322                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
323                                    _parser = _parser;
324                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
325                            } catch(org.eigenbase.xom.XOMException _ex) {
326                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
327                            }
328                    }
329    
330                    public Boolean enabled;  // attribute default: true
331    
332    
333                    public String getName()
334                    {
335                            return "Base";
336                    }
337    
338                    public void display(java.io.PrintWriter _out, int _indent)
339                    {
340                            _out.println(getName());
341                            displayAttribute(_out, "enabled", enabled, _indent+1);
342                    }
343                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
344                    {
345                            _out.beginTag("(%Base;)", new org.eigenbase.xom.XMLAttrVector()
346                                    .add("enabled", enabled)
347                                    );
348                            _out.endTag("(%Base;)");
349                    }
350                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
351                    {
352                            boolean _diff = true;
353                            Base _cother = (Base)_other;
354                            _diff = _diff && displayAttributeDiff("enabled", enabled, _cother.enabled, _out, _indent+1);
355                            return _diff;
356                    }
357                    // BEGIN pass-through code block ---
358    public boolean isEnabled() {
359                    return enabled.booleanValue();
360                }
361                protected abstract String getTag();
362                public abstract void validate(final AggRules rules,
363                                              final mondrian.recorder.MessageRecorder msgRecorder);
364                    // END pass-through code block ---
365            }
366    
367            /**
368             * This is a base class for all elements that can match strings
369             * where the case of the string is important. In addition,
370             * it has an id which services as its tag.
371             */
372            public static abstract class CaseMatcher extends Base
373            {
374                    public CaseMatcher()
375                    {
376                    }
377    
378                    public CaseMatcher(org.eigenbase.xom.DOMWrapper _def)
379                            throws org.eigenbase.xom.XOMException
380                    {
381                            try {
382                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
383                                    _parser = _parser;
384                                    id = (String)_parser.getAttribute("id", "String", null, null, true);
385                                    charcase = (String)_parser.getAttribute("charcase", "String", "ignore", _charcase_values, false);
386                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
387                            } catch(org.eigenbase.xom.XOMException _ex) {
388                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
389                            }
390                    }
391    
392                    public String id;  // required attribute
393                    /** Allowable values for {@link #charcase}. */
394                    public static final String[] _charcase_values = {"ignore", "exact", "upper", "lower"};
395                    public String charcase;  // attribute default: ignore
396    
397    
398                    public String getName()
399                    {
400                            return "CaseMatcher";
401                    }
402    
403                    public void display(java.io.PrintWriter _out, int _indent)
404                    {
405                            _out.println(getName());
406                            displayAttribute(_out, "id", id, _indent+1);
407                            displayAttribute(_out, "charcase", charcase, _indent+1);
408                            displayAttribute(_out, "enabled", enabled, _indent+1);
409                    }
410                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
411                    {
412                            _out.beginTag("(%CaseMatcher;)", new org.eigenbase.xom.XMLAttrVector()
413                                    .add("id", id)
414                                    .add("charcase", charcase)
415                                    .add("enabled", enabled)
416                                    );
417                            _out.endTag("(%CaseMatcher;)");
418                    }
419                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
420                    {
421                            boolean _diff = true;
422                            CaseMatcher _cother = (CaseMatcher)_other;
423                            _diff = _diff && displayAttributeDiff("id", id, _cother.id, _out, _indent+1);
424                            _diff = _diff && displayAttributeDiff("charcase", charcase, _cother.charcase, _out, _indent+1);
425                            return _diff;
426                    }
427                    // BEGIN pass-through code block ---
428    public void validate(final AggRules rules,
429                                     final mondrian.recorder.MessageRecorder msgRecorder) {
430                    // empty
431                }
432                protected String getTag() {
433                    return getId();
434                }
435                public String getId() {
436                    return id;
437                }
438                public String getCharCase() {
439                    return charcase;
440                }
441                    // END pass-through code block ---
442            }
443    
444            /**
445             * A NameMatcher is a CaseMatcher that prepends and appends
446             * regular expressions to a given string as part of creating
447             * the matching regular expression. Both the pre/post
448             * regular expression can be null in which case matches are
449             * applied simply against the name (modulo case considerations).
450             * The purpose of this class is to allow aggregate tables to
451             * be identified when their table names are formed by placing
452             * text before and/or after the base fact table name.
453             */
454            public static abstract class NameMatcher extends CaseMatcher
455            {
456                    public NameMatcher()
457                    {
458                    }
459    
460                    public NameMatcher(org.eigenbase.xom.DOMWrapper _def)
461                            throws org.eigenbase.xom.XOMException
462                    {
463                            try {
464                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
465                                    _parser = _parser;
466                                    pretemplate = (String)_parser.getAttribute("pretemplate", "String", null, null, false);
467                                    posttemplate = (String)_parser.getAttribute("posttemplate", "String", null, null, false);
468                                    basename = (String)_parser.getAttribute("basename", "String", null, null, false);
469                                    id = (String)_parser.getAttribute("id", "String", null, null, true);
470                                    charcase = (String)_parser.getAttribute("charcase", "String", "ignore", _charcase_values, false);
471                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
472                            } catch(org.eigenbase.xom.XOMException _ex) {
473                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
474                            }
475                    }
476    
477                    public String pretemplate;  // optional attribute
478                    public String posttemplate;  // optional attribute
479                    public String basename;  // optional attribute
480    
481    
482                    public String getName()
483                    {
484                            return "NameMatcher";
485                    }
486    
487                    public void display(java.io.PrintWriter _out, int _indent)
488                    {
489                            _out.println(getName());
490                            displayAttribute(_out, "pretemplate", pretemplate, _indent+1);
491                            displayAttribute(_out, "posttemplate", posttemplate, _indent+1);
492                            displayAttribute(_out, "basename", basename, _indent+1);
493                            displayAttribute(_out, "id", id, _indent+1);
494                            displayAttribute(_out, "charcase", charcase, _indent+1);
495                            displayAttribute(_out, "enabled", enabled, _indent+1);
496                    }
497                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
498                    {
499                            _out.beginTag("(%NameMatcher;)", new org.eigenbase.xom.XMLAttrVector()
500                                    .add("pretemplate", pretemplate)
501                                    .add("posttemplate", posttemplate)
502                                    .add("basename", basename)
503                                    .add("id", id)
504                                    .add("charcase", charcase)
505                                    .add("enabled", enabled)
506                                    );
507                            _out.endTag("(%NameMatcher;)");
508                    }
509                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
510                    {
511                            boolean _diff = true;
512                            NameMatcher _cother = (NameMatcher)_other;
513                            _diff = _diff && displayAttributeDiff("pretemplate", pretemplate, _cother.pretemplate, _out, _indent+1);
514                            _diff = _diff && displayAttributeDiff("posttemplate", posttemplate, _cother.posttemplate, _out, _indent+1);
515                            _diff = _diff && displayAttributeDiff("basename", basename, _cother.basename, _out, _indent+1);
516                            return _diff;
517                    }
518                    // BEGIN pass-through code block ---
519    java.util.regex.Pattern baseNamePattern = null;
520                public void validate(final AggRules rules,
521                                     final mondrian.recorder.MessageRecorder msgRecorder) {
522                    msgRecorder.pushContextName(getName());
523                    try {
524                        super.validate(rules, msgRecorder);
525    
526                        if (basename != null) {
527                            baseNamePattern =
528                                java.util.regex.Pattern.compile(basename);
529                        }
530                    } finally {
531                        msgRecorder.popContextName();
532                    }
533                }
534    
535                /**
536                 * Generates a regular expression string by prepending and
537                 * appending regular expression to the parameter tableName.
538                 *
539                 * @param name Table name
540                 * @return regular expression
541                 */
542                public String getRegex(final String name) {
543                    StringBuilder buf = new StringBuilder();
544                    if (pretemplate != null) {
545                        buf.append(pretemplate);
546                    }
547                    if (name != null) {
548                        String n = name;
549                        if (baseNamePattern != null) {
550                            java.util.regex.Matcher matcher =
551                                baseNamePattern.matcher(name);
552                            if (matcher.matches() && matcher.groupCount() > 0) {
553                                n = matcher.group(1);
554    
555                            } else {
556                                if (AggRules.getLogger().isDebugEnabled()) {
557                                    StringBuilder bf = new StringBuilder(64);
558                                    bf.append(getName());
559                                    bf.append(".getRegex: for name \"");
560                                    bf.append(name);
561                                    bf.append("\" regex is null because basename \"");
562                                    bf.append(basename);
563                                    bf.append("\" is not matched.");
564    
565                                    String msg = bf.toString();
566                                    AggRules.getLogger().debug(msg);
567                                }
568                                // If the table name does not match the basename
569                                // pattern, then return null for regex.
570                                return null;
571                            }
572                        }
573                        buf.append(n);
574                    }
575                    if (posttemplate != null) {
576                        buf.append(posttemplate);
577                    }
578    
579                    String regex = buf.toString();
580    
581                    if (AggRules.getLogger().isDebugEnabled()) {
582                        StringBuilder bf = new StringBuilder(64);
583                        bf.append(getName());
584                        bf.append(".getRegex: for name \"");
585                        bf.append(name);
586                        bf.append("\" regex is \"");
587                        bf.append(regex);
588                        bf.append('"');
589    
590                        String msg = bf.toString();
591                        AggRules.getLogger().debug(msg);
592                    }
593                    return regex;
594                }
595    
596                protected Recognizer.Matcher getMatcher(String name) {
597    
598                    final String charcase = getCharCase();
599                    final String regex;
600                    int flag = 0;
601    
602                    if (charcase.equals("ignore")) {
603                        // the case of name does not matter
604                        // since the Pattern will be create to ignore case
605                        regex = getRegex(name);
606    
607                        flag = java.util.regex.Pattern.CASE_INSENSITIVE;
608    
609                    } else if (charcase.equals("exact")) {
610                        // the case of name is not changed
611                        // since we are interested in exact case matching
612                        regex = getRegex(name);
613    
614                    } else if (charcase.equals("upper")) {
615                        // convert name to upper case
616                        regex = getRegex(name.toUpperCase());
617    
618                    } else {
619                        // lower
620                        // convert name to lower case
621                        regex = getRegex(name.toLowerCase());
622    
623                    }
624                    // If regex is null, then return a matcher that matches nothing
625                    if (regex == null) {
626                        return new Recognizer.Matcher() {
627                            public boolean matches(String name) {
628                                return false;
629                            }
630                        };
631                    }
632    
633                    final java.util.regex.Pattern pattern =
634                            java.util.regex.Pattern.compile(regex, flag);
635    
636                    return new Recognizer.Matcher() {
637                        public boolean matches(String name) {
638                            boolean b = pattern.matcher(name).matches();
639                            if (AggRules.getLogger().isDebugEnabled()) {
640                                debug(name);
641                            }
642                            return b;
643                        }
644                        private void debug(String name) {
645                            StringBuilder bf = new StringBuilder(64);
646                            bf.append(NameMatcher.this.getName());
647                            bf.append(".Matcher.matches:");
648                            bf.append(" name \"");
649                            bf.append(name);
650                            bf.append("\" pattern \"");
651                            bf.append(pattern.pattern());
652                            bf.append("\"");
653                            if ((pattern.flags() &
654                                java.util.regex.Pattern.CASE_INSENSITIVE) != 0) {
655                                bf.append(" case_insensitive");
656                            }
657    
658                            String msg = bf.toString();
659                            AggRules.getLogger().debug(msg);
660                        }
661                    };
662                }
663                    // END pass-through code block ---
664            }
665    
666            /**
667             * This is used to identify the "fact_count" column in an aggregate
668             * table. It allows one to match using regular exprssions.
669             * The default is that the name of the fact count colum is simply
670             * the string "fact_count".
671             */
672            public static class FactCountMatch extends NameMatcher
673            {
674                    public FactCountMatch()
675                    {
676                    }
677    
678                    public FactCountMatch(org.eigenbase.xom.DOMWrapper _def)
679                            throws org.eigenbase.xom.XOMException
680                    {
681                            try {
682                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
683                                    _parser = _parser;
684                                    factCountName = (String)_parser.getAttribute("factCountName", "String", "fact_count", null, true);
685                                    pretemplate = (String)_parser.getAttribute("pretemplate", "String", null, null, false);
686                                    posttemplate = (String)_parser.getAttribute("posttemplate", "String", null, null, false);
687                                    basename = (String)_parser.getAttribute("basename", "String", null, null, false);
688                                    id = (String)_parser.getAttribute("id", "String", null, null, true);
689                                    charcase = (String)_parser.getAttribute("charcase", "String", "ignore", _charcase_values, false);
690                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
691                            } catch(org.eigenbase.xom.XOMException _ex) {
692                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
693                            }
694                    }
695    
696                    public String factCountName;  // attribute default: fact_count
697    
698    
699                    public String getName()
700                    {
701                            return "FactCountMatch";
702                    }
703    
704                    public void display(java.io.PrintWriter _out, int _indent)
705                    {
706                            _out.println(getName());
707                            displayAttribute(_out, "factCountName", factCountName, _indent+1);
708                            displayAttribute(_out, "pretemplate", pretemplate, _indent+1);
709                            displayAttribute(_out, "posttemplate", posttemplate, _indent+1);
710                            displayAttribute(_out, "basename", basename, _indent+1);
711                            displayAttribute(_out, "id", id, _indent+1);
712                            displayAttribute(_out, "charcase", charcase, _indent+1);
713                            displayAttribute(_out, "enabled", enabled, _indent+1);
714                    }
715                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
716                    {
717                            _out.beginTag("FactCountMatch", new org.eigenbase.xom.XMLAttrVector()
718                                    .add("factCountName", factCountName)
719                                    .add("pretemplate", pretemplate)
720                                    .add("posttemplate", posttemplate)
721                                    .add("basename", basename)
722                                    .add("id", id)
723                                    .add("charcase", charcase)
724                                    .add("enabled", enabled)
725                                    );
726                            _out.endTag("FactCountMatch");
727                    }
728                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
729                    {
730                            boolean _diff = true;
731                            FactCountMatch _cother = (FactCountMatch)_other;
732                            _diff = _diff && displayAttributeDiff("factCountName", factCountName, _cother.factCountName, _out, _indent+1);
733                            return _diff;
734                    }
735                    // BEGIN pass-through code block ---
736    public void validate(final AggRules rules,
737                                     final mondrian.recorder.MessageRecorder msgRecorder) {
738                    msgRecorder.pushContextName(getName());
739                    try {
740                        super.validate(rules, msgRecorder);
741                    } finally {
742                        msgRecorder.popContextName();
743                    }
744                }
745                public Recognizer.Matcher getMatcher() {
746                    return super.getMatcher(factCountName);
747                }
748                    // END pass-through code block ---
749            }
750    
751            /**
752             * This is used to identify foreign key columns in a candidate
753             * aggregate table given the name of a foreign key column of the
754             * base fact table. This allows such foreign keys to be identified
755             * by using a regular exprsssion. The default is to simply
756             * match the base fact table's foreign key column name.
757             */
758            public static class ForeignKeyMatch extends NameMatcher
759            {
760                    public ForeignKeyMatch()
761                    {
762                    }
763    
764                    public ForeignKeyMatch(org.eigenbase.xom.DOMWrapper _def)
765                            throws org.eigenbase.xom.XOMException
766                    {
767                            try {
768                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
769                                    _parser = _parser;
770                                    pretemplate = (String)_parser.getAttribute("pretemplate", "String", null, null, false);
771                                    posttemplate = (String)_parser.getAttribute("posttemplate", "String", null, null, false);
772                                    basename = (String)_parser.getAttribute("basename", "String", null, null, false);
773                                    id = (String)_parser.getAttribute("id", "String", null, null, true);
774                                    charcase = (String)_parser.getAttribute("charcase", "String", "ignore", _charcase_values, false);
775                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
776                            } catch(org.eigenbase.xom.XOMException _ex) {
777                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
778                            }
779                    }
780    
781    
782    
783                    public String getName()
784                    {
785                            return "ForeignKeyMatch";
786                    }
787    
788                    public void display(java.io.PrintWriter _out, int _indent)
789                    {
790                            _out.println(getName());
791                            displayAttribute(_out, "pretemplate", pretemplate, _indent+1);
792                            displayAttribute(_out, "posttemplate", posttemplate, _indent+1);
793                            displayAttribute(_out, "basename", basename, _indent+1);
794                            displayAttribute(_out, "id", id, _indent+1);
795                            displayAttribute(_out, "charcase", charcase, _indent+1);
796                            displayAttribute(_out, "enabled", enabled, _indent+1);
797                    }
798                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
799                    {
800                            _out.beginTag("ForeignKeyMatch", new org.eigenbase.xom.XMLAttrVector()
801                                    .add("pretemplate", pretemplate)
802                                    .add("posttemplate", posttemplate)
803                                    .add("basename", basename)
804                                    .add("id", id)
805                                    .add("charcase", charcase)
806                                    .add("enabled", enabled)
807                                    );
808                            _out.endTag("ForeignKeyMatch");
809                    }
810                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
811                    {
812                            boolean _diff = true;
813                            ForeignKeyMatch _cother = (ForeignKeyMatch)_other;
814                            return _diff;
815                    }
816                    // BEGIN pass-through code block ---
817    public void validate(final AggRules rules,
818                                     final mondrian.recorder.MessageRecorder msgRecorder) {
819                    msgRecorder.pushContextName(getName());
820                    try {
821                        super.validate(rules, msgRecorder);
822                    } finally {
823                        msgRecorder.popContextName();
824                    }
825                }
826                public Recognizer.Matcher getMatcher(final String foreignKeyName) {
827                    return super.getMatcher(foreignKeyName);
828                }
829                    // END pass-through code block ---
830            }
831    
832            /**
833             * This is used to identify which tables in the database might
834             * be aggregate table of a given fact table.
835             * It is expected that aggregate table names will include the
836             * base fact table name with additional text before and/or
837             * after.
838             * It is not allow for both the prepending and appending
839             * regular expression text to be null (if it were, then only
840             * aggregate tables who names were the same as (modulo case)
841             * would match - which is surely not allowed).
842             */
843            public static class TableMatch extends NameMatcher
844            {
845                    public TableMatch()
846                    {
847                    }
848    
849                    public TableMatch(org.eigenbase.xom.DOMWrapper _def)
850                            throws org.eigenbase.xom.XOMException
851                    {
852                            try {
853                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
854                                    _parser = _parser;
855                                    pretemplate = (String)_parser.getAttribute("pretemplate", "String", null, null, false);
856                                    posttemplate = (String)_parser.getAttribute("posttemplate", "String", null, null, false);
857                                    basename = (String)_parser.getAttribute("basename", "String", null, null, false);
858                                    id = (String)_parser.getAttribute("id", "String", null, null, true);
859                                    charcase = (String)_parser.getAttribute("charcase", "String", "ignore", _charcase_values, false);
860                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
861                            } catch(org.eigenbase.xom.XOMException _ex) {
862                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
863                            }
864                    }
865    
866    
867    
868                    public String getName()
869                    {
870                            return "TableMatch";
871                    }
872    
873                    public void display(java.io.PrintWriter _out, int _indent)
874                    {
875                            _out.println(getName());
876                            displayAttribute(_out, "pretemplate", pretemplate, _indent+1);
877                            displayAttribute(_out, "posttemplate", posttemplate, _indent+1);
878                            displayAttribute(_out, "basename", basename, _indent+1);
879                            displayAttribute(_out, "id", id, _indent+1);
880                            displayAttribute(_out, "charcase", charcase, _indent+1);
881                            displayAttribute(_out, "enabled", enabled, _indent+1);
882                    }
883                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
884                    {
885                            _out.beginTag("TableMatch", new org.eigenbase.xom.XMLAttrVector()
886                                    .add("pretemplate", pretemplate)
887                                    .add("posttemplate", posttemplate)
888                                    .add("basename", basename)
889                                    .add("id", id)
890                                    .add("charcase", charcase)
891                                    .add("enabled", enabled)
892                                    );
893                            _out.endTag("TableMatch");
894                    }
895                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
896                    {
897                            boolean _diff = true;
898                            TableMatch _cother = (TableMatch)_other;
899                            return _diff;
900                    }
901                    // BEGIN pass-through code block ---
902    public void validate(final AggRules rules,
903                                     final mondrian.recorder.MessageRecorder msgRecorder) {
904                    msgRecorder.pushContextName(getName());
905                    try {
906                        if ((pretemplate == null) && (posttemplate == null)) {
907                            String msg = "Must have at least one template non-null";
908                            msgRecorder.reportError(msg);
909                        }
910                        super.validate(rules, msgRecorder);
911                    } finally {
912                        msgRecorder.popContextName();
913                    }
914                }
915                public Recognizer.Matcher getMatcher(final String name) {
916                    return super.getMatcher(name);
917                }
918                    // END pass-through code block ---
919            }
920    
921            /**
922             * This allows one to create an element that matches against a
923             * single template, where the template is an attribute.
924             * While much loved, this is currently not used.
925             */
926            public static abstract class Mapper extends CaseMatcher
927            {
928                    public Mapper()
929                    {
930                    }
931    
932                    public Mapper(org.eigenbase.xom.DOMWrapper _def)
933                            throws org.eigenbase.xom.XOMException
934                    {
935                            try {
936                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
937                                    _parser = _parser;
938                                    template = (String)_parser.getAttribute("template", "String", null, null, true);
939                                    space = (String)_parser.getAttribute("space", "String", "_", null, false);
940                                    dot = (String)_parser.getAttribute("dot", "String", "_", null, false);
941                                    id = (String)_parser.getAttribute("id", "String", null, null, true);
942                                    charcase = (String)_parser.getAttribute("charcase", "String", "ignore", _charcase_values, false);
943                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
944                            } catch(org.eigenbase.xom.XOMException _ex) {
945                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
946                            }
947                    }
948    
949                    public String template;  // required attribute
950                    public String space;  // attribute default: _
951                    public String dot;  // attribute default: _
952    
953    
954                    public String getName()
955                    {
956                            return "Mapper";
957                    }
958    
959                    public void display(java.io.PrintWriter _out, int _indent)
960                    {
961                            _out.println(getName());
962                            displayAttribute(_out, "template", template, _indent+1);
963                            displayAttribute(_out, "space", space, _indent+1);
964                            displayAttribute(_out, "dot", dot, _indent+1);
965                            displayAttribute(_out, "id", id, _indent+1);
966                            displayAttribute(_out, "charcase", charcase, _indent+1);
967                            displayAttribute(_out, "enabled", enabled, _indent+1);
968                    }
969                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
970                    {
971                            _out.beginTag("(%Mapper;)", new org.eigenbase.xom.XMLAttrVector()
972                                    .add("template", template)
973                                    .add("space", space)
974                                    .add("dot", dot)
975                                    .add("id", id)
976                                    .add("charcase", charcase)
977                                    .add("enabled", enabled)
978                                    );
979                            _out.endTag("(%Mapper;)");
980                    }
981                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
982                    {
983                            boolean _diff = true;
984                            Mapper _cother = (Mapper)_other;
985                            _diff = _diff && displayAttributeDiff("template", template, _cother.template, _out, _indent+1);
986                            _diff = _diff && displayAttributeDiff("space", space, _cother.space, _out, _indent+1);
987                            _diff = _diff && displayAttributeDiff("dot", dot, _cother.dot, _out, _indent+1);
988                            return _diff;
989                    }
990                    // BEGIN pass-through code block ---
991    public String getTemplate() {
992                    return template;
993                }
994                public String getSpace() {
995                    return space;
996                }
997                public String getDot() {
998                    return dot;
999                }
1000                protected static final int BAD_ID = -1;
1001    
1002                protected String[] templateParts;
1003                protected int[] templateNamePos;
1004    
1005                /**
1006                 * It is hoped that no one will need to match more than 50 names
1007                 * in a template. Currently, this implementation, requires only 3.
1008                 */
1009                private static final int MAX_SIZE = 50;
1010    
1011                public void validate(final AggRules rules,
1012                                     final mondrian.recorder.MessageRecorder msgRecorder) {
1013                    msgRecorder.pushContextName(getName());
1014                    try {
1015                        super.validate(rules, msgRecorder);
1016    
1017                        String[] ss = new String[MAX_SIZE+1];
1018                        int[] poss = new int[MAX_SIZE];
1019    
1020                        String template = getTemplate();
1021                        int count = 0;
1022    
1023                        int end = 0;
1024                        int previousEnd = 0;
1025                        int start = template.indexOf("${", end);
1026                        while (count < MAX_SIZE) {
1027                            if (start == -1) {
1028                                if (count == 0) {
1029                                    // there are no ${} in template which
1030                                    // is an error
1031                                    String msg = "Bad template \"" +
1032                                        template +
1033                                        "\", no ${} entries";
1034                                    msgRecorder.reportError(msg);
1035                                    return;
1036                                }
1037                                // its OK, there are "count" ${}
1038                                templateNamePos = new int[count];
1039                                System.arraycopy(poss, 0, templateNamePos, 0, count);
1040    
1041                                ss[count++] =
1042                                    template.substring(end, template.length());
1043                                templateParts = new String[count];
1044                                System.arraycopy(ss, 0, templateParts, 0, count);
1045    
1046                                return;
1047                            }
1048    
1049                            previousEnd = end;
1050                            end = template.indexOf('}', start);
1051                            if (end == -1) {
1052                                // there was a "${" but not '}' in template
1053                                String msg = "Bad template \"" +
1054                                    template +
1055                                    "\", it had a \"${\", but no '}'";
1056                                msgRecorder.reportError(msg);
1057                                return;
1058                            }
1059    
1060                            String name = template.substring(start+2, end);
1061                            int pos = convertNameToID(name, msgRecorder);
1062                            if (pos == BAD_ID) {
1063                                return;
1064                            }
1065    
1066                            poss[count] = pos;
1067                            ss[count] = template.substring(previousEnd, start);
1068    
1069                            start = template.indexOf("${", end);
1070                            end++;
1071    
1072                            count++;
1073                        }
1074    
1075                    } finally {
1076                        msgRecorder.popContextName();
1077                    }
1078                }
1079    
1080    
1081                protected abstract String[] getTemplateNames();
1082    
1083                private int convertNameToID(final String name,
1084                                            final mondrian.recorder.MessageRecorder msgRecorder) {
1085    
1086                    if (name == null) {
1087                        String msg = "Template name is null";
1088                        msgRecorder.reportError(msg);
1089                        return BAD_ID;
1090                    }
1091    
1092                    String[] names = getTemplateNames();
1093                    for (int i = 0; i < names.length; i++) {
1094                        if (names[i].equals(name)) {
1095                            return i;
1096                        }
1097                    }
1098    
1099                    String msg = "Bad template name \"" +
1100                        name +
1101                        "\"";
1102                    msgRecorder.reportError(msg);
1103                    return BAD_ID;
1104                }
1105    
1106                public String getRegex(final String[] names) {
1107                    final String space = getSpace();
1108                    final String dot = getDot();
1109    
1110                    final StringBuilder buf = new StringBuilder();
1111    
1112                    //
1113                    // Remember that:
1114                    //      templateParts.length == templateNamePos.length+1
1115                    //
1116                    buf.append(templateParts[0]);
1117                    for (int i = 0; i < templateNamePos.length; i++) {
1118                        String n = names[templateNamePos[i]];
1119    
1120                        if (space != null) {
1121                            n = n.replaceAll(" ", space);
1122                        }
1123                        if (dot != null) {
1124                            n = n.replaceAll("\\.", dot);
1125                        }
1126    
1127                        buf.append(n);
1128                        buf.append(templateParts[i+1]);
1129                    }
1130    
1131                    String regex = buf.toString();
1132    
1133                    if (AggRules.getLogger().isDebugEnabled()) {
1134                        StringBuilder bf = new StringBuilder(64);
1135                        bf.append(getName());
1136                        bf.append(".getRegex:");
1137                        bf.append(" for names ");
1138                        for (int i = 0; i < names.length; i++) {
1139                            bf.append('"');
1140                            bf.append(names[i]);
1141                            bf.append('"');
1142                            if (i+1 < names.length) {
1143                                bf.append(", ");
1144                            }
1145                        }
1146                        bf.append(" regex is \"");
1147                        bf.append(regex);
1148                        bf.append('"');
1149    
1150                        String msg = bf.toString();
1151                        AggRules.getLogger().debug(msg);
1152                    }
1153                    return regex;
1154                }
1155    
1156                protected Recognizer.Matcher getMatcher(final String[] names) {
1157    
1158                    final String charcase = getCharCase();
1159                    final String regex;
1160                    int flag = 0;
1161    
1162                    if (charcase.equals("ignore")) {
1163                        // the case of name does not matter
1164                        // since the Pattern will be create to ignore case
1165                        regex = getRegex(names);
1166    
1167                        flag = java.util.regex.Pattern.CASE_INSENSITIVE;
1168    
1169                    } else if (charcase.equals("exact")) {
1170                        // the case of name is not changed
1171                        // since we are interested in exact case matching
1172                        regex = getRegex(names);
1173    
1174                    } else if (charcase.equals("upper")) {
1175                        // convert name to upper case
1176                        String[] ucNames = new String[names.length];
1177                        for (int i = 0; i < names.length; i++) {
1178                            ucNames[i] = names[i].toUpperCase();
1179                        }
1180    
1181                        regex = getRegex(ucNames);
1182    
1183                    } else {
1184                        // lower
1185                        // convert name to lower case
1186                        String[] lcNames = new String[names.length];
1187                        for (int i = 0; i < names.length; i++) {
1188                            lcNames[i] = names[i].toLowerCase();
1189                        }
1190    
1191                        regex = getRegex(lcNames);
1192    
1193                    }
1194                    final java.util.regex.Pattern pattern =
1195                        java.util.regex.Pattern.compile(regex, flag);
1196    
1197                    return new Recognizer.Matcher() {
1198                        public boolean matches(String name) {
1199                            boolean b = pattern.matcher(name).matches();
1200                            if (AggRules.getLogger().isDebugEnabled()) {
1201                                debug(name);
1202                            }
1203                            return b;
1204                        }
1205                        private void debug(String name) {
1206                            StringBuilder bf = new StringBuilder(64);
1207                            bf.append(Mapper.this.getName());
1208                            bf.append(".Matcher.matches:");
1209                            bf.append(" name \"");
1210                            bf.append(name);
1211                            bf.append("\" pattern \"");
1212                            bf.append(pattern.pattern());
1213                            bf.append("\"");
1214                            if ((pattern.flags() &
1215                                java.util.regex.Pattern.CASE_INSENSITIVE) != 0) {
1216                                bf.append(" case_insensitive");
1217                            }
1218    
1219                            String msg = bf.toString();
1220                            AggRules.getLogger().debug(msg);
1221                        }
1222                    };
1223    
1224                }
1225                    // END pass-through code block ---
1226            }
1227    
1228            /**
1229             * This element is used in a vector of child elements when
1230             * one wishes to have one or more regular expressions associated
1231             * with matching a given string. The parent element must
1232             * initialize Regex object by calling its validate method
1233             * passing in an array of template names.
1234             * The cdata content is a regular expression with embedded
1235             * template names. Each name must be surrounded by "${" and "}".
1236             * Each time this is used for a new set of names, the names
1237             * replace the template names in the regular expression.
1238             * For example, if the charcase="lower", the attribute
1239             * dot="-" (the default dot value is "_"), the template names are:
1240             * "city", "state", and "country"
1241             * and the cdata is:
1242             * .*_${country}_.*_${city}
1243             * Then when the names:
1244             * "San Francisco", "California", and "U.S.A"
1245             * are passed in, the regular expression becomes:
1246             * .*_u-s-a_.*_san_francisco
1247             * Note that a given template name can only appear ONCE in the
1248             * template content, the cdata content. As an example, the
1249             * following cdata template is not supported:
1250             * .*_${country}_.*_${city}_${country}
1251             */
1252            public static class Regex extends CaseMatcher
1253            {
1254                    public Regex()
1255                    {
1256                    }
1257    
1258                    public Regex(org.eigenbase.xom.DOMWrapper _def)
1259                            throws org.eigenbase.xom.XOMException
1260                    {
1261                            try {
1262                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
1263                                    _parser = _parser;
1264                                    space = (String)_parser.getAttribute("space", "String", "_", null, false);
1265                                    dot = (String)_parser.getAttribute("dot", "String", "_", null, false);
1266                                    id = (String)_parser.getAttribute("id", "String", null, null, true);
1267                                    charcase = (String)_parser.getAttribute("charcase", "String", "ignore", _charcase_values, false);
1268                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
1269                                    cdata = _parser.getText();
1270                            } catch(org.eigenbase.xom.XOMException _ex) {
1271                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
1272                            }
1273                    }
1274    
1275                    public String space;  // attribute default: _
1276                    public String dot;  // attribute default: _
1277    
1278                    public String cdata;  // All text goes here
1279                    public String getName()
1280                    {
1281                            return "Regex";
1282                    }
1283    
1284                    public void display(java.io.PrintWriter _out, int _indent)
1285                    {
1286                            _out.println(getName());
1287                            displayAttribute(_out, "space", space, _indent+1);
1288                            displayAttribute(_out, "dot", dot, _indent+1);
1289                            displayAttribute(_out, "id", id, _indent+1);
1290                            displayAttribute(_out, "charcase", charcase, _indent+1);
1291                            displayAttribute(_out, "enabled", enabled, _indent+1);
1292                            displayString(_out, "cdata", cdata, _indent+1);
1293                    }
1294                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
1295                    {
1296                            _out.beginTag("Regex", new org.eigenbase.xom.XMLAttrVector()
1297                                    .add("space", space)
1298                                    .add("dot", dot)
1299                                    .add("id", id)
1300                                    .add("charcase", charcase)
1301                                    .add("enabled", enabled)
1302                                    );
1303                            _out.cdata(cdata);
1304                            _out.endTag("Regex");
1305                    }
1306                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
1307                    {
1308                            boolean _diff = true;
1309                            Regex _cother = (Regex)_other;
1310                            _diff = _diff && displayAttributeDiff("space", space, _cother.space, _out, _indent+1);
1311                            _diff = _diff && displayAttributeDiff("dot", dot, _cother.dot, _out, _indent+1);
1312                            _diff = _diff && displayStringDiff("cdata", cdata, _cother.cdata, _out, _indent+1);
1313                            return _diff;
1314                    }
1315                    // BEGIN pass-through code block ---
1316    public String getSpace() {
1317                    return space;
1318                }
1319                public String getDot() {
1320                    return dot;
1321                }
1322                public String getTemplate() {
1323                    return cdata;
1324                }
1325    
1326                protected static final int BAD_ID = -1;
1327    
1328                protected String[] templateParts;
1329    
1330                /**
1331                 * This is a one-to-one mapping, each template name can appear
1332                 * at most once.
1333                 */
1334                protected int[] templateNamePos;
1335    
1336                /**
1337                 * It is hoped that no one will need to match more than 50 names
1338                 * in a template. Currently, this implementation, requires only 3.
1339                 */
1340                private static final int MAX_SIZE = 50;
1341    
1342                public void validate(final AggRules rules,
1343                                     final String[] templateNames,
1344                                     final mondrian.recorder.MessageRecorder msgRecorder) {
1345                    msgRecorder.pushContextName(getName());
1346                    try {
1347                        super.validate(rules, msgRecorder);
1348    
1349                        String[] ss = new String[MAX_SIZE+1];
1350                        int[] poss = new int[MAX_SIZE];
1351    
1352                        String template = getTemplate();
1353                        int count = 0;
1354    
1355                        int end = 0;
1356                        int previousEnd = 0;
1357                        int start = template.indexOf("${", end);
1358                        // if no templateNames, then there better not be
1359                        // any ${}s
1360                        if (templateNames.length == 0) {
1361                            if (start == -1) {
1362                                // everything is ok
1363                                templateParts = new String[1];
1364                                templateParts[0] = template;
1365                                templateNamePos = new int[0];
1366                            } else {
1367                                String msg = "Bad template \"" +
1368                                    template +
1369                                    "\", no ${} entries but there are "+
1370                                    "template names" ;
1371                                msgRecorder.reportError(msg);
1372                            }
1373                            return;
1374                        }
1375                        while (count < MAX_SIZE) {
1376                            if (start == -1) {
1377                                if (count == 0) {
1378                                    // there are no ${} in template which
1379                                    // is an error
1380                                    String msg = "Bad template \"" +
1381                                        template +
1382                                        "\", no ${} entries";
1383                                    msgRecorder.reportError(msg);
1384                                    return;
1385                                }
1386                                // its OK, there are "count" ${}
1387                                templateNamePos = new int[count];
1388                                System.arraycopy(poss, 0, templateNamePos, 0, count);
1389    
1390                                ss[count++] =
1391                                    template.substring(end, template.length());
1392                                templateParts = new String[count];
1393                                System.arraycopy(ss, 0, templateParts, 0, count);
1394    
1395                                return;
1396                            }
1397    
1398                            previousEnd = end;
1399                            end = template.indexOf('}', start);
1400                            if (end == -1) {
1401                                // there was a "${" but not '}' in template
1402                                String msg = "Bad template \"" +
1403                                    template +
1404                                    "\", it had a \"${\", but no '}'";
1405                                msgRecorder.reportError(msg);
1406                                return;
1407                            }
1408    
1409                            String name = template.substring(start+2, end);
1410                            int pos = convertNameToID(name,
1411                                                      templateNames,
1412                                                      msgRecorder);
1413                            if (pos == BAD_ID) {
1414                                return;
1415                            }
1416    
1417                            poss[count] = pos;
1418                            ss[count] = template.substring(previousEnd, start);
1419    
1420                            start = template.indexOf("${", end);
1421                            end++;
1422    
1423                            count++;
1424                        }
1425    
1426                    } finally {
1427                        msgRecorder.popContextName();
1428                    }
1429                }
1430                private int convertNameToID(final String name,
1431                                            final String[] templateNames,
1432                                            final mondrian.recorder.MessageRecorder msgRecorder) {
1433    
1434                    if (name == null) {
1435                        String msg = "Template name is null";
1436                        msgRecorder.reportError(msg);
1437                        return BAD_ID;
1438                    }
1439    
1440                    for (int i = 0; i < templateNames.length; i++) {
1441                        if (templateNames[i].equals(name)) {
1442                            return i;
1443                        }
1444                    }
1445    
1446                    String msg = "Bad template name \"" +
1447                        name +
1448                        "\"";
1449                    msgRecorder.reportError(msg);
1450                    return BAD_ID;
1451                }
1452                public String getRegex(final String[] names) {
1453                    final String space = getSpace();
1454                    final String dot = getDot();
1455    
1456                    final StringBuilder buf = new StringBuilder();
1457    
1458                    //
1459                    // Remember that:
1460                    //      templateParts.length == templateNamePos.length+1
1461                    //
1462                    buf.append(templateParts[0]);
1463                    for (int i = 0; i < templateNamePos.length; i++) {
1464                        String n = names[templateNamePos[i]];
1465                        if (n == null) {
1466                            // its ok for a name to be null, it just
1467                            // eliminates the current regex from consideration
1468                            return null;
1469                        }
1470    
1471                        if (space != null) {
1472                            n = n.replaceAll(" ", space);
1473                        }
1474                        if (dot != null) {
1475                            n = n.replaceAll("\\.", dot);
1476                        }
1477    
1478                        buf.append(n);
1479                        buf.append(templateParts[i+1]);
1480                    }
1481    
1482                    String regex = buf.toString();
1483    
1484                    if (AggRules.getLogger().isDebugEnabled()) {
1485                        StringBuilder bf = new StringBuilder(64);
1486                        bf.append(getName());
1487                        bf.append(".getRegex:");
1488                        bf.append(" for names ");
1489                        for (int i = 0; i < names.length; i++) {
1490                            bf.append('"');
1491                            bf.append(names[i]);
1492                            bf.append('"');
1493                            if (i+1 < names.length) {
1494                                bf.append(", ");
1495                            }
1496                        }
1497                        bf.append(" regex is \"");
1498                        bf.append(regex);
1499                        bf.append('"');
1500    
1501                        String msg = bf.toString();
1502                        AggRules.getLogger().debug(msg);
1503                    }
1504    
1505                    return regex;
1506                }
1507                protected java.util.regex.Pattern getPattern(final String[] names) {
1508    
1509                    final String charcase = getCharCase();
1510    
1511                    if (charcase.equals("ignore")) {
1512                        // the case of name does not matter
1513                        // since the Pattern will be create to ignore case
1514                        final String regex = getRegex(names);
1515                        if (regex == null) {
1516                            return null;
1517                        }
1518    
1519                        final java.util.regex.Pattern pattern =
1520                            java.util.regex.Pattern.compile(regex,
1521                                java.util.regex.Pattern.CASE_INSENSITIVE);
1522    
1523                        return pattern;
1524    
1525                    } else if (charcase.equals("exact")) {
1526                        // the case of name is not changed
1527                        // since we are interested in exact case matching
1528                        final String regex = getRegex(names);
1529                        if (regex == null) {
1530                            return null;
1531                        }
1532    
1533                        final java.util.regex.Pattern pattern =
1534                            java.util.regex.Pattern.compile(regex);
1535    
1536                        return pattern;
1537    
1538                    } else if (charcase.equals("upper")) {
1539                        // convert name to upper case
1540                        String[] ucNames = new String[names.length];
1541                        for (int i = 0; i < names.length; i++) {
1542                            String name = names[i];
1543                            ucNames[i] = (name == null)
1544                                ? null: name.toUpperCase();
1545                        }
1546    
1547                        final String regex = getRegex(ucNames);
1548                        if (regex == null) {
1549                            return null;
1550                        }
1551    
1552                        final java.util.regex.Pattern pattern =
1553                            java.util.regex.Pattern.compile(regex);
1554    
1555                        return pattern;
1556    
1557                    } else {
1558                        // lower
1559                        // convert name to lower case
1560                        String[] lcNames = new String[names.length];
1561                        for (int i = 0; i < names.length; i++) {
1562                            String name = names[i];
1563                            lcNames[i] = (name == null)
1564                                ? null: name.toLowerCase();
1565                        }
1566    
1567                        final String regex = getRegex(lcNames);
1568                        if (regex == null) {
1569                            return null;
1570                        }
1571    
1572                        final java.util.regex.Pattern pattern =
1573                            java.util.regex.Pattern.compile(regex);
1574    
1575                        return pattern;
1576                    }
1577                }
1578                    // END pass-through code block ---
1579            }
1580    
1581            /**
1582             */
1583            public static abstract class RegexMapper extends Base
1584            {
1585                    public RegexMapper()
1586                    {
1587                    }
1588    
1589                    public RegexMapper(org.eigenbase.xom.DOMWrapper _def)
1590                            throws org.eigenbase.xom.XOMException
1591                    {
1592                            try {
1593                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
1594                                    _parser = _parser;
1595                                    org.eigenbase.xom.NodeDef[] _tempArray = null;
1596                                    _tempArray = _tempArray;
1597                                    id = (String)_parser.getAttribute("id", "String", null, null, true);
1598                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
1599                                    _tempArray = _parser.getArray(Regex.class, 0, 0);
1600                                    regexs = new Regex[_tempArray.length];
1601                                    for(int _i=0; _i<regexs.length; _i++)
1602                                            regexs[_i] = (Regex)_tempArray[_i];
1603                            } catch(org.eigenbase.xom.XOMException _ex) {
1604                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
1605                            }
1606                    }
1607    
1608                    public String id;  // required attribute
1609    
1610                    /**
1611                     * This is an array of Regex. A match occurs if any one of
1612                     * the Regex matches; it is the equivalent of or-ing the
1613                     * regular expressions together. A candidate string is processed
1614                     * sequentially by each Regex in their document order until
1615                     * one matches. In none match, well, none match.
1616                     */
1617                    public Regex[] regexs;  //optional array
1618    
1619                    public String getName()
1620                    {
1621                            return "RegexMapper";
1622                    }
1623    
1624                    public void display(java.io.PrintWriter _out, int _indent)
1625                    {
1626                            _out.println(getName());
1627                            displayAttribute(_out, "id", id, _indent+1);
1628                            displayAttribute(_out, "enabled", enabled, _indent+1);
1629                            displayElementArray(_out, "regexs", regexs, _indent+1);
1630                    }
1631                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
1632                    {
1633                            _out.beginTag("(%RegexMapper;)", new org.eigenbase.xom.XMLAttrVector()
1634                                    .add("id", id)
1635                                    .add("enabled", enabled)
1636                                    );
1637                            displayXMLElementArray(_out, regexs);
1638                            _out.endTag("(%RegexMapper;)");
1639                    }
1640                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
1641                    {
1642                            boolean _diff = true;
1643                            RegexMapper _cother = (RegexMapper)_other;
1644                            _diff = _diff && displayAttributeDiff("id", id, _cother.id, _out, _indent+1);
1645                            _diff = _diff && displayElementArrayDiff("regexs", regexs, _cother.regexs, _out, _indent+1);
1646                            return _diff;
1647                    }
1648                    // BEGIN pass-through code block ---
1649    protected String getTag() {
1650                    return id;
1651                }
1652    
1653                public void validate(final AggRules rules,
1654                                     final mondrian.recorder.MessageRecorder msgRecorder) {
1655                    msgRecorder.pushContextName(getName());
1656                    try {
1657    
1658                        String[] templateNames = getTemplateNames();
1659    
1660                        for (int i = 0; i < regexs.length; i++) {
1661                            Regex regex = regexs[i];
1662                            regex.validate(rules, templateNames, msgRecorder);
1663                        }
1664    
1665                    } finally {
1666                        msgRecorder.popContextName();
1667                    }
1668                }
1669    
1670    
1671                /**
1672                 * This must be defined in derived classes. It returns an array of
1673                 * symbolic names that are the symbolic names allowed to appear
1674                 * in the regular expression templates.
1675                 *
1676                 * @return array of symbol names
1677                 */
1678                protected abstract String[] getTemplateNames();
1679    
1680                protected Recognizer.Matcher getMatcher(final String[] names) {
1681    
1682                    final java.util.regex.Pattern[] patterns =
1683                        new java.util.regex.Pattern[regexs.length];
1684    
1685                    for (int i = 0; i < regexs.length; i++) {
1686                        Regex regex = regexs[i];
1687                        patterns[i] = regex.getPattern(names);
1688                    }
1689    
1690                    return new Recognizer.Matcher() {
1691                        public boolean matches(String name) {
1692                            for (int i = 0; i < patterns.length; i++) {
1693                                java.util.regex.Pattern pattern = patterns[i];
1694                                if ((pattern != null) &&
1695                                        pattern.matcher(name).matches()) {
1696    
1697                                    if (AggRules.getLogger().isDebugEnabled()) {
1698                                        debug(name, pattern);
1699                                    }
1700    
1701                                    return true;
1702                                }
1703                            }
1704                            return false;
1705                        }
1706                        private void debug(String name, java.util.regex.Pattern p) {
1707                            StringBuilder bf = new StringBuilder(64);
1708                            bf.append("DefaultDef.RegexMapper");
1709                            bf.append(".Matcher.matches:");
1710                            bf.append(" name \"");
1711                            bf.append(name);
1712                            bf.append("\" matches regex \"");
1713                            bf.append(p.pattern());
1714                            bf.append("\"");
1715                            if ((p.flags() &
1716                                java.util.regex.Pattern.CASE_INSENSITIVE) != 0) {
1717                                bf.append(" case_insensitive");
1718                            }
1719    
1720                            String msg = bf.toString();
1721                            AggRules.getLogger().debug(msg);
1722                        }
1723                    };
1724                }
1725                    // END pass-through code block ---
1726            }
1727    
1728            public static abstract class Ref extends Base
1729            {
1730                    public Ref()
1731                    {
1732                    }
1733    
1734                    public Ref(org.eigenbase.xom.DOMWrapper _def)
1735                            throws org.eigenbase.xom.XOMException
1736                    {
1737                            try {
1738                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
1739                                    _parser = _parser;
1740                                    refId = (String)_parser.getAttribute("refId", "String", null, null, true);
1741                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
1742                            } catch(org.eigenbase.xom.XOMException _ex) {
1743                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
1744                            }
1745                    }
1746    
1747                    public String refId;  // required attribute
1748    
1749    
1750                    public String getName()
1751                    {
1752                            return "Ref";
1753                    }
1754    
1755                    public void display(java.io.PrintWriter _out, int _indent)
1756                    {
1757                            _out.println(getName());
1758                            displayAttribute(_out, "refId", refId, _indent+1);
1759                            displayAttribute(_out, "enabled", enabled, _indent+1);
1760                    }
1761                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
1762                    {
1763                            _out.beginTag("(%Ref;)", new org.eigenbase.xom.XMLAttrVector()
1764                                    .add("refId", refId)
1765                                    .add("enabled", enabled)
1766                                    );
1767                            _out.endTag("(%Ref;)");
1768                    }
1769                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
1770                    {
1771                            boolean _diff = true;
1772                            Ref _cother = (Ref)_other;
1773                            _diff = _diff && displayAttributeDiff("refId", refId, _cother.refId, _out, _indent+1);
1774                            return _diff;
1775                    }
1776                    // BEGIN pass-through code block ---
1777    protected String getTag() {
1778                    return getRefId();
1779                }
1780                public String getRefId() {
1781                    return refId;
1782                }
1783                    // END pass-through code block ---
1784            }
1785    
1786            public static class LevelMapRef extends Ref
1787            {
1788                    public LevelMapRef()
1789                    {
1790                    }
1791    
1792                    public LevelMapRef(org.eigenbase.xom.DOMWrapper _def)
1793                            throws org.eigenbase.xom.XOMException
1794                    {
1795                            try {
1796                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
1797                                    _parser = _parser;
1798                                    refId = (String)_parser.getAttribute("refId", "String", null, null, true);
1799                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
1800                            } catch(org.eigenbase.xom.XOMException _ex) {
1801                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
1802                            }
1803                    }
1804    
1805    
1806    
1807                    public String getName()
1808                    {
1809                            return "LevelMapRef";
1810                    }
1811    
1812                    public void display(java.io.PrintWriter _out, int _indent)
1813                    {
1814                            _out.println(getName());
1815                            displayAttribute(_out, "refId", refId, _indent+1);
1816                            displayAttribute(_out, "enabled", enabled, _indent+1);
1817                    }
1818                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
1819                    {
1820                            _out.beginTag("LevelMapRef", new org.eigenbase.xom.XMLAttrVector()
1821                                    .add("refId", refId)
1822                                    .add("enabled", enabled)
1823                                    );
1824                            _out.endTag("LevelMapRef");
1825                    }
1826                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
1827                    {
1828                            boolean _diff = true;
1829                            LevelMapRef _cother = (LevelMapRef)_other;
1830                            return _diff;
1831                    }
1832                    // BEGIN pass-through code block ---
1833    public void validate(final AggRules rules,
1834                                     final mondrian.recorder.MessageRecorder msgRecorder) {
1835                    msgRecorder.pushContextName(getName());
1836                    try {
1837                        if (! rules.hasLevelMap(getRefId())) {
1838                            String msg = "No LevelMap has id equal to refid \"" +
1839                                getRefId() +
1840                                "\"";
1841                            msgRecorder.reportError(msg);
1842                        }
1843                    } finally {
1844                        msgRecorder.popContextName();
1845                    }
1846                }
1847                    // END pass-through code block ---
1848            }
1849    
1850            public static class MeasureMapRef extends Ref
1851            {
1852                    public MeasureMapRef()
1853                    {
1854                    }
1855    
1856                    public MeasureMapRef(org.eigenbase.xom.DOMWrapper _def)
1857                            throws org.eigenbase.xom.XOMException
1858                    {
1859                            try {
1860                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
1861                                    _parser = _parser;
1862                                    refId = (String)_parser.getAttribute("refId", "String", null, null, true);
1863                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
1864                            } catch(org.eigenbase.xom.XOMException _ex) {
1865                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
1866                            }
1867                    }
1868    
1869    
1870    
1871                    public String getName()
1872                    {
1873                            return "MeasureMapRef";
1874                    }
1875    
1876                    public void display(java.io.PrintWriter _out, int _indent)
1877                    {
1878                            _out.println(getName());
1879                            displayAttribute(_out, "refId", refId, _indent+1);
1880                            displayAttribute(_out, "enabled", enabled, _indent+1);
1881                    }
1882                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
1883                    {
1884                            _out.beginTag("MeasureMapRef", new org.eigenbase.xom.XMLAttrVector()
1885                                    .add("refId", refId)
1886                                    .add("enabled", enabled)
1887                                    );
1888                            _out.endTag("MeasureMapRef");
1889                    }
1890                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
1891                    {
1892                            boolean _diff = true;
1893                            MeasureMapRef _cother = (MeasureMapRef)_other;
1894                            return _diff;
1895                    }
1896                    // BEGIN pass-through code block ---
1897    public void validate(final AggRules rules,
1898                                     final mondrian.recorder.MessageRecorder msgRecorder) {
1899                    msgRecorder.pushContextName(getName());
1900                    try {
1901                        if (! rules.hasMeasureMap(getRefId())) {
1902                            String msg = "No MeasureMap has id equal to refid \"" +
1903                                getRefId() +
1904                                "\"";
1905                            msgRecorder.reportError(msg);
1906                        }
1907                    } finally {
1908                        msgRecorder.popContextName();
1909                    }
1910                }
1911                    // END pass-through code block ---
1912            }
1913    
1914            public static class IgnoreMapRef extends Ref
1915            {
1916                    public IgnoreMapRef()
1917                    {
1918                    }
1919    
1920                    public IgnoreMapRef(org.eigenbase.xom.DOMWrapper _def)
1921                            throws org.eigenbase.xom.XOMException
1922                    {
1923                            try {
1924                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
1925                                    _parser = _parser;
1926                                    refId = (String)_parser.getAttribute("refId", "String", null, null, true);
1927                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
1928                            } catch(org.eigenbase.xom.XOMException _ex) {
1929                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
1930                            }
1931                    }
1932    
1933    
1934    
1935                    public String getName()
1936                    {
1937                            return "IgnoreMapRef";
1938                    }
1939    
1940                    public void display(java.io.PrintWriter _out, int _indent)
1941                    {
1942                            _out.println(getName());
1943                            displayAttribute(_out, "refId", refId, _indent+1);
1944                            displayAttribute(_out, "enabled", enabled, _indent+1);
1945                    }
1946                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
1947                    {
1948                            _out.beginTag("IgnoreMapRef", new org.eigenbase.xom.XMLAttrVector()
1949                                    .add("refId", refId)
1950                                    .add("enabled", enabled)
1951                                    );
1952                            _out.endTag("IgnoreMapRef");
1953                    }
1954                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
1955                    {
1956                            boolean _diff = true;
1957                            IgnoreMapRef _cother = (IgnoreMapRef)_other;
1958                            return _diff;
1959                    }
1960                    // BEGIN pass-through code block ---
1961    public void validate(final AggRules rules,
1962                                     final mondrian.recorder.MessageRecorder msgRecorder) {
1963                    msgRecorder.pushContextName(getName());
1964                    try {
1965                        if (! rules.hasIgnoreMap(getRefId())) {
1966                            String msg = "No IgnoreMap has id equal to refid \"" +
1967                                getRefId() +
1968                                "\"";
1969                            msgRecorder.reportError(msg);
1970                        }
1971                    } finally {
1972                        msgRecorder.popContextName();
1973                    }
1974                }
1975                    // END pass-through code block ---
1976            }
1977    
1978            public static class FactCountMatchRef extends Ref
1979            {
1980                    public FactCountMatchRef()
1981                    {
1982                    }
1983    
1984                    public FactCountMatchRef(org.eigenbase.xom.DOMWrapper _def)
1985                            throws org.eigenbase.xom.XOMException
1986                    {
1987                            try {
1988                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
1989                                    _parser = _parser;
1990                                    refId = (String)_parser.getAttribute("refId", "String", null, null, true);
1991                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
1992                            } catch(org.eigenbase.xom.XOMException _ex) {
1993                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
1994                            }
1995                    }
1996    
1997    
1998    
1999                    public String getName()
2000                    {
2001                            return "FactCountMatchRef";
2002                    }
2003    
2004                    public void display(java.io.PrintWriter _out, int _indent)
2005                    {
2006                            _out.println(getName());
2007                            displayAttribute(_out, "refId", refId, _indent+1);
2008                            displayAttribute(_out, "enabled", enabled, _indent+1);
2009                    }
2010                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
2011                    {
2012                            _out.beginTag("FactCountMatchRef", new org.eigenbase.xom.XMLAttrVector()
2013                                    .add("refId", refId)
2014                                    .add("enabled", enabled)
2015                                    );
2016                            _out.endTag("FactCountMatchRef");
2017                    }
2018                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
2019                    {
2020                            boolean _diff = true;
2021                            FactCountMatchRef _cother = (FactCountMatchRef)_other;
2022                            return _diff;
2023                    }
2024                    // BEGIN pass-through code block ---
2025    public void validate(final AggRules rules,
2026                                     final mondrian.recorder.MessageRecorder msgRecorder) {
2027                    msgRecorder.pushContextName(getName());
2028                    try {
2029                        if (! rules.hasFactCountMatch(getRefId())) {
2030                            String msg = "No FactCountMatch has id equal to refid \"" +
2031                                getRefId() +
2032                                "\"";
2033                            msgRecorder.reportError(msg);
2034                        }
2035                    } finally {
2036                        msgRecorder.popContextName();
2037                    }
2038                }
2039                    // END pass-through code block ---
2040            }
2041    
2042            public static class ForeignKeyMatchRef extends Ref
2043            {
2044                    public ForeignKeyMatchRef()
2045                    {
2046                    }
2047    
2048                    public ForeignKeyMatchRef(org.eigenbase.xom.DOMWrapper _def)
2049                            throws org.eigenbase.xom.XOMException
2050                    {
2051                            try {
2052                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
2053                                    _parser = _parser;
2054                                    refId = (String)_parser.getAttribute("refId", "String", null, null, true);
2055                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
2056                            } catch(org.eigenbase.xom.XOMException _ex) {
2057                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
2058                            }
2059                    }
2060    
2061    
2062    
2063                    public String getName()
2064                    {
2065                            return "ForeignKeyMatchRef";
2066                    }
2067    
2068                    public void display(java.io.PrintWriter _out, int _indent)
2069                    {
2070                            _out.println(getName());
2071                            displayAttribute(_out, "refId", refId, _indent+1);
2072                            displayAttribute(_out, "enabled", enabled, _indent+1);
2073                    }
2074                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
2075                    {
2076                            _out.beginTag("ForeignKeyMatchRef", new org.eigenbase.xom.XMLAttrVector()
2077                                    .add("refId", refId)
2078                                    .add("enabled", enabled)
2079                                    );
2080                            _out.endTag("ForeignKeyMatchRef");
2081                    }
2082                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
2083                    {
2084                            boolean _diff = true;
2085                            ForeignKeyMatchRef _cother = (ForeignKeyMatchRef)_other;
2086                            return _diff;
2087                    }
2088                    // BEGIN pass-through code block ---
2089    public void validate(final AggRules rules,
2090                                     final mondrian.recorder.MessageRecorder msgRecorder) {
2091                    msgRecorder.pushContextName(getName());
2092                    try {
2093                        if (! rules.hasForeignKeyMatch(getRefId())) {
2094                            String msg = "No ForeignKeyMatch has id equal to refid \"" +
2095                                getRefId() +
2096                                "\"";
2097                            msgRecorder.reportError(msg);
2098                        }
2099                    } finally {
2100                        msgRecorder.popContextName();
2101                    }
2102                }
2103                    // END pass-through code block ---
2104            }
2105    
2106            public static class TableMatchRef extends Ref
2107            {
2108                    public TableMatchRef()
2109                    {
2110                    }
2111    
2112                    public TableMatchRef(org.eigenbase.xom.DOMWrapper _def)
2113                            throws org.eigenbase.xom.XOMException
2114                    {
2115                            try {
2116                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
2117                                    _parser = _parser;
2118                                    refId = (String)_parser.getAttribute("refId", "String", null, null, true);
2119                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
2120                            } catch(org.eigenbase.xom.XOMException _ex) {
2121                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
2122                            }
2123                    }
2124    
2125    
2126    
2127                    public String getName()
2128                    {
2129                            return "TableMatchRef";
2130                    }
2131    
2132                    public void display(java.io.PrintWriter _out, int _indent)
2133                    {
2134                            _out.println(getName());
2135                            displayAttribute(_out, "refId", refId, _indent+1);
2136                            displayAttribute(_out, "enabled", enabled, _indent+1);
2137                    }
2138                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
2139                    {
2140                            _out.beginTag("TableMatchRef", new org.eigenbase.xom.XMLAttrVector()
2141                                    .add("refId", refId)
2142                                    .add("enabled", enabled)
2143                                    );
2144                            _out.endTag("TableMatchRef");
2145                    }
2146                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
2147                    {
2148                            boolean _diff = true;
2149                            TableMatchRef _cother = (TableMatchRef)_other;
2150                            return _diff;
2151                    }
2152                    // BEGIN pass-through code block ---
2153    public void validate(final AggRules rules,
2154                                     final mondrian.recorder.MessageRecorder msgRecorder) {
2155                    msgRecorder.pushContextName(getName());
2156                    try {
2157                        if (! rules.hasTableMatch(getRefId())) {
2158                            String msg = "No TableMatch has id equal to refid \"" +
2159                                getRefId() +
2160                                "\"";
2161                            msgRecorder.reportError(msg);
2162                        }
2163                    } finally {
2164                        msgRecorder.popContextName();
2165                    }
2166                }
2167                    // END pass-through code block ---
2168            }
2169    
2170            /**
2171             * This is the template that maps from a combination of level
2172             * usage_prefix
2173             * hierarchy_name
2174             * level_name
2175             * level_column_name
2176             */
2177            public static class LevelMap extends RegexMapper
2178            {
2179                    public LevelMap()
2180                    {
2181                    }
2182    
2183                    public LevelMap(org.eigenbase.xom.DOMWrapper _def)
2184                            throws org.eigenbase.xom.XOMException
2185                    {
2186                            try {
2187                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
2188                                    _parser = _parser;
2189                                    org.eigenbase.xom.NodeDef[] _tempArray = null;
2190                                    _tempArray = _tempArray;
2191                                    id = (String)_parser.getAttribute("id", "String", null, null, true);
2192                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
2193                                    _tempArray = _parser.getArray(Regex.class, 0, 0);
2194                                    regexs = new Regex[_tempArray.length];
2195                                    for(int _i=0; _i<regexs.length; _i++)
2196                                            regexs[_i] = (Regex)_tempArray[_i];
2197                            } catch(org.eigenbase.xom.XOMException _ex) {
2198                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
2199                            }
2200                    }
2201    
2202    
2203    
2204                    public String getName()
2205                    {
2206                            return "LevelMap";
2207                    }
2208    
2209                    public void display(java.io.PrintWriter _out, int _indent)
2210                    {
2211                            _out.println(getName());
2212                            displayAttribute(_out, "id", id, _indent+1);
2213                            displayAttribute(_out, "enabled", enabled, _indent+1);
2214                            displayElementArray(_out, "regexs", regexs, _indent+1);
2215                    }
2216                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
2217                    {
2218                            _out.beginTag("LevelMap", new org.eigenbase.xom.XMLAttrVector()
2219                                    .add("id", id)
2220                                    .add("enabled", enabled)
2221                                    );
2222                            displayXMLElementArray(_out, regexs);
2223                            _out.endTag("LevelMap");
2224                    }
2225                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
2226                    {
2227                            boolean _diff = true;
2228                            LevelMap _cother = (LevelMap)_other;
2229                            _diff = _diff && displayElementArrayDiff("regexs", regexs, _cother.regexs, _out, _indent+1);
2230                            return _diff;
2231                    }
2232                    // BEGIN pass-through code block ---
2233    private static final String[] TEMPLATE_NAMES = new String[] {
2234                    "usage_prefix",
2235                    "hierarchy_name",
2236                    "level_name",
2237                    "level_column_name"
2238                };
2239                protected String[] getTemplateNames() {
2240                    return TEMPLATE_NAMES;
2241                }
2242    
2243                protected Recognizer.Matcher getMatcher(
2244                                                final String usagePrefix,
2245                                                final String hierarchyName,
2246                                                final String levelName,
2247                                                final String levelColumnName) {
2248                    return getMatcher(new String[] {
2249                        usagePrefix,
2250                        hierarchyName,
2251                        levelName,
2252                        levelColumnName
2253                    });
2254                }
2255                    // END pass-through code block ---
2256            }
2257    
2258            /**
2259             * This is the template that maps from a combination of measure
2260             * measure_name,
2261             * measure_column_name, and
2262             * aggregate_name ("count", "sum", "avg", "min", "max",
2263             * "distinct-count").
2264             */
2265            public static class MeasureMap extends RegexMapper
2266            {
2267                    public MeasureMap()
2268                    {
2269                    }
2270    
2271                    public MeasureMap(org.eigenbase.xom.DOMWrapper _def)
2272                            throws org.eigenbase.xom.XOMException
2273                    {
2274                            try {
2275                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
2276                                    _parser = _parser;
2277                                    org.eigenbase.xom.NodeDef[] _tempArray = null;
2278                                    _tempArray = _tempArray;
2279                                    id = (String)_parser.getAttribute("id", "String", null, null, true);
2280                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
2281                                    _tempArray = _parser.getArray(Regex.class, 0, 0);
2282                                    regexs = new Regex[_tempArray.length];
2283                                    for(int _i=0; _i<regexs.length; _i++)
2284                                            regexs[_i] = (Regex)_tempArray[_i];
2285                            } catch(org.eigenbase.xom.XOMException _ex) {
2286                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
2287                            }
2288                    }
2289    
2290    
2291    
2292                    public String getName()
2293                    {
2294                            return "MeasureMap";
2295                    }
2296    
2297                    public void display(java.io.PrintWriter _out, int _indent)
2298                    {
2299                            _out.println(getName());
2300                            displayAttribute(_out, "id", id, _indent+1);
2301                            displayAttribute(_out, "enabled", enabled, _indent+1);
2302                            displayElementArray(_out, "regexs", regexs, _indent+1);
2303                    }
2304                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
2305                    {
2306                            _out.beginTag("MeasureMap", new org.eigenbase.xom.XMLAttrVector()
2307                                    .add("id", id)
2308                                    .add("enabled", enabled)
2309                                    );
2310                            displayXMLElementArray(_out, regexs);
2311                            _out.endTag("MeasureMap");
2312                    }
2313                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
2314                    {
2315                            boolean _diff = true;
2316                            MeasureMap _cother = (MeasureMap)_other;
2317                            _diff = _diff && displayElementArrayDiff("regexs", regexs, _cother.regexs, _out, _indent+1);
2318                            return _diff;
2319                    }
2320                    // BEGIN pass-through code block ---
2321    private static final String[] TEMPLATE_NAMES = new String[] {
2322                    "measure_name",
2323                    "measure_column_name",
2324                    "aggregate_name"
2325                };
2326                protected String[] getTemplateNames() {
2327                    return TEMPLATE_NAMES;
2328                }
2329                protected Recognizer.Matcher getMatcher(
2330                                                final String measureName,
2331                                                final String measuerColumnName,
2332                                                final String aggregateName) {
2333                    return getMatcher(new String[] {
2334                        measureName,
2335                        measuerColumnName,
2336                        aggregateName
2337                    });
2338                }
2339                    // END pass-through code block ---
2340            }
2341    
2342            /**
2343             * This is the template used to specify columns to be ignored.
2344             * There are NO template names. One simply uses a regular
2345             * expression.
2346             */
2347            public static class IgnoreMap extends RegexMapper
2348            {
2349                    public IgnoreMap()
2350                    {
2351                    }
2352    
2353                    public IgnoreMap(org.eigenbase.xom.DOMWrapper _def)
2354                            throws org.eigenbase.xom.XOMException
2355                    {
2356                            try {
2357                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
2358                                    _parser = _parser;
2359                                    org.eigenbase.xom.NodeDef[] _tempArray = null;
2360                                    _tempArray = _tempArray;
2361                                    id = (String)_parser.getAttribute("id", "String", null, null, true);
2362                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
2363                                    _tempArray = _parser.getArray(Regex.class, 0, 0);
2364                                    regexs = new Regex[_tempArray.length];
2365                                    for(int _i=0; _i<regexs.length; _i++)
2366                                            regexs[_i] = (Regex)_tempArray[_i];
2367                            } catch(org.eigenbase.xom.XOMException _ex) {
2368                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
2369                            }
2370                    }
2371    
2372    
2373    
2374                    public String getName()
2375                    {
2376                            return "IgnoreMap";
2377                    }
2378    
2379                    public void display(java.io.PrintWriter _out, int _indent)
2380                    {
2381                            _out.println(getName());
2382                            displayAttribute(_out, "id", id, _indent+1);
2383                            displayAttribute(_out, "enabled", enabled, _indent+1);
2384                            displayElementArray(_out, "regexs", regexs, _indent+1);
2385                    }
2386                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
2387                    {
2388                            _out.beginTag("IgnoreMap", new org.eigenbase.xom.XMLAttrVector()
2389                                    .add("id", id)
2390                                    .add("enabled", enabled)
2391                                    );
2392                            displayXMLElementArray(_out, regexs);
2393                            _out.endTag("IgnoreMap");
2394                    }
2395                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
2396                    {
2397                            boolean _diff = true;
2398                            IgnoreMap _cother = (IgnoreMap)_other;
2399                            _diff = _diff && displayElementArrayDiff("regexs", regexs, _cother.regexs, _out, _indent+1);
2400                            return _diff;
2401                    }
2402                    // BEGIN pass-through code block ---
2403    private static final String[] TEMPLATE_NAMES = new String[] { };
2404                protected String[] getTemplateNames() {
2405                    return TEMPLATE_NAMES;
2406                }
2407                protected Recognizer.Matcher getMatcher() {
2408                    return getMatcher(new String[]{});
2409                }
2410                    // END pass-through code block ---
2411            }
2412    
2413            /**
2414             * A RolapConnection uses one AggRule. If no name is specified, then
2415             * the AggRule which is marked as default==true is used (validation
2416             * fails if one and only one AggRule is not marked as the default).
2417             * An AggRule has manditory child elements for matching the
2418             * aggregate table names, aggregate table fact count column,
2419             * foreign key columns, the measure columns, and the hierarchy level
2420             * columns. These child elements can be specified as direct children
2421             * of an AggRule element or by reference to elements defined as a
2422             * pier to the AggRule (using references allows reuse of the child
2423             * elements and with one quick edit the reference to use can be
2424             * changed by changing the refid attribute value).
2425             */
2426            public static class AggRule extends Base
2427            {
2428                    public AggRule()
2429                    {
2430                    }
2431    
2432                    public AggRule(org.eigenbase.xom.DOMWrapper _def)
2433                            throws org.eigenbase.xom.XOMException
2434                    {
2435                            try {
2436                                    org.eigenbase.xom.DOMElementParser _parser = new org.eigenbase.xom.DOMElementParser(_def, "", DefaultDef.class);
2437                                    _parser = _parser;
2438                                    tag = (String)_parser.getAttribute("tag", "String", null, null, true);
2439                                    countColumn = (String)_parser.getAttribute("countColumn", "String", "fact_count", null, true);
2440                                    enabled = (Boolean)_parser.getAttribute("enabled", "Boolean", "true", null, false);
2441                                    ignoreMap = (IgnoreMap)_parser.getElement(IgnoreMap.class, false);
2442                                    ignoreMapRef = (IgnoreMapRef)_parser.getElement(IgnoreMapRef.class, false);
2443                                    factCountMatch = (FactCountMatch)_parser.getElement(FactCountMatch.class, false);
2444                                    factCountMatchRef = (FactCountMatchRef)_parser.getElement(FactCountMatchRef.class, false);
2445                                    foreignKeyMatch = (ForeignKeyMatch)_parser.getElement(ForeignKeyMatch.class, false);
2446                                    foreignKeyMatchRef = (ForeignKeyMatchRef)_parser.getElement(ForeignKeyMatchRef.class, false);
2447                                    tableMatch = (TableMatch)_parser.getElement(TableMatch.class, false);
2448                                    tableMatchRef = (TableMatchRef)_parser.getElement(TableMatchRef.class, false);
2449                                    levelMap = (LevelMap)_parser.getElement(LevelMap.class, false);
2450                                    levelMapRef = (LevelMapRef)_parser.getElement(LevelMapRef.class, false);
2451                                    measureMap = (MeasureMap)_parser.getElement(MeasureMap.class, false);
2452                                    measureMapRef = (MeasureMapRef)_parser.getElement(MeasureMapRef.class, false);
2453                            } catch(org.eigenbase.xom.XOMException _ex) {
2454                                    throw new org.eigenbase.xom.XOMException("In " + getName() + ": " + _ex.getMessage());
2455                            }
2456                    }
2457    
2458                    public String tag;  // required attribute
2459                    public String countColumn;  // attribute default: fact_count
2460    
2461                    /**
2462                     */
2463                    public IgnoreMap ignoreMap;  //optional element
2464                    /**
2465                     */
2466                    public IgnoreMapRef ignoreMapRef;  //optional element
2467                    /**
2468                     */
2469                    public FactCountMatch factCountMatch;  //optional element
2470                    /**
2471                     */
2472                    public FactCountMatchRef factCountMatchRef;  //optional element
2473                    /**
2474                     */
2475                    public ForeignKeyMatch foreignKeyMatch;  //optional element
2476                    /**
2477                     */
2478                    public ForeignKeyMatchRef foreignKeyMatchRef;  //optional element
2479                    /**
2480                     */
2481                    public TableMatch tableMatch;  //optional element
2482                    /**
2483                     */
2484                    public TableMatchRef tableMatchRef;  //optional element
2485                    /**
2486                     */
2487                    public LevelMap levelMap;  //optional element
2488                    /**
2489                     */
2490                    public LevelMapRef levelMapRef;  //optional element
2491                    /**
2492                     */
2493                    public MeasureMap measureMap;  //optional element
2494                    /**
2495                     */
2496                    public MeasureMapRef measureMapRef;  //optional element
2497    
2498                    public String getName()
2499                    {
2500                            return "AggRule";
2501                    }
2502    
2503                    public void display(java.io.PrintWriter _out, int _indent)
2504                    {
2505                            _out.println(getName());
2506                            displayAttribute(_out, "tag", tag, _indent+1);
2507                            displayAttribute(_out, "countColumn", countColumn, _indent+1);
2508                            displayAttribute(_out, "enabled", enabled, _indent+1);
2509                            displayElement(_out, "ignoreMap", ignoreMap, _indent+1);
2510                            displayElement(_out, "ignoreMapRef", ignoreMapRef, _indent+1);
2511                            displayElement(_out, "factCountMatch", factCountMatch, _indent+1);
2512                            displayElement(_out, "factCountMatchRef", factCountMatchRef, _indent+1);
2513                            displayElement(_out, "foreignKeyMatch", foreignKeyMatch, _indent+1);
2514                            displayElement(_out, "foreignKeyMatchRef", foreignKeyMatchRef, _indent+1);
2515                            displayElement(_out, "tableMatch", tableMatch, _indent+1);
2516                            displayElement(_out, "tableMatchRef", tableMatchRef, _indent+1);
2517                            displayElement(_out, "levelMap", levelMap, _indent+1);
2518                            displayElement(_out, "levelMapRef", levelMapRef, _indent+1);
2519                            displayElement(_out, "measureMap", measureMap, _indent+1);
2520                            displayElement(_out, "measureMapRef", measureMapRef, _indent+1);
2521                    }
2522                    public void displayXML(org.eigenbase.xom.XMLOutput _out, int _indent)
2523                    {
2524                            _out.beginTag("AggRule", new org.eigenbase.xom.XMLAttrVector()
2525                                    .add("tag", tag)
2526                                    .add("countColumn", countColumn)
2527                                    .add("enabled", enabled)
2528                                    );
2529                            displayXMLElement(_out, ignoreMap);
2530                            displayXMLElement(_out, ignoreMapRef);
2531                            displayXMLElement(_out, factCountMatch);
2532                            displayXMLElement(_out, factCountMatchRef);
2533                            displayXMLElement(_out, foreignKeyMatch);
2534                            displayXMLElement(_out, foreignKeyMatchRef);
2535                            displayXMLElement(_out, tableMatch);
2536                            displayXMLElement(_out, tableMatchRef);
2537                            displayXMLElement(_out, levelMap);
2538                            displayXMLElement(_out, levelMapRef);
2539                            displayXMLElement(_out, measureMap);
2540                            displayXMLElement(_out, measureMapRef);
2541                            _out.endTag("AggRule");
2542                    }
2543                    public boolean displayDiff(org.eigenbase.xom.ElementDef _other, java.io.PrintWriter _out, int _indent)
2544                    {
2545                            boolean _diff = true;
2546                            AggRule _cother = (AggRule)_other;
2547                            _diff = _diff && displayAttributeDiff("tag", tag, _cother.tag, _out, _indent+1);
2548                            _diff = _diff && displayAttributeDiff("countColumn", countColumn, _cother.countColumn, _out, _indent+1);
2549                            _diff = _diff && displayElementDiff("ignoreMap", ignoreMap, _cother.ignoreMap, _out, _indent+1);
2550                            _diff = _diff && displayElementDiff("ignoreMapRef", ignoreMapRef, _cother.ignoreMapRef, _out, _indent+1);
2551                            _diff = _diff && displayElementDiff("factCountMatch", factCountMatch, _cother.factCountMatch, _out, _indent+1);
2552                            _diff = _diff && displayElementDiff("factCountMatchRef", factCountMatchRef, _cother.factCountMatchRef, _out, _indent+1);
2553                            _diff = _diff && displayElementDiff("foreignKeyMatch", foreignKeyMatch, _cother.foreignKeyMatch, _out, _indent+1);
2554                            _diff = _diff && displayElementDiff("foreignKeyMatchRef", foreignKeyMatchRef, _cother.foreignKeyMatchRef, _out, _indent+1);
2555                            _diff = _diff && displayElementDiff("tableMatch", tableMatch, _cother.tableMatch, _out, _indent+1);
2556                            _diff = _diff && displayElementDiff("tableMatchRef", tableMatchRef, _cother.tableMatchRef, _out, _indent+1);
2557                            _diff = _diff && displayElementDiff("levelMap", levelMap, _cother.levelMap, _out, _indent+1);
2558                            _diff = _diff && displayElementDiff("levelMapRef", levelMapRef, _cother.levelMapRef, _out, _indent+1);
2559                            _diff = _diff && displayElementDiff("measureMap", measureMap, _cother.measureMap, _out, _indent+1);
2560                            _diff = _diff && displayElementDiff("measureMapRef", measureMapRef, _cother.measureMapRef, _out, _indent+1);
2561                            return _diff;
2562                    }
2563                    // BEGIN pass-through code block ---
2564    private boolean isOk(final Base base) {
2565                    return ((base != null) && base.isEnabled());
2566                }
2567                private boolean isRef(final AggRules rules,
2568                                      final mondrian.recorder.MessageRecorder msgRecorder,
2569                                      final Base base,
2570                                      final Base baseRef,
2571                                      final String baseName) {
2572                    if (! isOk(base)) {
2573                        if (isOk(baseRef)) {
2574                            baseRef.validate(rules, msgRecorder);
2575                            return true;
2576                        } else {
2577                            String msg = "Neither base " +
2578                                baseName +
2579                                " or baseref " +
2580                                baseName +
2581                                "Ref is ok";
2582                            msgRecorder.reportError(msg);
2583                            return false;
2584                        }
2585                    } else if (isOk(baseRef)) {
2586                        String msg = "Both base " +
2587                            base.getName() +
2588                            " and baseref " +
2589                            baseRef.getName() +
2590                            " are ok";
2591                        msgRecorder.reportError(msg);
2592                        return false;
2593                    } else {
2594                        base.validate(rules, msgRecorder);
2595                        return false;
2596                    }
2597                }
2598                // called after a constructor is called
2599                public void validate(final AggRules rules,
2600                                     final mondrian.recorder.MessageRecorder msgRecorder) {
2601                    msgRecorder.pushContextName(getName());
2602                    try {
2603                        // IgnoreMap is optional
2604                        if (ignoreMap != null) {
2605                            ignoreMap.validate(rules, msgRecorder);
2606                        } else if (ignoreMapRef != null) {
2607                            ignoreMapRef.validate(rules, msgRecorder);
2608                            ignoreMap =
2609                                rules.lookupIgnoreMap(ignoreMapRef.getRefId());
2610                        }
2611                        if (isRef(rules, msgRecorder, factCountMatch,
2612                                factCountMatchRef, "FactCountMatch")) {
2613                            factCountMatch = rules.lookupFactCountMatch(
2614                                factCountMatchRef.getRefId());
2615                        }
2616                        if (isRef(rules, msgRecorder, foreignKeyMatch,
2617                                foreignKeyMatchRef, "ForeignKeyMatch")) {
2618                            foreignKeyMatch = rules.lookupForeignKeyMatch(
2619                                foreignKeyMatchRef.getRefId());
2620                        }
2621                        if (isRef(rules, msgRecorder, tableMatch,
2622                                tableMatchRef, "TableMatch")) {
2623                            tableMatch =
2624                                rules.lookupTableMatch(tableMatchRef.getRefId());
2625                        }
2626                        if (isRef(rules, msgRecorder, levelMap,
2627                                levelMapRef, "LevelMap")) {
2628                            levelMap = rules.lookupLevelMap(levelMapRef.getRefId());
2629                        }
2630                        if (isRef(rules, msgRecorder, measureMap,
2631                                measureMapRef, "MeasureMap")) {
2632                            measureMap =
2633                                rules.lookupMeasureMap(measureMapRef.getRefId());
2634                        }
2635                    } finally {
2636                        msgRecorder.popContextName();
2637                    }
2638                }
2639                public String getTag() {
2640                    return tag;
2641                }
2642                public String getCountColumn() {
2643                    return countColumn;
2644                }
2645                public FactCountMatch getFactCountMatch() {
2646                    return factCountMatch;
2647                }
2648                public ForeignKeyMatch getForeignKeyMatch() {
2649                    return foreignKeyMatch;
2650                }
2651                public TableMatch getTableMatch() {
2652                    return tableMatch;
2653                }
2654                public LevelMap getLevelMap() {
2655                    return levelMap;
2656                }
2657                public MeasureMap getMeasureMap() {
2658                    return measureMap;
2659                }
2660                public IgnoreMap getIgnoreMap() {
2661                    return ignoreMap;
2662                }
2663                    // END pass-through code block ---
2664            }
2665    
2666    
2667    }