Package mondrian.calc.impl

Source Code of mondrian.calc.impl.AbstractCalc

/*
// $Id: //open/mondrian-release/3.2/src/main/mondrian/calc/impl/AbstractCalc.java#1 $
// This software is subject to the terms of the Eclipse Public License v1.0
// Agreement, available at the following URL:
// http://www.eclipse.org/legal/epl-v10.html.
// Copyright (C) 2006-2009 Julian Hyde
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
*/
package mondrian.calc.impl;

import mondrian.olap.*;
import mondrian.olap.type.Type;
import mondrian.calc.Calc;
import mondrian.calc.CalcWriter;
import mondrian.calc.ResultStyle;
import mondrian.mdx.ResolvedFunCall;
import mondrian.rolap.RolapEvaluator;
import mondrian.rolap.RolapHierarchy;

import java.io.PrintWriter;
import java.util.List;
import java.util.Collections;

/**
* Abstract implementation of the {@link mondrian.calc.Calc} interface.
*
* @author jhyde
* @version $Id: //open/mondrian-release/3.2/src/main/mondrian/calc/impl/AbstractCalc.java#1 $
* @since Sep 27, 2005
*/
public abstract class AbstractCalc implements Calc {
    private final Calc[] calcs;
    protected final Type type;
    protected final Exp exp;

    /**
     * Creates an AbstractCalc.
     *
     * @param exp Source expression
     * @param calcs Child compiled expressions
     */
    protected AbstractCalc(Exp exp, Calc[] calcs) {
        assert exp != null;
        this.exp = exp;
        this.calcs = calcs;
        this.type = exp.getType();
    }

    public Type getType() {
        return type;
    }

    public void accept(CalcWriter calcWriter) {
        final PrintWriter pw = calcWriter.getWriter();
        String name = getName();
        pw.print(name);
        final Calc[] calcs = getCalcs();
        final List<Object> argumentList = getArguments();
        if (calcs.length > 0 || !argumentList.isEmpty()) {
            pw.print("(");
            int k = 0;
            for (Calc calc : calcs) {
                if (k++ > 0) {
                    pw.print(", ");
                }
                calc.accept(calcWriter);
            }
            for (Object o : argumentList) {
                if (k++ > 0) {
                    pw.print(", ");
                }
                pw.print(o);
            }
            pw.print(")");
        }
    }

    /**
     * Returns the name of this expression type, used when serializing an
     * expression to a string.
     *
     * <p>The default implementation tries to extract a name from a function
     * call, if any, then prints the last part of the class name.
     */
    protected String getName() {
        String name;
        if (exp instanceof ResolvedFunCall) {
            ResolvedFunCall funCall = (ResolvedFunCall) exp;
            name = funCall.getFunDef().getName();
        } else {
            name = getClass().getName();
            int dot = name.lastIndexOf('.');
            int dollar = name.lastIndexOf('$');
            int dotDollar = Math.max(dot, dollar);
            if (dotDollar >= 0) {
                name = name.substring(dotDollar + 1);
            }
        }
        return name;
    }

    /**
     * Returns this expression's child expressions.
     */
    public Calc[] getCalcs() {
        return calcs;
    }

    public boolean dependsOn(Hierarchy hierarchy) {
        return anyDepends(getCalcs(), hierarchy);
    }

    /**
     * Returns true if one of the calcs depends on the given dimension.
     */
    public static boolean anyDepends(Calc[] calcs, Hierarchy hierarchy) {
        for (Calc calc : calcs) {
            if (calc != null && calc.dependsOn(hierarchy)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns true if calc[0] depends on dimension,
     * else false if calc[0] returns dimension,
     * else true if any of the other calcs depend on dimension.
     *
     * <p>Typical application: <code>Aggregate({Set}, {Value Expression})</code>
     * depends upon everything {Value Expression} depends upon, except the
     * dimensions of {Set}.
     */
    public static boolean anyDependsButFirst(
        Calc[] calcs, Hierarchy hierarchy)
    {
        if (calcs.length == 0) {
            return false;
        }
        if (calcs[0].dependsOn(hierarchy)) {
            return true;
        }
        if (calcs[0].getType().usesHierarchy(hierarchy, true)) {
            return false;
        }
        for (int i = 1; i < calcs.length; i++) {
            Calc calc = calcs[i];
            if (calc != null && calc.dependsOn(hierarchy)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Returns true if any of the calcs depend on dimension,
     * else false if any of the calcs return dimension,
     * else true.
     */
    public static boolean butDepends(
        Calc[] calcs, Hierarchy hierarchy)
    {
        boolean result = true;
        for (Calc calc : calcs) {
            if (calc != null) {
                if (calc.dependsOn(hierarchy)) {
                    return true;
                }
                if (calc.getType().usesHierarchy(hierarchy, true)) {
                    result = false;
                }
            }
        }
        return result;
    }

    /**
     * Returns any other arguments to this calc.
     * The default implementation returns the empty list.
     */
    public List<Object> getArguments() {
        return Collections.emptyList();
    }

    /**
     * Returns a simplified evalator whose context is the same for every
     * dimension which an expression depends on, and the default member for
     * every dimension which it does not depend on.
     *
     * <p>The default member is often the 'all' member, so this evaluator is
     * usually the most efficient context in which to evaluate the expression.
     *
     * @param calc
     * @param evaluator
     */
    public static Evaluator simplifyEvaluator(Calc calc, Evaluator evaluator) {
        if (evaluator.isNonEmpty()) {
            // If NON EMPTY is present, we cannot simplify the context, because
            // we have to assume that the expression depends on everything.
            // TODO: Bug 1456418: Convert 'NON EMPTY Crossjoin' to
            // 'NonEmptyCrossJoin'.
            return evaluator;
        }
        int changeCount = 0;
        Evaluator ev = evaluator;
        final List<RolapHierarchy> hierarchies =
            ((RolapEvaluator) evaluator).getCube().getHierarchies();
        for (RolapHierarchy hierarchy : hierarchies) {
            final Member member = ev.getContext(hierarchy);
            if (member.isAll()) {
                continue;
            }
            if (calc.dependsOn(hierarchy)) {
                continue;
            }
            final Member unconstrainedMember =
                member.getHierarchy().getDefaultMember();
            if (member == unconstrainedMember) {
                // This is a hierarchy without an 'all' member, and the context
                // is already the default member.
                continue;
            }
            if (changeCount++ == 0) {
                ev = evaluator.push(unconstrainedMember);
            } else {
                ev.setContext(unconstrainedMember);
            }
        }
        return ev;
    }

    public ResultStyle getResultStyle() {
        return ResultStyle.VALUE;
    }
}

// End AbstractCalc.java
TOP

Related Classes of mondrian.calc.impl.AbstractCalc

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.