rolapcube.java
来自「数据仓库展示程序」· Java 代码 · 共 1,687 行 · 第 1/5 页
JAVA
1,687 行
/*
// $Id: //open/mondrian/src/main/mondrian/rolap/RolapCube.java#64 $
// 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.
// Copyright (C) 2001-2005 Kana Software, Inc. and others.
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
// jhyde, 10 August, 2001
*/
package mondrian.rolap;
import mondrian.olap.*;
import mondrian.rolap.agg.AggregationManager;
import mondrian.rolap.aggmatcher.ExplicitRules;
import mondrian.resource.MondrianResource;
import org.apache.log4j.Logger;
import org.eigenbase.xom.*;
import org.eigenbase.xom.Parser;
import java.lang.reflect.Constructor;
import java.util.*;
import java.util.Set;
/**
* <code>RolapCube</code> implements {@link Cube} for a ROLAP database.
*
* @author jhyde
* @since 10 August, 2001
* @version $Id: //open/mondrian/src/main/mondrian/rolap/RolapCube.java#64 $
*/
public class RolapCube extends CubeBase {
private static final Logger LOGGER = Logger.getLogger(RolapCube.class);
private final RolapSchema schema;
private final RolapHierarchy measuresHierarchy;
/** For SQL generator. Fact table. */
final MondrianDef.Relation fact;
/** To access all measures stored in the fact table. */
private final CellReader cellReader;
/**
* Mapping such that
* <code>localDimensionOrdinals[dimension.globalOrdinal]</code> is equal to
* the ordinal of the dimension in this cube. See {@link
* RolapDimension#topic_ordinals}
*/
private int[] localDimensionOrdinals;
/** Schema reader which can see this cube and nothing else. */
private SchemaReader schemaReader;
/**
* List of calculated members.
*/
private Formula[] calculatedMembers;
/**
* List of named sets.
*/
private Formula[] namedSets;
/** Contains {@link HierarchyUsage}s for this cube */
private final List hierarchyUsages;
private RolapStar star;
private ExplicitRules.Group aggGroup;
/**
* private constructor used by both normal cubes and virtual cubes.
*
* @param schema
* @param name
* @param fact
*/
private RolapCube(RolapSchema schema,
MondrianDef.Schema xmlSchema,
String name,
boolean cache,
MondrianDef.Relation fact,
MondrianDef.CubeDimension[] dimensions) {
super(name, new RolapDimension[dimensions.length + 1]);
this.schema = schema;
this.fact = fact;
this.hierarchyUsages = new ArrayList();
this.cellReader = AggregationManager.instance();
this.calculatedMembers = new Formula[0];
this.namedSets = new Formula[0];
if (! isVirtual()) {
this.star = schema.getRolapStarRegistry().getOrCreateStar(fact);
// only set if different from default (so that if two cubes share
// the same fact table, either can turn off caching and both are
// effected).
if (! cache) {
star.setCacheAggregations(cache);
}
}
if (getLogger().isDebugEnabled()) {
if (isVirtual()) {
getLogger().debug("RolapCube<init>: virtual cube=" +this.name);
} else {
getLogger().debug("RolapCube<init>: cube=" +this.name);
}
}
RolapDimension measuresDimension = new RolapDimension(
schema,
Dimension.MEASURES_NAME,
0,
DimensionType.StandardDimension);
this.dimensions[0] = measuresDimension;
this.measuresHierarchy = measuresDimension.newHierarchy(null, false);
if (!Util.isEmpty(xmlSchema.measuresCaption)) {
measuresDimension.setCaption(xmlSchema.measuresCaption);
this.measuresHierarchy.setCaption(xmlSchema.measuresCaption);
}
for (int i = 0; i < dimensions.length; i++) {
MondrianDef.CubeDimension xmlCubeDimension = dimensions[i];
// Look up usages of shared dimensions in the schema before
// consulting the XML schema (which may be null).
RolapDimension dimension =
getOrCreateDimension(xmlCubeDimension, schema, xmlSchema);
if (getLogger().isDebugEnabled()) {
getLogger().debug("RolapCube<init>: dimension="
+dimension.getName());
}
this.dimensions[i + 1] = dimension;
if (! isVirtual()) {
createUsages(dimension, xmlCubeDimension);
}
}
schema.addCube(this);
}
/**
* Creates a <code>RolapCube</code> from a regular cube.
**/
RolapCube(RolapSchema schema,
MondrianDef.Schema xmlSchema,
MondrianDef.Cube xmlCube) {
this(schema, xmlSchema, xmlCube.name, xmlCube.cache.booleanValue(),
xmlCube.fact, xmlCube.dimensions);
if (fact.getAlias() == null) {
throw Util.newError(
"Must specify alias for fact table of cube " +
getUniqueName());
}
// since MondrianDef.Measure and MondrianDef.VirtualCubeMeasure
// can not be treated as the same, measure creation can not be
// done in a common constructor.
RolapLevel measuresLevel =
this.measuresHierarchy.newLevel("MeasuresLevel", 0);
RolapStoredMeasure measures[] = new RolapStoredMeasure[
xmlCube.measures.length];
for (int i = 0; i < xmlCube.measures.length; i++) {
MondrianDef.Measure xmlMeasure = xmlCube.measures[i];
MondrianDef.Column column =
new MondrianDef.Column(fact.getAlias(), xmlMeasure.column);
final RolapStoredMeasure measure = new RolapStoredMeasure(
this, null, measuresLevel, xmlMeasure.name,
xmlMeasure.formatString, column,
xmlMeasure.aggregator, xmlMeasure.datatype);
measures[i] = measure;
if (!Util.isEmpty(xmlMeasure.formatter)) {
// there is a special cell formatter class
try {
Class clazz = Class.forName(xmlMeasure.formatter);
Constructor ctor = clazz.getConstructor(new Class[0]);
CellFormatter cellFormatter =
(CellFormatter) ctor.newInstance(new Object[0]);
measure.setFormatter(cellFormatter);
} catch (Exception e) {
e.printStackTrace();
}
}
// Set member's caption, if present.
if (!Util.isEmpty(xmlMeasure.caption)) {
// there is a special caption string
measure.setProperty(
Property.CAPTION.name,
xmlMeasure.caption);
}
// Set member's visibility, default true.
Boolean visible = xmlMeasure.visible;
if (visible == null) {
visible = Boolean.TRUE;
}
measure.setProperty(Property.VISIBLE.name, visible);
List propNames = new ArrayList();
List propExprs = new ArrayList();
validateMemberProps(xmlMeasure.memberProperties, propNames,
propExprs, xmlMeasure.name);
for (int j = 0; j < propNames.size(); j++) {
String propName = (String) propNames.get(j);
final Object propExpr = propExprs.get(j);
measure.setProperty(propName, propExpr);
}
}
this.measuresHierarchy.memberReader = new CacheMemberReader(
new MeasureMemberSource(this.measuresHierarchy, measures));
init(xmlCube.dimensions);
init(xmlCube);
loadAggGroup(xmlCube);
}
/**
* Creates a <code>RolapCube</code> from a virtual cube.
**/
RolapCube(RolapSchema schema,
MondrianDef.Schema xmlSchema,
MondrianDef.VirtualCube xmlVirtualCube) {
this(schema, xmlSchema, xmlVirtualCube.name, true,
null, xmlVirtualCube.dimensions);
// since MondrianDef.Measure and MondrianDef.VirtualCubeMeasure
// can not be treated as the same, measure creation can not be
// done in a common constructor.
this.measuresHierarchy.newLevel("MeasuresLevel", 0);
RolapMeasure measures[] = new RolapMeasure[
xmlVirtualCube.measures.length];
for (int i = 0; i < xmlVirtualCube.measures.length; i++) {
// Lookup a measure in an existing cube. (Don't know whether it
// will confuse things that this measure still points to its 'real'
// cube.)
MondrianDef.VirtualCubeMeasure xmlMeasure =
xmlVirtualCube.measures[i];
RolapCube cube = (RolapCube) schema.lookupCube(xmlMeasure.cubeName);
Member[] cubeMeasures = cube.getMeasures();
for (int j = 0; j < cubeMeasures.length; j++) {
if (cubeMeasures[j].getUniqueName().equals(xmlMeasure.name)) {
measures[i] = (RolapMeasure) cubeMeasures[j];
break;
}
}
if (measures[i] == null) {
throw Util.newInternal(
"could not find measure '" + xmlMeasure.name +
"' in cube '" + xmlMeasure.cubeName + "'");
}
}
this.measuresHierarchy.memberReader = new CacheMemberReader(
new MeasureMemberSource(this.measuresHierarchy, measures));
init(xmlVirtualCube.dimensions);
// Note: virtual cubes do not get aggregate
}
protected Logger getLogger() {
return LOGGER;
}
public boolean hasAggGroup() {
return (aggGroup != null);
}
public ExplicitRules.Group getAggGroup() {
return aggGroup;
}
void loadAggGroup(MondrianDef.Cube xmlCube) {
aggGroup = ExplicitRules.Group.make(this, xmlCube);
}
/**
* Creates a dimension from its XML definition. If the XML definition is
* a <DimensionUsage>, and the shared dimension is cached in the
* schema, returns that.
*
* @param xmlCubeDimension XML Dimension or DimensionUsage
* @param schema Schema
* @param xmlSchema XML Schema
* @return A dimension
*/
private RolapDimension getOrCreateDimension(
MondrianDef.CubeDimension xmlCubeDimension,
RolapSchema schema,
MondrianDef.Schema xmlSchema) {
if (xmlCubeDimension instanceof MondrianDef.DimensionUsage) {
MondrianDef.DimensionUsage usage =
(MondrianDef.DimensionUsage) xmlCubeDimension;
final RolapHierarchy sharedHierarchy =
schema.getSharedHierarchy(usage.source);
if (sharedHierarchy != null) {
return (RolapDimension) sharedHierarchy.getDimension();
}
}
MondrianDef.Dimension xmlDimension =
xmlCubeDimension.getDimension(xmlSchema);
return new RolapDimension(schema, this, xmlDimension,
xmlCubeDimension);
}
/**
* Post-initialization, doing things which cannot be done in the
* constructor.
*/
private void init(MondrianDef.Cube xmlCube) {
// Load calculated members and named sets.
// (We cannot do this in the constructor, because
// cannot parse the generated query, because the schema has not been
// set in the cube at this point.)
List memberList = new ArrayList();
List formulaList = new ArrayList();
createCalcMembersAndNamedSets(
xmlCube.calculatedMembers, xmlCube.namedSets,
memberList, formulaList);
}
/**
* Adds a collection of calculated members and named sets to this cube.
* The members and sets can refer to each other.
*
* @param xmlCalcMembers XML objects representing members
* @param xmlNamedSets Array of XML definition of named set
* @param memberList Output list of {@link Member} objects
* @param formulaList Output list of {@link Formula} objects
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?