explicitrules.java
来自「数据仓库展示程序」· Java 代码 · 共 1,597 行 · 第 1/4 页
JAVA
1,597 行
}
/**
* This class is used to map from a measure's symbolic name,
* [Measures].[Unit Sales] to the aggregate table's column
* name, UNIT_SALES_SUM.
*/
class Measure {
private final String name;
private String symbolicName;
private final String columnName;
private RolapStar.Measure rolapMeasure;
Measure(final String name, final String columnName) {
this.name = name;
this.columnName = columnName;
}
/**
* Get the symbolic name, the measure name, i.e.,
* [Measures].[Unit Sales].
*
* @return
*/
public String getName() {
return name;
}
/**
* Get the symbolic name, the measure name, i.e., [Unit Sales].
*
* @return
*/
public String getSymbolicName() {
return symbolicName;
}
/**
* Get the aggregate table column name.
*
* @return
*/
public String getColumnName() {
return columnName;
}
/**
* Get the RolapStar.Measure associated with this symbolic name.
*
* @return
*/
public RolapStar.Measure getRolapStarMeasure() {
return rolapMeasure;
}
/**
* Validates a measure's name
* AggMeasure name is a [Measures].[measure name]
* Check that is of length 2, starts with "Measures" and
* the "measure name" exists.
*
* @param msgRecorder
*/
public void validate(final MessageRecorder msgRecorder) {
msgRecorder.pushContextName("Measure");
try {
String name = getName();
String column = getColumnName();
checkAttributeString(msgRecorder, name, "name");
checkAttributeString(msgRecorder, column, "column");
String[] names = Util.explode(name);
if (names.length != 2) {
msgRecorder.reportError(
mres.BadMeasureNameFormat.str(
msgRecorder.getContext(),
name));
} else {
RolapCube cube = ExplicitRules.TableDef.this.getCube();
SchemaReader schemaReader = cube.getSchemaReader();
Member member = (Member) schemaReader.lookupCompound(
cube,
names,
false,
Category.Member);
if (member == null) {
if (! names[0].equals("Measures")) {
msgRecorder.reportError(
mres.BadMeasures.str(
msgRecorder.getContext(),
names[0]));
} else {
msgRecorder.reportError(
mres.UnknownMeasureName.str(
msgRecorder.getContext(),
names[1]));
}
}
RolapStar star = cube.getStar();
rolapMeasure =
star.getFactTable().lookupMeasureByName(names[1]);
if (rolapMeasure == null) {
msgRecorder.reportError(
mres.BadMeasureName.str(
msgRecorder.getContext(),
names[1],
cube.getName()));
}
symbolicName = names[1];
}
} finally {
msgRecorder.popContextName();
}
}
public String toString() {
StringWriter sw = new StringWriter(256);
PrintWriter pw = new PrintWriter(sw);
print(pw, "");
pw.flush();
return sw.toString();
}
public void print(final PrintWriter pw, final String prefix) {
pw.print(prefix);
pw.println("Measure:");
String subprefix = prefix + " ";
pw.print(subprefix);
pw.print("name=");
pw.println(this.name);
pw.print(subprefix);
pw.print("column=");
pw.println(this.columnName);
}
}
private static int idCount = 0;
private static int nextId() {
return idCount++;
}
protected final int id;
protected final boolean ignoreCase;
protected final ExplicitRules.Group aggGroup;
protected String factCountName;
protected List ignoreColumnNames;
private Map foreignKeyMap;
private List levels;
private List measures;
protected TableDef(final boolean ignoreCase,
final ExplicitRules.Group aggGroup) {
this.id = nextId();
this.ignoreCase = ignoreCase;
this.aggGroup = aggGroup;
this.foreignKeyMap = Collections.EMPTY_MAP;
this.levels = Collections.EMPTY_LIST;
this.measures = Collections.EMPTY_LIST;
this.ignoreColumnNames = Collections.EMPTY_LIST;
}
/**
* TODO: This does not seemed to be used anywhere???
*
* @return
*/
public int getId() {
return this.id;
}
/**
* Return true if this name/pattern matching ignores case.
*
* @return
*/
public boolean isIgnoreCase() {
return this.ignoreCase;
}
/**
* Get the RolapStar associated with this cube.
*
* @return
*/
public RolapStar getStar() {
return getAggGroup().getStar();
}
/**
* Get the Group with which is a part.
*
* @return
*/
public ExplicitRules.Group getAggGroup() {
return this.aggGroup;
}
/**
* Get the name of the fact count column.
*
* @return
*/
protected String getFactCountName() {
return factCountName;
}
/**
* Set the name of the fact count column.
*
* @param factCountName
*/
protected void setFactCountName(final String factCountName) {
this.factCountName = factCountName;
}
/**
* Get an Iterator over all ignore column name entries.
*
* @return
*/
protected Iterator getIgnoreColumnNames() {
return ignoreColumnNames.iterator();
}
/**
* Get an Iterator over all level mappings.
*
* @return
*/
public Iterator getLevels() {
return this.levels.iterator();
}
/**
* Get an Iterator over all level mappings.
*
* @return
*/
public Iterator getMeasures() {
return this.measures.iterator();
}
/**
* Get Matcher for ignore columns.
*
* @return
*/
protected Recognizer.Matcher getIgnoreMatcher() {
return new Recognizer.Matcher() {
public boolean matches(final String name) {
for (Iterator it =
ExplicitRules.TableDef.this.getIgnoreColumnNames();
it.hasNext();) {
String ignoreName = (String) it.next();
if (ignoreName.equals(name)) {
return true;
}
}
return false;
}
};
}
/**
* Get Matcher for the fact count column.
*
* @return
*/
protected Recognizer.Matcher getFactCountMatcher() {
return new Recognizer.Matcher() {
public boolean matches(String name) {
// Match is case insensitive
return ExplicitRules.TableDef.this.factCountName.equalsIgnoreCase(name);
}
};
}
/**
* Get the RolapCube associated with this mapping.
*
* @return
*/
RolapCube getCube() {
return aggGroup.getCube();
}
/**
* Check that ALL of the columns in the dbTable have a mapping in in the
* tableDef.
* <p>
* It is an error if there is a column that does not have a mapping.
*
* @param star
* @param dbFactTable
* @param dbTable
* @param msgRecorder
* @return
*/
public boolean columnsOK(final RolapStar star,
final JdbcSchema.Table dbFactTable,
final JdbcSchema.Table dbTable,
final MessageRecorder msgRecorder) {
Recognizer cb = new ExplicitRecognizer(this,
star,
dbFactTable,
dbTable,
msgRecorder);
return cb.check();
}
/**
* Add the name of an aggregate table column that is to be ignored.
*
* @param ignoreName
*/
protected void addIgnoreColumnName(final String ignoreName) {
if (this.ignoreColumnNames == Collections.EMPTY_LIST) {
this.ignoreColumnNames = new ArrayList();
}
this.ignoreColumnNames.add(ignoreName);
}
/**
* Add foreign key mapping entry (maps from fact table foreign key
* column name to aggregate table foreign key column name).
*
* @param fk
*/
protected void addFK(final MondrianDef.AggForeignKey fk) {
if (this.foreignKeyMap == Collections.EMPTY_MAP) {
this.foreignKeyMap = new HashMap();
}
this.foreignKeyMap.put(fk.getFactFKColumnName(),
fk.getAggregateFKColumnName());
}
/**
* Get the name of the aggregate table's foreign key column that matches
* the base fact table's foreign key column or return null.
*
* @param baseFK
* @return
*/
protected String getAggregateFK(final String baseFK) {
return (String) this.foreignKeyMap.get(baseFK);
}
/**
* Get an Iterator over the foreign key matchers.
*
* @return
*/
protected Iterator getFKEntries() {
return this.foreignKeyMap.entrySet().iterator();
}
/**
* Add a Level.
*
* @param level
*/
protected void add(final Level level) {
if (this.levels == Collections.EMPTY_LIST) {
this.levels = new ArrayList();
}
this.levels.add(level);
}
/**
* Add a Measure.
*
* @param measure
*/
protected void add(final Measure measure) {
if (this.measures == Collections.EMPTY_LIST) {
this.measures = new ArrayList();
}
this.measures.add(measure);
}
/**
* Does the TableDef match a table with name tableName.
*
* @param tableName
* @return
*/
public abstract boolean matches(final String tableName);
/**
* Validate the Levels and Measures, also make sure each definition
* is different, both name and column.
*
* @param msgRecorder
*/
public void validate(final MessageRecorder msgRecorder) {
msgRecorder.pushContextName("TableDef");
try {
// used to detect duplicates
Map namesToObjects = new HashMap();
// used to detect duplicates
Map columnsToObjects = new HashMap();
for (Iterator it = levels.iterator(); it.hasNext(); ) {
Level level = (Level) it.next();
level.validate(msgRecorder);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?