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) 2005-2005 Julian Hyde
008// Copyright (C) 2005-2009 Pentaho
009// All Rights Reserved.
010*/
011package mondrian.olap;
012
013import mondrian.calc.*;
014import mondrian.calc.impl.BetterExpCompiler;
015
016import java.util.ArrayList;
017import java.util.List;
018
019/**
020 * Holds information necessary to add an expression to the expression result
021 * cache (see {@link Evaluator#getCachedResult(ExpCacheDescriptor)}).
022 *
023 * @author jhyde
024 * @since Aug 16, 2005
025 */
026public class ExpCacheDescriptor {
027    private final Exp exp;
028    private int[] dependentHierarchyOrdinals;
029    private final Calc calc;
030
031    /**
032     * Creates a descriptor with a given compiled expression.
033     *
034     * @param exp Expression
035     * @param calc Compiled expression
036     * @param evaluator Evaluator
037     */
038    public ExpCacheDescriptor(Exp exp, Calc calc, Evaluator evaluator) {
039        this.calc = calc;
040        this.exp = exp;
041        computeDepends(calc, evaluator);
042    }
043
044    /**
045     * Creates a descriptor.
046     *
047     * @param exp Expression
048     * @param evaluator Evaluator
049     */
050    public ExpCacheDescriptor(Exp exp, Evaluator evaluator) {
051        this(exp, new BetterExpCompiler(evaluator, null));
052    }
053
054    /**
055     * Creates a descriptor.
056     *
057     * @param exp Expression
058     * @param compiler Compiler
059     */
060    public ExpCacheDescriptor(Exp exp, ExpCompiler compiler) {
061        this.exp = exp;
062
063        // Compile expression.
064        Calc calc = compiler.compile(exp);
065        if (calc == null) {
066            // now allow conversions
067            calc = compiler.compileAs(exp, null, ResultStyle.ANY_ONLY);
068        }
069        this.calc = calc;
070
071        // Compute list of dependent dimensions.
072        computeDepends(calc, compiler.getEvaluator());
073    }
074
075    private void computeDepends(Calc calc, Evaluator evaluator) {
076        final List<Integer> ordinalList = new ArrayList<Integer>();
077        final Member[] members = evaluator.getMembers();
078        for (int i = 0; i < members.length; i++) {
079            Hierarchy hierarchy = members[i].getHierarchy();
080            if (calc.dependsOn(hierarchy)) {
081                ordinalList.add(i);
082            }
083        }
084        dependentHierarchyOrdinals = new int[ordinalList.size()];
085        for (int i = 0; i < dependentHierarchyOrdinals.length; i++) {
086            dependentHierarchyOrdinals[i] = ordinalList.get(i);
087        }
088    }
089
090    public Exp getExp() {
091        return exp;
092    }
093
094    public Calc getCalc() {
095        return calc;
096    }
097
098    public Object evaluate(Evaluator evaluator) {
099        return calc.evaluate(evaluator);
100    }
101
102    /**
103     * Returns the ordinals of the hierarchies which this expression is
104     * dependent upon. When the cache descriptor is used to generate a cache
105     * key, the key will consist of a member from each of these hierarchies.
106     */
107    public int[] getDependentHierarchyOrdinals() {
108        return dependentHierarchyOrdinals;
109    }
110
111}
112
113// End ExpCacheDescriptor.java