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) 2006-2011 Pentaho
008// All Rights Reserved.
009*/
010package mondrian.olap.fun;
011
012import mondrian.calc.*;
013import mondrian.calc.impl.AbstractMemberCalc;
014import mondrian.mdx.ResolvedFunCall;
015import mondrian.olap.*;
016import mondrian.rolap.RolapHierarchy;
017
018import java.util.Map;
019
020/**
021 * Definition of the <code>&lt;Hierarchy&gt;.CurrentMember</code> MDX
022 * builtin function.
023 *
024 * @author jhyde
025 * @since Mar 23, 2006
026 */
027public class HierarchyCurrentMemberFunDef extends FunDefBase {
028    static final HierarchyCurrentMemberFunDef instance =
029            new HierarchyCurrentMemberFunDef();
030
031    private HierarchyCurrentMemberFunDef() {
032        super(
033            "CurrentMember",
034            "Returns the current member along a hierarchy during an iteration.",
035            "pmh");
036    }
037
038    public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
039        final HierarchyCalc hierarchyCalc =
040            compiler.compileHierarchy(call.getArg(0));
041        final Hierarchy hierarchy = hierarchyCalc.getType().getHierarchy();
042        if (hierarchy != null) {
043            return new FixedCalcImpl(call, hierarchy);
044        } else {
045            return new CalcImpl(call, hierarchyCalc);
046        }
047    }
048
049    /**
050     * Compiled implementation of the Hierarchy.CurrentMember function that
051     * evaluates the hierarchy expression first.
052     */
053    public static class CalcImpl extends AbstractMemberCalc {
054        private final HierarchyCalc hierarchyCalc;
055
056        public CalcImpl(Exp exp, HierarchyCalc hierarchyCalc) {
057            super(exp, new Calc[] {hierarchyCalc});
058            this.hierarchyCalc = hierarchyCalc;
059        }
060
061        protected String getName() {
062            return "CurrentMember";
063        }
064
065        public Member evaluateMember(Evaluator evaluator) {
066            Hierarchy hierarchy = hierarchyCalc.evaluateHierarchy(evaluator);
067            return evaluator.getContext(hierarchy);
068        }
069
070        public boolean dependsOn(Hierarchy hierarchy) {
071            return hierarchyCalc.getType().usesHierarchy(hierarchy, false);
072        }
073    }
074
075    /**
076     * Compiled implementation of the Hierarchy.CurrentMember function that
077     * uses a fixed hierarchy.
078     */
079    public static class FixedCalcImpl extends AbstractMemberCalc {
080        // getContext works faster if we give RolapHierarchy rather than
081        // Hierarchy
082        private final RolapHierarchy hierarchy;
083
084        public FixedCalcImpl(Exp exp, Hierarchy hierarchy) {
085            super(exp, new Calc[] {});
086            assert hierarchy != null;
087            this.hierarchy = (RolapHierarchy) hierarchy;
088        }
089
090        protected String getName() {
091            return "CurrentMemberFixed";
092        }
093
094        public Member evaluateMember(Evaluator evaluator) {
095            return evaluator.getContext(hierarchy);
096        }
097
098        public boolean dependsOn(Hierarchy hierarchy) {
099            return this.hierarchy == hierarchy;
100        }
101
102        public void collectArguments(Map<String, Object> arguments) {
103            arguments.put("hierarchy", hierarchy);
104            super.collectArguments(arguments);
105        }
106    }
107}
108
109// End HierarchyCurrentMemberFunDef.java