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