KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > rolap > aggmatcher > ExplicitRecognizer


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/rolap/aggmatcher/ExplicitRecognizer.java#15 $
3 // This software is subject to the terms of the Common Public License
4 // Agreement, available at the following URL:
5 // http://www.opensource.org/licenses/cpl.html.
6 // Copyright (C) 2005-2007 Julian Hyde and others
7 // All Rights Reserved.
8 // You must accept the terms of that agreement to use this software.
9 */

10
11 package mondrian.rolap.aggmatcher;
12
13 import mondrian.olap.Hierarchy;
14 import mondrian.olap.Util;
15 import mondrian.recorder.MessageRecorder;
16 import mondrian.rolap.*;
17
18 import java.util.Iterator JavaDoc;
19
20 /**
21  * This is the Recognizer for the aggregate table descriptions that appear in
22  * the catalog schema files; the user explicitly defines the aggregate.
23  *
24  * @author Richard M. Emberson
25  * @version $Id: //open/mondrian/src/main/mondrian/rolap/aggmatcher/ExplicitRecognizer.java#15 $
26  */

27 class ExplicitRecognizer extends Recognizer {
28     private ExplicitRules.TableDef tableDef;
29
30     ExplicitRecognizer(
31             final ExplicitRules.TableDef tableDef,
32             final RolapStar star,
33             final JdbcSchema.Table dbFactTable,
34             final JdbcSchema.Table aggTable,
35             final MessageRecorder msgRecorder) {
36         super(star, dbFactTable, aggTable, msgRecorder);
37         this.tableDef = tableDef;
38     }
39
40     /**
41      * Get the ExplicitRules.TableDef associated with this instance.
42      */

43     protected ExplicitRules.TableDef getTableDef() {
44         return tableDef;
45     }
46
47     /**
48      * Get the Matcher to be used to match columns to be ignored.
49      */

50     protected Recognizer.Matcher getIgnoreMatcher() {
51         return getTableDef().getIgnoreMatcher();
52     }
53
54     /**
55      * Get the Matcher to be used to match the column which is the fact count
56      * column.
57      */

58     protected Recognizer.Matcher getFactCountMatcher() {
59         return getTableDef().getFactCountMatcher();
60     }
61
62     /**
63      * Make the measures for this aggregate table.
64      * <p>
65      * First, iterate through all of the columns in the table.
66      * For each column, iterate through all of the tableDef measures, the
67      * explicit definitions of a measure.
68      * If the table's column name matches the column name in the measure
69      * definition, then make a measure.
70      * Next, look through all of the fact table column usage measures.
71      * For each such measure usage that has a sibling foreign key usage
72      * see if the tableDef has a foreign key defined with the same name.
73      * If so, then, for free, we can make a measure for the aggregate using
74      * its foreign key.
75      * <p>
76      *
77      * @return number of measures created.
78      */

79     protected int checkMeasures() {
80         msgRecorder.pushContextName("ExplicitRecognizer.checkMeasures");
81         try {
82
83             int measureColumnCounts = 0;
84             // Look at each aggregate table column. For each measure defined,
85
// see if the measure's column name equals the column's name.
86
// If so, make the aggregate measure usage for that column.
87
for (JdbcSchema.Table.Column aggColumn : aggTable.getColumns()) {
88                 // if marked as ignore, then do not consider
89
if (aggColumn.hasUsage(JdbcSchema.UsageType.IGNORE)) {
90                     continue;
91                 }
92
93                 String JavaDoc aggColumnName = aggColumn.getName();
94
95                 for (ExplicitRules.TableDef.Measure measure :
96                     getTableDef().getMeasures())
97                 {
98                     // Column name match is case insensitive
99
if (measure.getColumnName().equalsIgnoreCase(aggColumnName)) {
100
101                         String JavaDoc name = measure.getName();
102                         String JavaDoc[] parts = Util.explode(name);
103                         String JavaDoc nameLast = parts[parts.length - 1];
104
105                         RolapStar.Measure m =
106                             star.getFactTable().lookupMeasureByName(nameLast);
107                         RolapAggregator agg = null;
108                         if (m != null) {
109                             agg = m.getAggregator();
110                         }
111                         // Ok, got a match, so now make a measure
112
makeMeasure(measure, agg, aggColumn);
113                         measureColumnCounts++;
114                     }
115                 }
116             }
117             // Ok, now look at all of the fact table columns with measure usage
118
// that have a sibling foreign key usage. These can be automagically
119
// generated for the aggregate table as long as it still has the
120
// foreign key.
121
for (Iterator JavaDoc<JdbcSchema.Table.Column.Usage> it =
122                      dbFactTable.getColumnUsages(JdbcSchema.UsageType.MEASURE);
123                  it.hasNext(); ) {
124                 JdbcSchema.Table.Column.Usage factUsage = it.next();
125                 JdbcSchema.Table.Column factColumn = factUsage.getColumn();
126
127                 if (factColumn.hasUsage(JdbcSchema.UsageType.FOREIGN_KEY)) {
128                     // What we've got here is a measure based upon a foreign key
129
String JavaDoc aggFK =
130                         getTableDef().getAggregateFK(factColumn.getName());
131                     // OK, not a lost dimension
132
if (aggFK != null) {
133                         JdbcSchema.Table.Column aggColumn =
134                             aggTable.getColumn(aggFK);
135
136                         // Column name match is case insensitive
137
if (aggColumn == null) {
138                             aggColumn = aggTable.getColumn(aggFK.toLowerCase());
139                         }
140                         if (aggColumn == null) {
141                             aggColumn = aggTable.getColumn(aggFK.toUpperCase());
142                         }
143
144                         if (aggColumn != null) {
145                             makeMeasure(factUsage, aggColumn);
146                             measureColumnCounts++;
147                         }
148                     }
149                 }
150             }
151             return measureColumnCounts;
152
153         } finally {
154             msgRecorder.popContextName();
155         }
156     }
157
158     /**
159      * Make a measure. This makes a measure usage using the Aggregator found in
160      * the RolapStar.Measure associated with the ExplicitRules.TableDef.Measure.
161      *
162      * @param measure
163      * @param aggColumn
164      */

165     protected void makeMeasure(
166             final ExplicitRules.TableDef.Measure measure,
167             RolapAggregator factAgg,
168             final JdbcSchema.Table.Column aggColumn) {
169         RolapStar.Measure rm = measure.getRolapStarMeasure();
170
171         JdbcSchema.Table.Column.Usage aggUsage =
172             aggColumn.newUsage(JdbcSchema.UsageType.MEASURE);
173
174         aggUsage.setSymbolicName(measure.getSymbolicName());
175         RolapAggregator ra = (factAgg == null)
176                     ? convertAggregator(aggUsage, rm.getAggregator())
177                     : convertAggregator(aggUsage, factAgg, rm.getAggregator());
178         aggUsage.setAggregator(ra);
179
180         aggUsage.rMeasure = rm;
181     }
182
183     /**
184      * This creates a foreign key usage.
185      *
186      * <p> First the column name of the fact usage which is a foreign key is used to
187      * search for a foreign key definition in the ExplicitRules.tableDef.
188      * If not found, thats ok, it is just a lost dimension.
189      * If found, look for a column in the aggregate table with that name and
190      * make a foreign key usage.
191      */

192     protected int matchForeignKey(
193             final JdbcSchema.Table.Column.Usage factUsage) {
194         JdbcSchema.Table.Column factColumn = factUsage.getColumn();
195         String JavaDoc aggFK = getTableDef().getAggregateFK(factColumn.getName());
196
197         // OK, a lost dimension
198
if (aggFK == null) {
199             return 0;
200         }
201
202         int matchCount = 0;
203         for (JdbcSchema.Table.Column aggColumn : aggTable.getColumns()) {
204             // if marked as ignore, then do not consider
205
if (aggColumn.hasUsage(JdbcSchema.UsageType.IGNORE)) {
206                 continue;
207             }
208
209             if (aggFK.equals(aggColumn.getName())) {
210                 makeForeignKey(factUsage, aggColumn, aggFK);
211                 matchCount++;
212             }
213         }
214         return matchCount;
215
216     }
217
218     /**
219      * This creates a level usage. A level usage is a column that is used in a
220      * collapsed dimension aggregate table.
221      *
222      * <p> First, iterate through the ExplicitRules.TableDef's level
223      * definitions for one with a name equal to the RolapLevel unique name,
224      * i.e., [Time].[Quarter]. Now, using the level's column name, search
225      * through the aggregate table's columns for one with that name and make a
226      * level usage for the column. Return true if the aggregate table's column
227      * was found.
228      */

229     protected boolean matchLevel(
230             final Hierarchy hierarchy,
231             final HierarchyUsage hierarchyUsage,
232             final RolapLevel rlevel) {
233         msgRecorder.pushContextName("ExplicitRecognizer.matchLevel");
234         try {
235
236             // Try to match a Level's name against the RolapLevel unique name.
237
String JavaDoc levelUniqueName = rlevel.getUniqueName();
238             for (ExplicitRules.TableDef.Level level : getTableDef().getLevels()) {
239                 if (level.getName().equals(levelUniqueName)) {
240                     // Ok, got a match, so now make a measue
241
//makeLevel(level, xxxxolumn);
242
// Now can we find a column in the aggTable that matches the
243
// Level's column
244
String JavaDoc columnName = level.getColumnName();
245                     for (JdbcSchema.Table.Column aggColumn : aggTable.getColumns()) {
246                         if (aggColumn.getName().equals(columnName)) {
247                             makeLevel(
248                                 aggColumn,
249                                 hierarchy,
250                                 hierarchyUsage,
251                                 getColumnName(rlevel.getKeyExp()),
252                                 columnName,
253                                 rlevel.getName());
254                             return true;
255                         }
256                     }
257
258                 }
259             }
260             return false;
261
262         } finally {
263             msgRecorder.popContextName();
264         }
265     }
266 }
267
268 // End ExplicitRecognizer.java
269
Popular Tags