hierarchyusage.java
来自「数据仓库展示程序」· Java 代码 · 共 444 行
JAVA
444 行
/*
// $Id: //open/mondrian/src/main/mondrian/rolap/HierarchyUsage.java#14 $
// This software is subject to the terms of the Common Public License
// Agreement, available at the following URL:
// http://www.opensource.org/licenses/cpl.html.
// (C) Copyright 2002-2005 Kana Software, Inc. and others.
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
// jhyde, 21 March, 2002
*/
package mondrian.rolap;
import mondrian.olap.*;
import mondrian.resource.MondrianResource;
import org.apache.log4j.Logger;
/**
* A <code>HierarchyUsage</code> is the usage of a hierarchy in the context
* of a cube. Private hierarchies can only be used in their own
* cube. Public hierarchies can be used in several cubes. The problem comes
* when several cubes which the same public hierarchy are brought together
* in one virtual cube. There are now several usages of the same public
* hierarchy. Which one to use? It depends upon what measure we are
* currently using. We should use the hierarchy usage for the fact table
* which underlies the measure. That is what determines the foreign key to
* join on.
*
* A <code>HierarchyUsage</code> is identified by
* <code>(hierarchy.sharedHierarchy, factTable)</code> if the hierarchy is
* shared, or <code>(hierarchy, factTable)</code> if it is private.
*
* @author jhyde
* @since 21 March, 2002
* @version $Id: //open/mondrian/src/main/mondrian/rolap/HierarchyUsage.java#14 $
**/
public class HierarchyUsage {
private static final Logger LOGGER = Logger.getLogger(HierarchyUsage.class);
static final int UNKNOWN_KIND = 0;
static final int SHARED_KIND = 1;
static final int VIRTUAL_KIND = 2;
static final int PRIVATE_KIND = 3;
static String lookupKindName(int kind) {
String name = null;
switch (kind) {
case HierarchyUsage.SHARED_KIND :
name = "SHARED";
break;
case HierarchyUsage.VIRTUAL_KIND :
name = "VIRTUAL";
break;
case HierarchyUsage.PRIVATE_KIND :
name = "PRIVATE";
break;
case HierarchyUsage.UNKNOWN_KIND :
default :
name = "UNKNOWN";
break;
}
return name;
}
/**
* Fact table (or relation) which this usage is joining to. This
* identifies the usage, and determines which join conditions need to be
* used.
*/
protected final MondrianDef.Relation fact;
/**
* This matches the hierarchy - may not be unique.
* NOT NULL.
*/
private final String hierarchyName;
/**
* not NULL for DimensionUsage
* not NULL for Dimension
*/
private final String name;
/**
* This is the name used to look up the hierachy usage. When the dimension
* has only a single hierachy, then the fullName is simply the
* CubeDimension name; there is no need to use the default dimension name.
* But, when the dimension has more than one hierachy, then the fullName
* is the CubeDimension dotted with the dimension hierachy name.
*/
private final String fullName;
/**
* The foreign key by which this {@link Hierarchy} is joined to
* the {@link #fact} table.
*/
private final String foreignKey;
/**
* not NULL for DimensionUsage
* NULL for Dimension
*/
private final String source;
/**
* May be null, this is the field that is used to disambiguate column
* names in aggregate tables
*/
private final String usagePrefix;
// NOT USED
private final String level;
//final String type;
//final String caption;
/**
* Dimension table which contains the primary key for the hierarchy.
* (Usually the table of the lowest level of the hierarchy.)
*/
private MondrianDef.Relation joinTable;
/**
* The expression (usually a {@link MondrianDef.Column}) by which the
* hierarchy which is joined to the fact table.
*/
private MondrianDef.Expression joinExp;
private final int kind;
/**
*
*
* @param cube
* @param hierarchy
* @param cubeDim
*/
HierarchyUsage(RolapCube cube,
RolapHierarchy hierarchy,
MondrianDef.CubeDimension cubeDim) {
assert cubeDim != null : "precondition: cubeDim != null";
this.fact = cube.fact;
// Attributes common to all Hierarchy kinds
// name
// foreignKey
this.name = cubeDim.name;
this.foreignKey = cubeDim.foreignKey;
if (cubeDim instanceof MondrianDef.DimensionUsage) {
this.kind = HierarchyUsage.SHARED_KIND;
// Shared Hierarchy attributes
// source
// level
MondrianDef.DimensionUsage du =
(MondrianDef.DimensionUsage) cubeDim;
// Bug 657 - disable hierarchy aliasing
if (! du.name.equals(du.source)) {
StringBuffer buf = new StringBuffer();
buf.append("Cube \"");
buf.append(cube.getName());
buf.append("\": DimensionUsage name (\"");
buf.append(du.name);
buf.append("\") must equal source (\"");
buf.append(du.source);
buf.append("\")");
throw new MondrianException(buf.toString());
}
//this.hierarchyName = du.source;
this.hierarchyName = hierarchy.getName();
int index = this.hierarchyName.indexOf('.');
if (index == -1) {
this.fullName = this.name;
this.source = du.source;
} else {
String hname= this.hierarchyName.substring(
index+1, this.hierarchyName.length());
StringBuffer buf = new StringBuffer(32);
buf.append(this.name);
buf.append('.');
buf.append(hname);
this.fullName = buf.toString();
buf.setLength(0);
buf.append(du.source);
buf.append('.');
buf.append(hname);
this.source = buf.toString();
}
this.level = du.level;
this.usagePrefix = du.usagePrefix;
init(cube, hierarchy, du);
} else if (cubeDim instanceof MondrianDef.Dimension) {
this.kind = HierarchyUsage.PRIVATE_KIND;
// Private Hierarchy attributes
// type
// caption
MondrianDef.Dimension d = (MondrianDef.Dimension) cubeDim;
this.hierarchyName = hierarchy.getName();
this.fullName = this.name;
this.source = null;
this.usagePrefix = null;
this.level = null;
init(cube, hierarchy, null);
} else if (cubeDim instanceof MondrianDef.VirtualCubeDimension) {
this.kind = HierarchyUsage.VIRTUAL_KIND;
// Virtual Hierarchy attributes
MondrianDef.VirtualCubeDimension vd =
(MondrianDef.VirtualCubeDimension) cubeDim;
this.hierarchyName = cubeDim.name;
this.fullName = this.name;
this.source = null;
this.usagePrefix = null;
this.level = null;
init(cube, hierarchy, null);
} else {
getLogger().warn("HierarchyUsage<init>: Unknown cubeDim="
+cubeDim.getClass().getName());
this.kind = HierarchyUsage.UNKNOWN_KIND;
this.hierarchyName = cubeDim.name;
this.fullName = this.name;
this.source = null;
this.usagePrefix = null;
this.level = null;
init(cube, hierarchy, null);
}
if (getLogger().isDebugEnabled()) {
getLogger().debug(toString()
+ ", cubeDim="
+ cubeDim.getClass().getName());
}
}
protected Logger getLogger() {
return LOGGER;
}
public String getHierarchyName() {
return this.hierarchyName;
}
public String getFullName() {
return this.fullName;
}
public String getName() {
return this.name;
}
public String getForeignKey() {
return this.foreignKey;
}
public String getSource() {
return this.source;
}
public String getLevelName() {
return this.level;
}
public String getUsagePrefix() {
return this.usagePrefix;
}
public MondrianDef.Relation getJoinTable() {
return this.joinTable;
}
public MondrianDef.Expression getJoinExp() {
return this.joinExp;
}
public int getKind() {
return this.kind;
}
public boolean isShared() {
return (this.kind == HierarchyUsage.SHARED_KIND);
}
public boolean isVirtual() {
return (this.kind == HierarchyUsage.VIRTUAL_KIND);
}
public boolean isPrivate() {
return (this.kind == HierarchyUsage.PRIVATE_KIND);
}
public boolean equals(Object o) {
if (o instanceof HierarchyUsage) {
HierarchyUsage other = (HierarchyUsage) o;
return (this.kind == other.kind) &&
Util.equals(this.fact, other.fact) &&
Util.equals(this.hierarchyName, other.hierarchyName) &&
Util.equals(this.name, other.name) &&
Util.equals(this.source, other.source) &&
Util.equals(this.foreignKey, other.foreignKey);
} else {
return false;
}
}
public int hashCode() {
int h = fact.hashCode();
h = Util.hash(h, hierarchyName);
h = Util.hash(h, name);
h = Util.hash(h, source);
h = Util.hash(h, foreignKey);
return h;
}
public String toString() {
StringBuffer buf = new StringBuffer(100);
buf.append("HierarchyUsage: ");
buf.append("kind=");
buf.append(HierarchyUsage.lookupKindName(this.kind));
buf.append(", hierarchyName=");
buf.append(this.hierarchyName);
buf.append(", fullName=");
buf.append(this.fullName);
buf.append(", foreignKey=");
buf.append(this.foreignKey);
buf.append(", source=");
buf.append(this.source);
buf.append(", level=");
buf.append(this.level);
buf.append(", name=");
buf.append(this.name);
return buf.toString();
}
void init(RolapCube cube,
RolapHierarchy hierarchy,
MondrianDef.DimensionUsage cubeDim) {
// Three ways that a hierarchy can be joined to the fact table.
if (cubeDim != null && cubeDim.level != null) {
// 1. Specify an explicit 'level' attribute in a <DimensionUsage>.
RolapLevel joinLevel = (RolapLevel)
Util.lookupHierarchyLevel(hierarchy, cubeDim.level);
if (joinLevel == null) {
throw MondrianResource.instance()
.DimensionUsageHasUnknownLevel.ex(
hierarchy.getUniqueName(),
cube.getUniqueName(),
cubeDim.level);
}
this.joinTable = findJoinTable(hierarchy, joinLevel.getKeyExp().getTableAlias());
this.joinExp = joinLevel.getKeyExp();
} else if (hierarchy.xmlHierarchy != null &&
hierarchy.xmlHierarchy.primaryKey != null) {
// 2. Specify a "primaryKey" attribute of in <Hierarchy>. You must
// also specify the "primaryKeyTable" attribute if the hierarchy
// is a join (hence has more than one table).
this.joinTable = findJoinTable(hierarchy,
hierarchy.xmlHierarchy.primaryKeyTable);
this.joinExp = new MondrianDef.Column(this.joinTable.getAlias(),
hierarchy.xmlHierarchy.primaryKey);
} else {
// 3. If neither of the above, the join is assumed to be to key of
// the last level.
final Level[] levels = hierarchy.getLevels();
RolapLevel joinLevel = (RolapLevel) levels[levels.length - 1];
this.joinTable = findJoinTable(hierarchy,
joinLevel.getKeyExp().getTableAlias());
this.joinExp = joinLevel.getKeyExp();
}
/*
RME
Util.assertTrue(Util.equals(foreignKey, hierarchy.foreignKey));
*/
// Unless this hierarchy is drawing from the fact table, we need
// a join expresion and a foreign key.
final boolean inFactTable = this.joinTable.equals(cube.getFact());
if (!inFactTable) {
if (this.joinExp == null) {
throw MondrianResource.instance()
.MustSpecifyPrimaryKeyForHierarchy.ex(
hierarchy.getUniqueName(),
cube.getUniqueName());
}
if (foreignKey == null) {
throw MondrianResource.instance()
.MustSpecifyForeignKeyForHierarchy.ex(
hierarchy.getUniqueName(),
cube.getUniqueName());
}
}
}
/**
* Chooses the table with which to join a hierarchy to the fact table.
*
* @param hierarchy Hierarchy to be joined
* @param tableName Alias of the table; may be omitted if the hierarchy
* has only one table
* @return A table, never null
*/
private MondrianDef.Relation findJoinTable(
RolapHierarchy hierarchy,
String tableName)
{
final MondrianDef.Relation table;
if (tableName == null) {
table = hierarchy.getUniqueTable();
if (table == null) {
throw MondrianResource.instance()
.MustSpecifyPrimaryKeyTableForHierarchy.ex(
hierarchy.getUniqueName());
}
} else {
table = hierarchy.getRelation().find(tableName);
if (table == null) {
// todo: i18n msg
throw Util.newError(
"no table '" + tableName +
"' found in hierarchy " + hierarchy.getUniqueName());
}
}
return table;
}
}
// End HierarchyUsage.java
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?