1 10 11 package mondrian.rolap.aggmatcher; 12 13 import mondrian.olap.*; 14 import mondrian.rolap.*; 15 import mondrian.recorder.MessageRecorder; 16 import mondrian.resource.MondrianResource; 17 18 import org.apache.log4j.Logger; 19 20 import java.io.PrintWriter ; 21 import java.io.StringWriter ; 22 import java.util.*; 23 import java.util.regex.Pattern ; 24 25 32 public class ExplicitRules { 33 private static final Logger LOGGER = Logger.getLogger(ExplicitRules.class); 34 35 private static final MondrianResource mres = MondrianResource.instance(); 36 37 41 public static boolean excludeTable( 42 final String tableName, 43 final List<Group> aggGroups) { 44 for (Group group : aggGroups) { 45 if (group.excludeTable(tableName)) { 46 return true; 47 } 48 } 49 return false; 50 } 51 52 57 public static ExplicitRules.TableDef getIncludeByTableDef( 58 final String tableName, 59 final List<Group> aggGroups) { 60 for (Group group : aggGroups) { 61 TableDef tableDef = group.getIncludeByTableDef(tableName); 62 if (tableDef != null) { 63 return tableDef; 64 } 65 } 66 return null; 67 } 68 69 74 public static class Group { 75 76 80 public static ExplicitRules.Group make( 81 final RolapCube cube, 82 final MondrianDef.Cube xmlCube) { 83 Group group = new Group(cube); 84 85 MondrianDef.Relation relation = xmlCube.fact; 86 87 if (relation instanceof MondrianDef.Table) { 88 MondrianDef.AggExclude[] aggExcludes = 89 ((MondrianDef.Table) relation).getAggExcludes(); 90 if (aggExcludes != null) { 91 for (MondrianDef.AggExclude aggExclude : aggExcludes) { 92 Exclude exclude = 93 ExplicitRules.make(aggExclude); 94 group.addExclude(exclude); 95 } 96 } 97 MondrianDef.AggTable[] aggTables = 98 ((MondrianDef.Table) relation).getAggTables(); 99 if (aggTables != null) { 100 for (MondrianDef.AggTable aggTable : aggTables) { 101 TableDef tableDef = TableDef.make(aggTable, group); 102 group.addTableDef(tableDef); 103 } 104 } 105 } else { 106 String msg = mres.CubeRelationNotTable.str( 107 cube.getName(), 108 relation.getClass().getName()); 109 LOGGER.warn(msg); 110 } 111 112 if (LOGGER.isDebugEnabled()) { 113 LOGGER.debug(Util.nl+group); 114 } 115 return group; 116 } 117 118 private final RolapCube cube; 119 private List<TableDef> tableDefs; 120 private List<Exclude> excludes; 121 122 public Group(final RolapCube cube) { 123 this.cube = cube; 124 this.excludes = Collections.emptyList(); 125 this.tableDefs = Collections.emptyList(); 126 } 127 128 131 public RolapCube getCube() { 132 return cube; 133 } 134 135 138 public RolapStar getStar() { 139 return getCube().getStar(); 140 } 141 142 145 public String getName() { 146 return getCube().getName(); 147 } 148 149 152 public boolean hasRules() { 153 return (excludes != Collections.EMPTY_LIST) || 154 (tableDefs != Collections.EMPTY_LIST); 155 } 156 157 162 public void addExclude(final ExplicitRules.Exclude exclude) { 163 if (excludes == Collections.EMPTY_LIST) { 164 excludes = new ArrayList<Exclude>(); 165 } 166 excludes.add(exclude); 167 } 168 169 174 public void addTableDef(final ExplicitRules.TableDef tableDef) { 175 if (tableDefs == Collections.EMPTY_LIST) { 176 tableDefs = new ArrayList<TableDef>(); 177 } 178 tableDefs.add(tableDef); 179 } 180 181 184 public boolean excludeTable(final String tableName) { 185 for (Exclude exclude : excludes) { 187 if (exclude.isExcluded(tableName)) { 188 return true; 189 } 190 } 191 return false; 192 } 193 194 197 public ExplicitRules.TableDef getIncludeByTableDef( 198 final String tableName) { 199 for (ExplicitRules.TableDef tableDef : tableDefs) { 203 if (tableDef instanceof NameTableDef) { 204 if (tableDef.matches(tableName)) { 205 return tableDef; 206 } 207 } 208 } 209 for (ExplicitRules.TableDef tableDef : tableDefs) { 210 if (tableDef instanceof PatternTableDef) { 211 if (tableDef.matches(tableName)) { 212 return tableDef; 213 } 214 } 215 } 216 return null; 217 } 218 219 223 public String getTableName() { 224 RolapStar.Table table = getStar().getFactTable(); 225 MondrianDef.Relation relation = table.getRelation(); 226 return relation.getAlias(); 227 } 228 229 233 public String getSchemaName() { 234 String schema = null; 235 236 RolapStar.Table table = getStar().getFactTable(); 237 MondrianDef.Relation relation = table.getRelation(); 238 239 if (relation instanceof MondrianDef.Table) { 240 MondrianDef.Table mtable = (MondrianDef.Table) relation; 241 schema = mtable.schema; 242 } 243 return schema; 244 } 245 250 public String getCatalogName() { 251 return null; 252 } 253 254 257 public void validate(final MessageRecorder msgRecorder) { 258 msgRecorder.pushContextName(getName()); 259 try { 260 for (ExplicitRules.TableDef tableDef : tableDefs) { 261 tableDef.validate(msgRecorder); 262 } 263 } finally { 264 msgRecorder.popContextName(); 265 } 266 } 267 268 public String toString() { 269 StringWriter sw = new StringWriter (256); 270 PrintWriter pw = new PrintWriter (sw); 271 print(pw, ""); 272 pw.flush(); 273 return sw.toString(); 274 } 275 276 public void print(final PrintWriter pw, final String prefix) { 277 pw.print(prefix); 278 pw.println("ExplicitRules.Group:"); 279 String subprefix = prefix + " "; 280 String subsubprefix = subprefix + " "; 281 282 pw.print(subprefix); 283 pw.print("name="); 284 pw.println(getStar().getFactTable().getRelation()); 285 286 pw.print(subprefix); 287 pw.println("TableDefs: ["); 288 for (ExplicitRules.TableDef tableDef : tableDefs) { 289 tableDef.print(pw, subsubprefix); 290 } 291 pw.print(subprefix); 292 pw.println("]"); 293 } 294 } 295 296 private static Exclude make(final MondrianDef.AggExclude aggExclude) { 297 return (aggExclude.getNameAttribute() != null) ? 298 new ExcludeName( 299 aggExclude.getNameAttribute(), 300 aggExclude.isIgnoreCase()) : 301 (Exclude) new ExcludePattern( 302 aggExclude.getPattern(), 303 aggExclude.isIgnoreCase()); 304 } 305 306 311 private interface Exclude { 312 318 boolean isExcluded(final String tableName); 319 320 void validate(final MessageRecorder msgRecorder); 321 322 void print(final PrintWriter pw, final String prefix); 323 } 324 325 328 private static class ExcludeName implements Exclude { 329 private final String name; 330 private final boolean ignoreCase; 331 332 private ExcludeName(final String name, final boolean ignoreCase) { 333 this.name = name; 334 this.ignoreCase = ignoreCase; 335 } 336 337 340 public String getName() { 341 return name; 342 } 343 344 347 public boolean isIgnoreCase() { 348 return ignoreCase; 349 } 350 351 357 public boolean isExcluded(final String tableName) { 358 return (this.ignoreCase) 359 ? this.name.equals(tableName) 360 : this.name.equalsIgnoreCase(tableName); 361 } 362 363 368 public void validate(final MessageRecorder msgRecorder) { 369 msgRecorder.pushContextName("ExcludeName"); 370 try { 371 String name = getName(); 372 checkAttributeString(msgRecorder, name, "name"); 373 374 402 } finally { 403 msgRecorder.popContextName(); 404 } 405 } 406 407 public void print(final PrintWriter pw, final String prefix) { 408 pw.print(prefix); 409 pw.println("ExplicitRules.PatternTableDef.ExcludeName:"); 410 411 String subprefix = prefix + " "; 412 413 pw.print(subprefix); 414 pw.print("name="); 415 pw.println(this.name); 416 417 pw.print(subprefix); 418 pw.print("ignoreCase="); 419 pw.println(this.ignoreCase); 420 } 421 } 422 423 427 private static class ExcludePattern implements Exclude { 428 private final Pattern pattern; 429 430 private ExcludePattern( 431 final String pattern, 432 final boolean ignoreCase) { 433 this.pattern = (ignoreCase) ? 434 Pattern.compile(pattern, Pattern.CASE_INSENSITIVE) : 435 Pattern.compile(pattern); 436 } 437 438 444 public boolean isExcluded(final String tableName) { 445 return pattern.matcher(tableName).matches(); 446 } 447 448 453 public void validate(final MessageRecorder msgRecorder) { 454 msgRecorder.pushContextName("ExcludePattern"); 455 try { 456 checkAttributeString( 457 msgRecorder, 458 pattern.pattern(), 459 "pattern"); 460 } finally { 466 msgRecorder.popContextName(); 467 } 468 } 469 470 public void print(final PrintWriter pw, final String prefix) { 471 pw.print(prefix); 472 pw.println("ExplicitRules.PatternTableDef.ExcludePattern:"); 473 474 String subprefix = prefix + " "; 475 476 pw.print(subprefix); 477 pw.print("pattern="); 478 pw.print(this.pattern.pattern()); 479 pw.print(":"); 480 pw.println(this.pattern.flags()); 481 } 482 } 483 484 490 public static abstract class TableDef { 491 492 496 static ExplicitRules.TableDef make( 497 final MondrianDef.AggTable aggTable, 498 final ExplicitRules.Group group) { 499 return (aggTable instanceof MondrianDef.AggName) ? 500 ExplicitRules.NameTableDef.make( 501 (MondrianDef.AggName) aggTable, group) : 502 (ExplicitRules.TableDef) 503 ExplicitRules.PatternTableDef.make( 504 (MondrianDef.AggPattern) aggTable, group); 505 } 506 507 516 private static void add( 517 final ExplicitRules.TableDef tableDef, 518 final MondrianDef.AggTable aggTable) { 519 520 if (aggTable.getAggFactCount() != null) { 521 tableDef.setFactCountName(aggTable.getAggFactCount().getColumnName()); 522 } 523 524 MondrianDef.AggIgnoreColumn[] ignores = 525 aggTable.getAggIgnoreColumns(); 526 527 if (ignores != null) { 528 for (MondrianDef.AggIgnoreColumn ignore : ignores) { 529 tableDef.addIgnoreColumnName(ignore.getColumnName()); 530 } 531 } 532 533 MondrianDef.AggForeignKey[] fks = aggTable.getAggForeignKeys(); 534 if (fks != null) { 535 for (MondrianDef.AggForeignKey fk : fks) { 536 tableDef.addFK(fk); 537 } 538 } 539 MondrianDef.AggMeasure[] measures = aggTable.getAggMeasures(); 540 if (measures != null) { 541 for (MondrianDef.AggMeasure measure : measures) { 542 addTo(tableDef, measure); 543 } 544 } 545 546 MondrianDef.AggLevel[] levels = aggTable.getAggLevels(); 547 if (levels != null) { 548 for (MondrianDef.AggLevel level : levels) { 549 addTo(tableDef, level); 550 } 551 } 552 } 553 private static void addTo( 554 final ExplicitRules.TableDef tableDef, 555 final MondrianDef.AggLevel aggLevel) { 556 addLevelTo(tableDef, 557 aggLevel.getNameAttribute(), 558 aggLevel.getColumnName()); 559 } 560 561 private static void addTo( 562 final ExplicitRules.TableDef tableDef, 563 final MondrianDef.AggMeasure aggMeasure) { 564 addMeasureTo(tableDef, 565 aggMeasure.getNameAttribute(), 566 aggMeasure.getColumn()); 567 } 568 569 public static void addLevelTo( 570 final ExplicitRules.TableDef tableDef, 571 final String name, 572 final String columnName) { 573 Level level = tableDef.new Level(name, columnName); 574 tableDef.add(level); 575 } 576 577 public static void addMeasureTo( 578 final ExplicitRules.TableDef tableDef, 579 final String name, 580 final String column) { 581 Measure measure = tableDef.new Measure(name, column); 582 tableDef.add(measure); 583 } 584 585 589 class Level { 590 private final String name; 591 private final String columnName; 592 private RolapLevel rlevel; 593 594 Level(final String name, final String columnName) { 595 this.name = name; 596 this.columnName = columnName; 597 } 598 599 602 public String getName() { 603 return name; 604 } 605 606 609 public String getColumnName() { 610 return columnName; 611 } 612 613 616 public RolapLevel getRolapLevel() { 617 return rlevel; 618 } 619 620 629 public void validate(final MessageRecorder msgRecorder) { 630 msgRecorder.pushContextName("Level"); 631 try { 632 String name = getName(); 633 String columnName = getColumnName(); 634 checkAttributeString(msgRecorder, name, "name"); 635 checkAttributeString(msgRecorder, columnName, "column"); 636 637 String [] names = Util.explode(name); 638 if (names.length != 2) { 640 msgRecorder.reportError( 641 mres.BadLevelNameFormat.str( 642 msgRecorder.getContext(), 643 name)); 644 } else { 645 646 RolapCube cube = ExplicitRules.TableDef.this.getCube(); 647 SchemaReader schemaReader = cube.getSchemaReader(); 648 RolapLevel level = 649 (RolapLevel) schemaReader.lookupCompound( 650 cube, 651 names, 652 false, 653 Category.Level); 654 if (level == null) { 655 Hierarchy hierarchy = (Hierarchy) 656 schemaReader.lookupCompound( 657 cube, 658 new String [] { names[0] }, 659 false, 660 Category.Hierarchy); 661 if (hierarchy == null) { 662 msgRecorder.reportError( 663 mres.UnknownHierarchyName.str( 664 msgRecorder.getContext(), 665 names[0])); 666 } else { 667 msgRecorder.reportError( 668 mres.UnknownLevelName.str( 669 msgRecorder.getContext(), 670 names[0], 671 names[1])); 672 } 673 } 674 rlevel = level; 675 } 676 } finally { 677 msgRecorder.popContextName(); 678 } 679 } 680 681 public String toString() { 682 StringWriter sw = new StringWriter (256); 683 PrintWriter pw = new PrintWriter (sw); 684 print(pw, ""); 685 pw.flush(); 686 return sw.toString(); 687 } 688 689 public void print(final PrintWriter pw, final String prefix) { 690 pw.print(prefix); 691 pw.println("Level:"); 692 String subprefix = prefix + " "; 693 694 pw.print(subprefix); 695 pw.print("name="); 696 pw.println(this.name); 697 698 pw.print(subprefix); 699 pw.print("columnName="); 700 pw.println(this.columnName); 701 } 702 } 703 704 709 class Measure { 710 private final String name; 711 private String symbolicName; 712 private final String columnName; 713 private RolapStar.Measure rolapMeasure; 714 715 Measure(final String name, final String columnName) { 716 this.name = name; 717 this.columnName = columnName; 718 } 719 720 724 public String getName() { 725 return name; 726 } 727 728 731 public String getSymbolicName() { 732 return symbolicName; 733 } 734 735 738 public String getColumnName() { 739 return columnName; 740 } 741 742 745 public RolapStar.Measure getRolapStarMeasure() { 746 return rolapMeasure; 747 } 748 749 758 public void validate(final MessageRecorder msgRecorder) { 759 msgRecorder.pushContextName("Measure"); 760 try { 761 String name = getName(); 762 String column = getColumnName(); 763 checkAttributeString(msgRecorder, name, "name"); 764 checkAttributeString(msgRecorder, column, "column"); 765 766 String [] names = Util.explode(name); 767 if (names.length != 2) { 768 msgRecorder.reportError( 769 mres.BadMeasureNameFormat.str( 770 msgRecorder.getContext(), 771 name)); 772 } else { 773 RolapCube cube = ExplicitRules.TableDef.this.getCube(); 774 SchemaReader schemaReader = cube.getSchemaReader(); 775 Member member = (Member) schemaReader.lookupCompound( 776 cube, 777 names, 778 false, 779 Category.Member); 780 if (member == null) { 781 if (! names[0].equals("Measures")) { 782 msgRecorder.reportError( 783 mres.BadMeasures.str( 784 msgRecorder.getContext(), 785 names[0])); 786 } else { 787 msgRecorder.reportError( 788 mres.UnknownMeasureName.str( 789 msgRecorder.getContext(), 790 names[1])); 791 } 792 } 793 RolapStar star = cube.getStar(); 794 rolapMeasure = 795 star.getFactTable().lookupMeasureByName(names[1]); 796 if (rolapMeasure == null) { 797 msgRecorder.reportError( 798 mres.BadMeasureName.str( 799 msgRecorder.getContext(), 800 names[1], 801 cube.getName())); 802 } 803 symbolicName = names[1]; 804 } 805 } finally { 806 msgRecorder.popContextName(); 807 } 808 } 809 810 public String toString() { 811 StringWriter sw = new StringWriter (256); 812 PrintWriter pw = new PrintWriter (sw); 813 print(pw, ""); 814 pw.flush(); 815 return sw.toString(); 816 } 817 818 public void print(final PrintWriter pw, final String prefix) { 819 pw.print(prefix); 820 pw.println("Measure:"); 821 String subprefix = prefix + " "; 822 823 pw.print(subprefix); 824 pw.print("name="); 825 pw.println(this.name); 826 827 pw.print(subprefix); 828 pw.print("column="); 829 pw.println(this.columnName); 830 } 831 } 832 833 private static int idCount = 0; 834 private static int nextId() { 835 return idCount++; 836 } 837 838 protected final int id; 839 protected final boolean ignoreCase; 840 protected final ExplicitRules.Group aggGroup; 841 protected String factCountName; 842 protected List<String > ignoreColumnNames; 843 private Map<String , String > foreignKeyMap; 844 private List<Level> levels; 845 private List<Measure> measures; 846 847 protected TableDef( 848 final boolean ignoreCase, 849 final ExplicitRules.Group aggGroup) { 850 this.id = nextId(); 851 this.ignoreCase = ignoreCase; 852 this.aggGroup = aggGroup; 853 this.foreignKeyMap = Collections.emptyMap(); 854 this.levels = Collections.emptyList(); 855 this.measures = Collections.emptyList(); 856 this.ignoreColumnNames = Collections.emptyList(); 857 } 858 859 862 public int getId() { 863 return this.id; 864 } 865 866 869 public boolean isIgnoreCase() { 870 return this.ignoreCase; 871 } 872 873 876 public RolapStar getStar() { 877 return getAggGroup().getStar(); 878 } 879 880 883 public ExplicitRules.Group getAggGroup() { 884 return this.aggGroup; 885 } 886 887 890 protected String getFactCountName() { 891 return factCountName; 892 } 893 894 899 protected void setFactCountName(final String factCountName) { 900 this.factCountName = factCountName; 901 } 902 903 906 protected Iterator<String > getIgnoreColumnNames() { 907 return ignoreColumnNames.iterator(); 908 } 909 910 913 public List<Level> getLevels() { 914 return levels; 915 } 916 917 920 public List<Measure> getMeasures() { 921 return measures; 922 } 923 924 927 protected Recognizer.Matcher getIgnoreMatcher() { 928 return new Recognizer.Matcher() { 929 public boolean matches(final String name) { 930 for (Iterator<String > it = 931 ExplicitRules.TableDef.this.getIgnoreColumnNames(); 932 it.hasNext();) { 933 String ignoreName = it.next(); 934 if (ignoreName.equals(name)) { 935 return true; 936 } 937 } 938 return false; 939 } 940 }; 941 } 942 943 946 protected Recognizer.Matcher getFactCountMatcher() { 947 return new Recognizer.Matcher() { 948 public boolean matches(String name) { 949 return ExplicitRules.TableDef.this.factCountName.equalsIgnoreCase(name); 951 } 952 }; 953 } 954 955 958 RolapCube getCube() { 959 return aggGroup.getCube(); 960 } 961 962 968 public boolean columnsOK( 969 final RolapStar star, 970 final JdbcSchema.Table dbFactTable, 971 final JdbcSchema.Table dbTable, 972 final MessageRecorder msgRecorder) { 973 Recognizer cb = new ExplicitRecognizer( 974 this, star, dbFactTable, dbTable, msgRecorder); 975 return cb.check(); 976 } 977 978 981 protected void addIgnoreColumnName(final String ignoreName) { 982 if (this.ignoreColumnNames == Collections.EMPTY_LIST) { 983 this.ignoreColumnNames = new ArrayList<String >(); 984 } 985 this.ignoreColumnNames.add(ignoreName); 986 } 987 988 992 protected void addFK(final MondrianDef.AggForeignKey fk) { 993 if (this.foreignKeyMap == Collections.EMPTY_MAP) { 994 this.foreignKeyMap = new HashMap<String , String >(); 995 } 996 this.foreignKeyMap.put(fk.getFactFKColumnName(), 997 fk.getAggregateFKColumnName()); 998 } 999 1000 1004 protected String getAggregateFK(final String baseFK) { 1005 return this.foreignKeyMap.get(baseFK); 1006 } 1007 1008 1011 protected void add(final Level level) { 1012 if (this.levels == Collections.EMPTY_LIST) { 1013 this.levels = new ArrayList<Level>(); 1014 } 1015 this.levels.add(level); 1016 } 1017 1018 1021 protected void add(final Measure measure) { 1022 if (this.measures == Collections.EMPTY_LIST) { 1023 this.measures = new ArrayList<Measure>(); 1024 } 1025 this.measures.add(measure); 1026 } 1027 1028 1031 public abstract boolean matches(final String tableName); 1032 1033 1037 public void validate(final MessageRecorder msgRecorder) { 1038 msgRecorder.pushContextName("TableDef"); 1039 try { 1040 Map<String , Object > namesToObjects = 1042 new HashMap<String , Object >(); 1043 Map<String , Object > columnsToObjects = 1045 new HashMap<String , Object >(); 1046 1047 for (Level level : levels) { 1048 level.validate(msgRecorder); 1049 1050 if (namesToObjects.containsKey(level.getName())) { 1052 msgRecorder.reportError( 1053 mres.DuplicateLevelNames.str( 1054 msgRecorder.getContext(), 1055 level.getName())); 1056 } else { 1057 namesToObjects.put(level.getName(), level); 1058 } 1059 1060 if (columnsToObjects.containsKey(level.getColumnName())) { 1062 Level l = (Level) 1063 columnsToObjects.get(level.getColumnName()); 1064 msgRecorder.reportError( 1065 mres.DuplicateLevelColumnNames.str( 1066 msgRecorder.getContext(), 1067 level.getName(), 1068 l.getName(), 1069 level.getColumnName())); 1070 } else { 1071 columnsToObjects.put(level.getColumnName(), level); 1072 } 1073 } 1074 1075 namesToObjects.clear(); 1077 for (Measure measure : measures) { 1078 measure.validate(msgRecorder); 1079 1080 if (namesToObjects.containsKey(measure.getName())) { 1081 msgRecorder.reportError( 1082 mres.DuplicateMeasureNames.str( 1083 msgRecorder.getContext(), 1084 measure.getName())); 1085 continue; 1086 } else { 1087 namesToObjects.put(measure.getName(), measure); 1088 } 1089 1090 if (columnsToObjects.containsKey(measure.getColumnName())) { 1091 Object o = 1092 columnsToObjects.get(measure.getColumnName()); 1093 if (o instanceof Measure) { 1094 Measure m = (Measure) o; 1095 msgRecorder.reportError( 1096 mres.DuplicateMeasureColumnNames.str( 1097 msgRecorder.getContext(), 1098 measure.getName(), 1099 m.getName(), 1100 measure.getColumnName())); 1101 } else { 1102 Level l = (Level) o; 1103 msgRecorder.reportError( 1104 mres.DuplicateLevelMeasureColumnNames.str( 1105 msgRecorder.getContext(), 1106 l.getName(), 1107 measure.getName(), 1108 measure.getColumnName())); 1109 } 1110 1111 } else { 1112 columnsToObjects.put(measure.getColumnName(), measure); 1113 } 1114 } 1115 1116 namesToObjects.clear(); 1118 columnsToObjects.clear(); 1119 1120 RolapStar star = getStar(); 1123 RolapStar.Table factTable = star.getFactTable(); 1124 String tableName = factTable.getAlias(); 1125 for (Map.Entry<String , String > e : foreignKeyMap.entrySet()) { 1126 String baseFKName = e.getKey(); 1127 String aggFKName = e.getValue(); 1128 1129 if (namesToObjects.containsKey(baseFKName)) { 1130 msgRecorder.reportError( 1131 mres.DuplicateFactForeignKey.str( 1132 msgRecorder.getContext(), 1133 baseFKName, 1134 aggFKName)); 1135 } else { 1136 namesToObjects.put(baseFKName, aggFKName); 1137 } 1138 if (columnsToObjects.containsKey(aggFKName)) { 1139 msgRecorder.reportError( 1140 mres.DuplicateFactForeignKey.str( 1141 msgRecorder.getContext(), 1142 baseFKName, 1143 aggFKName)); 1144 } else { 1145 columnsToObjects.put(aggFKName, baseFKName); 1146 } 1147 1148 MondrianDef.Column c = 1149 new MondrianDef.Column(tableName, baseFKName); 1150 if (factTable.findTableWithLeftCondition(c) == null) { 1151 msgRecorder.reportError( 1152 mres.UnknownLeftJoinCondition.str( 1153 msgRecorder.getContext(), 1154 tableName, 1155 baseFKName)); 1156 } 1157 } 1158 } finally { 1159 msgRecorder.popContextName(); 1160 } 1161 } 1162 1163 public String toString() { 1164 StringWriter sw = new StringWriter (256); 1165 PrintWriter pw = new PrintWriter (sw); 1166 print(pw, ""); 1167 pw.flush(); 1168 return sw.toString(); 1169 } 1170 1171 public void print(final PrintWriter pw, final String prefix) { 1172 String subprefix = prefix + " "; 1173 String subsubprefix = subprefix + " "; 1174 1175 pw.print(subprefix); 1176 pw.print("id="); 1177 pw.println(this.id); 1178 1179 pw.print(subprefix); 1180 pw.print("ignoreCase="); 1181 pw.println(this.ignoreCase); 1182 1183 pw.print(subprefix); 1184 pw.println("Levels: ["); 1185 for (Level level : this.levels) { 1186 level.print(pw, subsubprefix); 1187 } 1188 pw.print(subprefix); 1189 pw.println("]"); 1190 1191 pw.print(subprefix); 1192 pw.println("Measures: ["); 1193 for (Measure measure : this.measures) { 1194 measure.print(pw, subsubprefix); 1195 } 1196 pw.print(subprefix); 1197 pw.println("]"); 1198 } 1199 } 1200 1201 static class NameTableDef extends ExplicitRules.TableDef { 1202 1205 static ExplicitRules.NameTableDef make( 1206 final MondrianDef.AggName aggName, 1207 final ExplicitRules.Group group) { 1208 ExplicitRules.NameTableDef name = 1209 new ExplicitRules.NameTableDef(aggName.getNameAttribute(), 1210 aggName.isIgnoreCase(), 1211 group); 1212 1213 ExplicitRules.TableDef.add(name, aggName); 1214 1215 return name; 1216 } 1217 1218 private final String name; 1219 public NameTableDef( 1220 final String name, 1221 final boolean ignoreCase, 1222 final ExplicitRules.Group group) { 1223 super(ignoreCase, group); 1224 this.name = name; 1225 } 1226 1227 1231 public boolean matches(final String tableName) { 1232 return (this.ignoreCase) ? 1233 this.name.equals(tableName) : 1234 this.name.equalsIgnoreCase(tableName); 1235 } 1236 1237 1242 public void validate(final MessageRecorder msgRecorder) { 1243 msgRecorder.pushContextName("NameTableDef"); 1244 try { 1245 checkAttributeString(msgRecorder, name, "name"); 1246 1247 super.validate(msgRecorder); 1248 } finally { 1249 msgRecorder.popContextName(); 1250 } 1251 } 1252 1253 public void print(final PrintWriter pw, final String prefix) { 1254 pw.print(prefix); 1255 pw.println("ExplicitRules.NameTableDef:"); 1256 super.print(pw, prefix); 1257 1258 String subprefix = prefix + " "; 1259 1260 pw.print(subprefix); 1261 pw.print("name="); 1262 pw.println(this.name); 1263 1264 } 1265 } 1266 1267 1270 public static class PatternTableDef extends ExplicitRules.TableDef { 1271 1272 1275 static ExplicitRules.PatternTableDef make( 1276 final MondrianDef.AggPattern aggPattern, 1277 final ExplicitRules.Group group) { 1278 1279 ExplicitRules.PatternTableDef pattern = 1280 new ExplicitRules.PatternTableDef( 1281 aggPattern.getPattern(), 1282 aggPattern.isIgnoreCase(), 1283 group); 1284 1285 MondrianDef.AggExclude[] excludes = aggPattern.getAggExcludes(); 1286 if (excludes != null) { 1287 for (MondrianDef.AggExclude exclude1 : excludes) { 1288 Exclude exclude = ExplicitRules.make(exclude1); 1289 pattern.add(exclude); 1290 } 1291 } 1292 1293 ExplicitRules.TableDef.add(pattern, aggPattern); 1294 1295 return pattern; 1296 } 1297 1298 private final Pattern pattern; 1299 private List<Exclude> excludes; 1300 1301 public PatternTableDef( 1302 final String pattern, 1303 final boolean ignoreCase, 1304 final ExplicitRules.Group group) { 1305 super(ignoreCase, group); 1306 this.pattern = (this.ignoreCase) 1307 ? Pattern.compile(pattern, Pattern.CASE_INSENSITIVE) 1308 : Pattern.compile(pattern); 1309 this.excludes = Collections.emptyList(); 1310 } 1311 1312 1315 public Pattern getPattern() { 1316 return pattern; 1317 } 1318 1319 1322 public List<Exclude> getExcludes() { 1323 return excludes; 1324 } 1325 1326 1331 private void add(final Exclude exclude) { 1332 if (this.excludes == Collections.EMPTY_LIST) { 1333 this.excludes = new ArrayList<Exclude>(); 1334 } 1335 this.excludes.add(exclude); 1336 } 1337 1338 1342 public boolean matches(final String tableName) { 1343 if (! pattern.matcher(tableName).matches()) { 1344 return false; 1345 } else { 1346 for (Exclude exclude : getExcludes()) { 1347 if (exclude.isExcluded(tableName)) { 1348 return false; 1349 } 1350 } 1351 return true; 1352 } 1353 } 1354 1355 1358 public void validate(final MessageRecorder msgRecorder) { 1359 msgRecorder.pushContextName("PatternTableDef"); 1360 try { 1361 checkAttributeString(msgRecorder, pattern.pattern(), "pattern"); 1362 1363 for (Exclude exclude : getExcludes()) { 1364 exclude.validate(msgRecorder); 1365 } 1366 super.validate(msgRecorder); 1367 } finally { 1368 msgRecorder.popContextName(); 1369 } 1370 } 1371 1372 public void print(final PrintWriter pw, final String prefix) { 1373 pw.print(prefix); 1374 pw.println("ExplicitRules.PatternTableDef:"); 1375 super.print(pw, prefix); 1376 1377 String subprefix = prefix + " "; 1378 String subsubprefix = subprefix + " "; 1379 1380 pw.print(subprefix); 1381 pw.print("pattern="); 1382 pw.print(this.pattern.pattern()); 1383 pw.print(":"); 1384 pw.println(this.pattern.flags()); 1385 1386 pw.print(subprefix); 1387 pw.println("Excludes: ["); 1388 Iterator<Exclude> it = this.excludes.iterator(); 1389 while (it.hasNext()) { 1390 Exclude exclude = it.next(); 1391 exclude.print(pw, subsubprefix); 1392 } 1393 pw.print(subprefix); 1394 pw.println("]"); 1395 1396 } 1397 } 1398 1399 1407 private static void checkAttributeString( 1408 final MessageRecorder msgRecorder, 1409 final String attrValue, 1410 final String attrName) { 1411 if (attrValue == null) { 1412 msgRecorder.reportError(mres.NullAttributeString.str( 1413 msgRecorder.getContext(), 1414 attrName)); 1415 } else if (attrValue.length() == 0) { 1416 msgRecorder.reportError(mres.EmptyAttributeString.str( 1417 msgRecorder.getContext(), 1418 attrName)); 1419 } 1420 } 1421 1422 1423 private ExplicitRules() {} 1424} 1425 1426 | Popular Tags |