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 &lt;DimensionUsage&gt;, 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 + -
显示快捷键?