rolaphierarchy.java

来自「数据仓库展示程序」· Java 代码 · 共 597 行 · 第 1/2 页

JAVA
597
字号
/*
// $Id: //open/mondrian/src/main/mondrian/rolap/RolapHierarchy.java#37 $
// 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 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.olap.fun.BuiltinFunTable;
import mondrian.olap.type.Type;
import mondrian.olap.type.MemberType;
import mondrian.rolap.sql.SqlQuery;
import mondrian.resource.MondrianResource;

import org.apache.log4j.Logger;
import java.util.List;

/**
 * <code>RolapHierarchy</code> implements {@link Hierarchy} for a ROLAP database.
 *
 * @author jhyde
 * @since 10 August, 2001
 * @version $Id: //open/mondrian/src/main/mondrian/rolap/RolapHierarchy.java#37 $
 */
class RolapHierarchy extends HierarchyBase {

    private static final Logger LOGGER = Logger.getLogger(RolapHierarchy.class);

    /**
     * The raw member reader. For a member reader which incorporates access
     * control and deals with hidden members (if the hierarchy is ragged), use
     * {@link #getMemberReader(Role)}.
     */
    MemberReader memberReader;
    MondrianDef.Hierarchy xmlHierarchy;
    private String memberReaderClass;
    private MondrianDef.Relation relation;
    private Member defaultMember;
    private String defaultMemberName;
    private RolapNullMember nullMember;

    /**
     * If this hierarchy is a public -- that is, it belongs to a dimension
     * which is a usage of a shared dimension -- then
     * <code>sharedHierarchy</code> holds the unique name of the shared
     * hierarchy; otherwise it is null.
     *
     * <p> Suppose this hierarchy is "Weekly" in the dimension "Order Date" of
     * cube "Sales", and that "Order Date" is a usage of the "Time"
     * dimension. Then <code>sharedHierarchy</code> will be "[Time].[Weekly]".
     **/
    private String sharedHierarchy;

    private Exp aggregateChildrenExpression;

    // for newClosedPeerHierarchy() to copy; but never used??
    private String primaryKey;

    /**
     * Type for members of this hierarchy. Set once to avoid excessive newing.
     */
    final Type memberType = new MemberType(this, null, null);

    RolapHierarchy(RolapDimension dimension, String subName, boolean hasAll) {
        super(dimension, subName, hasAll);

        this.levels = new RolapLevel[0];
        setCaption(dimension.getCaption());

        if (hasAll) {
            this.allLevelName = "(All)";
            Util.discard(newLevel(this.allLevelName,
                    RolapLevel.ALL | RolapLevel.UNIQUE));
            this.allMemberName = "All " + name + "s";
        }
    }

    /**
     * Creates a <code>RolapHierarchy</code>.
     *
     * @param cube Cube this hierarchy belongs to, or null if this is a shared
     *     hierarchy
     */
    RolapHierarchy(RolapCube cube, RolapDimension dimension,
            MondrianDef.Hierarchy xmlHierarchy,
            MondrianDef.CubeDimension xmlCubeDimension) {
        this(dimension, xmlHierarchy.name, xmlHierarchy.hasAll.booleanValue());

        if (xmlHierarchy.relation == null &&
                xmlHierarchy.memberReaderClass == null &&
                cube != null) {
            xmlHierarchy.relation = cube.fact;
        }
        this.xmlHierarchy = xmlHierarchy;
        this.relation = xmlHierarchy.relation;
        this.memberReaderClass = xmlHierarchy.memberReaderClass;
        if (hasAll) {
            if (xmlHierarchy.allMemberName != null) {
                this.allMemberName = xmlHierarchy.allMemberName;
            }
            if (xmlHierarchy.allLevelName != null) {
                this.allLevelName = xmlHierarchy.allLevelName;
            }
            this.levels = new RolapLevel[xmlHierarchy.levels.length + 1];
            this.levels[0] = new RolapLevel(
                    this, 0, this.allLevelName, null, null, null, null, null, null,
                    null, RolapProperty.emptyArray,
                    RolapLevel.ALL | RolapLevel.UNIQUE,
                    RolapLevel.HideMemberCondition.Never,
                    LevelType.Regular);
            for (int i = 0; i < xmlHierarchy.levels.length; i++) {
                final MondrianDef.Level xmlLevel = xmlHierarchy.levels[i];
                if (xmlLevel.getKeyExp() == null &&
                        xmlHierarchy.memberReaderClass == null) {
                    throw MondrianResource.instance().LevelMustHaveNameExpression.ex(xmlLevel.name);
                }
                levels[i + 1] = new RolapLevel(this, i + 1, xmlLevel);
            }
        } else {
            this.levels = new RolapLevel[xmlHierarchy.levels.length];
            for (int i = 0; i < xmlHierarchy.levels.length; i++) {
                levels[i] = new RolapLevel(this, i, xmlHierarchy.levels[i]);
            }
        }
        if (xmlCubeDimension instanceof MondrianDef.DimensionUsage) {
            String sharedDimensionName =
                ((MondrianDef.DimensionUsage) xmlCubeDimension).source;
            this.sharedHierarchy = sharedDimensionName;
            if (subName != null) {
                this.sharedHierarchy += "." + subName; // e.g. "Time.Weekly"
            }
        } else {
            this.sharedHierarchy = null;
        }
        if (xmlHierarchy.relation != null &&
                xmlHierarchy.memberReaderClass != null) {
            throw MondrianResource.instance().HierarchyMustNotHaveMoreThanOneSource.ex(getUniqueName());
        }
        this.primaryKey = xmlHierarchy.primaryKey;
        if (!Util.isEmpty(xmlHierarchy.caption)) {
            setCaption(xmlHierarchy.caption);
        }
        defaultMemberName = xmlHierarchy.defaultMember;
    }

    protected Logger getLogger() {
        return LOGGER;
    }

    public boolean equals(Object o) {
        if (!(o instanceof RolapHierarchy)) {
            return false;
        }
        if (this == o) {
            return true;
        }

        RolapHierarchy that = (RolapHierarchy)o;
        return ((sharedHierarchy == null) || (that.sharedHierarchy == null))
            ? false
            : (sharedHierarchy.equals(that.sharedHierarchy) &&
                getUniqueName().equals(that.getUniqueName()));
    }

    public int hashCode() {
        return super.hashCode() ^ (sharedHierarchy == null
            ? 0
            : sharedHierarchy.hashCode());
    }

    /**
     * Initializes a hierarchy within the context of a cube.
     */
    void init(RolapCube cube, MondrianDef.CubeDimension xmlDimension) {
        for (int i = 0; i < levels.length; i++) {
            ((RolapLevel) levels[i]).init(cube, xmlDimension);
        }
        if (this.memberReader == null) {
            this.memberReader = getRolapSchema().createMemberReader(
                sharedHierarchy, this, memberReaderClass);
        }
        if (defaultMemberName != null) {
            String[] uniqueNameParts = Util.explode(defaultMemberName);

            // We strip off the parent dimension name if the defaultMemberName
            // is the full unique name, [Time].[2004] rather than simply
            // [2004].
            Dimension dim = getDimension();
            if (dim.getName().equals(uniqueNameParts[0])) {
                String[] tmp = new String[uniqueNameParts.length-1];
                System.arraycopy(uniqueNameParts, 1, tmp, 0,
                                uniqueNameParts.length-1);
                uniqueNameParts = tmp;
            }

            // Now lookup the name from the hierarchy's members.
            defaultMember = memberReader.lookupMember(uniqueNameParts, false);
            if (defaultMember == null) {
                throw Util.newInternal(
                    "Can not find Default Member with name \""
                        + defaultMemberName + "\"");
            }
        }
    }

    RolapLevel newLevel(String name, int flags) {
        RolapLevel level = new RolapLevel(
                this, this.levels.length, name, null, null, null, null,
                null, null, null, RolapProperty.emptyArray, flags,
                RolapLevel.HideMemberCondition.Never, LevelType.Regular);
        this.levels = (RolapLevel[]) RolapUtil.addElement(this.levels, level);
        return level;
    }

    /**
     * If this hierarchy has precisely one table, returns that table;
     * if this hierarchy has no table, return the cube's fact-table;
     * otherwise, returns null.
     */
    MondrianDef.Relation getUniqueTable() {
        if (relation instanceof MondrianDef.Table ||
                relation instanceof MondrianDef.View) {
            return relation;
        } else if (relation instanceof MondrianDef.Join) {
            return null;
        } else {
            throw Util.newInternal(
                    "hierarchy's relation is a " + relation.getClass());
        }
    }

    boolean tableExists(String tableName) {
        return (relation != null) && tableExists(tableName, relation);
    }

    private static boolean tableExists(String tableName,
                                       MondrianDef.Relation relation) {
        if (relation instanceof MondrianDef.Table) {
            MondrianDef.Table table = (MondrianDef.Table) relation;
            // Check by table name and alias
            return table.name.equals(tableName) ||
                ((table.alias != null) && table.alias.equals(tableName));
        }
        if (relation instanceof MondrianDef.Join) {
            MondrianDef.Join join = (MondrianDef.Join) relation;
            return tableExists(tableName, join.left) ||
                tableExists(tableName, join.right);
        }
        return false;
    }

    RolapSchema getRolapSchema() {
        return (RolapSchema) dimension.getSchema();
    }

    MondrianDef.Relation getRelation() {
        return relation;
    }

    public Member getDefaultMember() {
        // use lazy initialization to get around bootstrap issues
        if (defaultMember == null) {
            List rootMembers = memberReader.getRootMembers();
            if (rootMembers.size() == 0) {
                throw MondrianResource.instance().InvalidHierarchyCondition.ex(this.getUniqueName());
/*
                throw Util.newError(
                    "cannot get default member: hierarchy " + getUniqueName() +
                    " has no root members");
*/
            }
            defaultMember = (RolapMember) rootMembers.get(0);
        }
        return defaultMember;
    }

    public Member getNullMember() {
        // use lazy initialization to get around bootstrap issues
        if (nullMember == null) {
            nullMember = new RolapNullMember(this);
        }
        return nullMember;
    }

    public Member createMember(Member parent,
                               Level level,
                               String name,
                               Formula formula) {
        return (formula != null)
            ? new RolapCalculatedMember(
                (RolapMember) parent, (RolapLevel) level, name, formula)
            : new RolapMember(

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?