001/*
002// This software is subject to the terms of the Eclipse Public License v1.0
003// Agreement, available at the following URL:
004// http://www.eclipse.org/legal/epl-v10.html.
005// You must accept the terms of that agreement to use this software.
006//
007// Copyright (C) 2009-2011 Pentaho
008// All Rights Reserved.
009*/
010package mondrian.rolap;
011
012import mondrian.calc.Calc;
013import mondrian.mdx.ResolvedFunCall;
014import mondrian.olap.Exp;
015import mondrian.olap.fun.AggregateFunDef;
016
017/**
018 * Implementation of {@link mondrian.rolap.RolapCalculation}
019 * that wraps a {@link RolapMember calculated member}.
020 *
021 * @author jhyde
022 * @since May 15, 2009
023 */
024class RolapMemberCalculation implements RolapCalculation {
025    private final RolapMember member;
026    private final int solveOrder;
027    private Boolean containsAggregateFunction;
028
029    /**
030     * Creates a RolapMemberCalculation.
031     *
032     * @param member Calculated member
033     */
034    public RolapMemberCalculation(RolapMember member) {
035        this.member = member;
036        // compute and solve order: it is used frequently
037        solveOrder = this.member.getSolveOrder();
038        assert member.isEvaluated();
039    }
040
041    public int hashCode() {
042        return member.hashCode();
043    }
044
045    public boolean equals(Object obj) {
046        return obj instanceof RolapMemberCalculation
047            && member == ((RolapMemberCalculation) obj).member;
048    }
049
050    public void setContextIn(RolapEvaluator evaluator) {
051        final RolapMember defaultMember =
052            evaluator.root.defaultMembers[getHierarchyOrdinal()];
053
054        // This method does not need to call RolapEvaluator.removeCalcMember.
055        // That happens implicitly in setContext.
056        evaluator.setContext(defaultMember);
057        evaluator.setExpanding(member);
058    }
059
060    public int getSolveOrder() {
061        return solveOrder;
062    }
063
064    public int getHierarchyOrdinal() {
065        return member.getHierarchy().getOrdinalInCube();
066    }
067
068    public Calc getCompiledExpression(RolapEvaluatorRoot root) {
069        final Exp exp = member.getExpression();
070        return root.getCompiled(exp, true, null);
071    }
072
073    public boolean isCalculatedInQuery() {
074        return member.isCalculatedInQuery();
075    }
076
077    public boolean containsAggregateFunction() {
078        // searching for agg functions is expensive, so cache result
079        if (containsAggregateFunction == null) {
080            containsAggregateFunction =
081                foundAggregateFunction(member.getExpression());
082        }
083        return containsAggregateFunction;
084    }
085
086    /**
087     * Returns whether an expression contains a call to an aggregate
088     * function such as "Aggregate" or "Sum".
089     *
090     * @param exp Expression
091     * @return Whether expression contains a call to an aggregate function.
092     */
093    private static boolean foundAggregateFunction(Exp exp) {
094        if (exp instanceof ResolvedFunCall) {
095            ResolvedFunCall resolvedFunCall = (ResolvedFunCall) exp;
096            if (resolvedFunCall.getFunDef() instanceof AggregateFunDef) {
097                return true;
098            } else {
099                for (Exp argExp : resolvedFunCall.getArgs()) {
100                    if (foundAggregateFunction(argExp)) {
101                        return true;
102                    }
103                }
104            }
105        }
106        return false;
107    }
108}
109
110// End RolapMemberCalculation.java