rolapevaluator.java

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

JAVA
517
字号
/*
// $Id: //open/mondrian/src/main/mondrian/rolap/RolapEvaluator.java#35 $
// 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.olap.fun.FunUtil;
import mondrian.util.Format;
import mondrian.resource.MondrianResource;

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

/**
 * <code>RolapEvaluator</code> evaluates expressions in a dimensional
 * environment.
 *
 * <p>The context contains a member (which may be the default member)
 * for every dimension in the current cube. Certain operations, such as
 * evaluating a calculated member or a tuple, change the current context. The
 * evaluator's {@link #push} method creates a clone of the current evaluator
 * so that you can revert to the original context once the operation has
 * completed.
 *
 * @author jhyde
 * @since 10 August, 2001
 * @version $Id: //open/mondrian/src/main/mondrian/rolap/RolapEvaluator.java#35 $
 */
class RolapEvaluator implements Evaluator {
    private static final Logger LOGGER = Logger.getLogger(RolapEvaluator.class);

    /**
     * Dummy value to represent null results in the expression cache.
     */
    private static final Object nullResult = new Object();

    private final Member[] currentMembers;
    private final Evaluator parent;
    protected CellReader cellReader;
    private final int depth;

    private Member expandingMember;
    private boolean nonEmpty;
    protected final RolapEvaluatorRoot root;

    /**
     * Creates an evaluator.
     */
    protected RolapEvaluator(
            RolapEvaluatorRoot root,
            RolapEvaluator parent,
            CellReader cellReader,
            Member[] currentMembers) {
        this.root = root;
        this.parent = parent;
        this.depth = parent == null ? 0 : parent.depth + 1;
        this.cellReader = cellReader;
        if (currentMembers == null) {
            this.currentMembers = new Member[root.cube.getDimensions().length];
        } else {
            this.currentMembers = currentMembers;
        }
    }

    /**
     * Creates an evaluator with no parent.
     *
     * @param root Shared context between this evaluator and its children
     */
    RolapEvaluator(RolapEvaluatorRoot root) {
        this(root, null, null, null);

        // we expect client to set CellReader

        SchemaReader scr = this.root.connection.getSchemaReader();
        Dimension[] dimensions = this.root.cube.getDimensions();
        for (int i = 0; i < dimensions.length; i++) {
            final Dimension dimension = dimensions[i];
            final int ordinal = dimension.getOrdinal(this.root.cube);
            final Hierarchy hier = dimension.getHierarchy();

            Member member = scr.getHierarchyDefaultMember(hier);

            // If there is no member, we cannot continue.
            if (member == null) {
                throw MondrianResource.instance().InvalidHierarchyCondition.ex(hier.getUniqueName());
            }

            HierarchyUsage[] hierarchyUsages = this.root.cube.getUsages(hier);
            if (hierarchyUsages.length != 0) {
                ((RolapMember) member).makeUniqueName(hierarchyUsages[0]);
            }

            currentMembers[ordinal] = member;
        }
    }

    protected static class RolapEvaluatorRoot {
        final RolapResult result;
        final Map expResultCache = new HashMap();
        final RolapCube cube;
        final RolapConnection connection;
        final SchemaReader schemaReader;

        RolapEvaluatorRoot(RolapResult result) {
            this.result = result;
            this.cube = (RolapCube) result.getQuery().getCube();
            this.connection = (RolapConnection) result.getQuery().getConnection();
            this.schemaReader = cube.getSchemaReader(connection.role);
        }
    }

    protected Logger getLogger() {
        return LOGGER;
    }

    Member[] getCurrentMembers() {
        return this.currentMembers;
    }

    void setCellReader(CellReader cellReader) {
        this.cellReader = cellReader;
    }

    public Cube getCube() {
        return root.cube;
    }

    public Query getQuery() {
        return root.result.getQuery();
    }

    public int getDepth() {
        return depth;
    }

    public Evaluator getParent() {
        return parent;
    }

    public SchemaReader getSchemaReader() {
        return root.schemaReader;
    }

    public Evaluator push(Member[] members) {
        final RolapEvaluator evaluator = _push();
        evaluator.setContext(members);
        return evaluator;
    }

    public Evaluator push(Member member) {
        final RolapEvaluator evaluator = _push();
        evaluator.setContext(member);
        return evaluator;
    }

    public Evaluator push() {
        return _push();
    }

    /**
     * Creates a clone of the current validator.
     */
    protected RolapEvaluator _push() {
        Member[] cloneCurrentMembers = (Member[]) this.currentMembers.clone();
        return new RolapEvaluator(
                root,
                this,
                cellReader,
                cloneCurrentMembers);
    }

    public Evaluator pop() {
        return parent;
    }

    public Object visit(Literal literal) {
        return literal.getValue();
    }

    public Object visit(Parameter parameter) {
        return parameter.getExp().evaluate(this);
    }

    public Object visit(FunCall funCall) {
        FunDef funDef = funCall.getFunDef();
        return funDef.evaluate(this, funCall.getArgs());
    }

    public Object visit(Id id) {
        throw new Error("unsupported");
    }

    public Object visit(OlapElement mdxElement) {
        return mdxElement;
    }

    public Member setContext(Member member) {
        RolapMember m = (RolapMember) member;
        int ordinal = m.getDimension().getOrdinal(root.cube);
        Member previous = currentMembers[ordinal];
        currentMembers[ordinal] = m;
        return previous;
    }

    public void setContext(Member[] members) {
        for (int i = 0; i < members.length; i++) {
            Member member = members[i];

            // more than one usage
            if (member == null) {
                if (getLogger().isDebugEnabled()) {
                    getLogger().debug(
                        "RolapEvaluator.setContext: member == null "
                         + " , count=" + i);
                }
                continue;
            }

            setContext(member);
        }
    }

    public Member getContext(Dimension dimension) {
        return currentMembers[dimension.getOrdinal(root.cube)];
    }

    public Object evaluateCurrent() {
        Member maxSolveMember = getMaxSolveMember();
        if (maxSolveMember != null) {
            // There is at least one calculated member. Expand the first one
            // with the highest solve order.
            RolapMember defaultMember = (RolapMember)
                    maxSolveMember.getHierarchy().getDefaultMember();
            Util.assertTrue(
                    defaultMember != maxSolveMember,
                    "default member must not be calculated");
            RolapEvaluator evaluator = (RolapEvaluator) push(defaultMember);
            evaluator.setExpanding(maxSolveMember);
            //((RolapEvaluator) evaluator).cellReader = new CachingCellReader(cellReader);
            return maxSolveMember.getExpression().evaluateScalar(evaluator);
        }
        return cellReader.get(this);
    }

    /**
     * Returns the member in the current context which is (a) calculated, and
     * (b) has the highest solve order; returns null if there are no calculated
     * members.
     */
    private Member getMaxSolveMember() {

⌨️ 快捷键说明

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