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.mdx;
011
012import mondrian.calc.*;
013import mondrian.calc.impl.AbstractIterCalc;
014import mondrian.olap.*;
015import mondrian.olap.type.Type;
016
017import java.util.List;
018
019/**
020 * Usage of a {@link mondrian.olap.NamedSet} in an MDX expression.
021 *
022 * @author jhyde
023 * @since Sep 26, 2005
024 */
025public class NamedSetExpr extends ExpBase implements Exp {
026    private final NamedSet namedSet;
027
028    /**
029     * Creates a usage of a named set.
030     *
031     * @param namedSet namedSet
032     * @pre NamedSet != null
033     */
034    public NamedSetExpr(NamedSet namedSet) {
035        Util.assertPrecondition(namedSet != null, "namedSet != null");
036        this.namedSet = namedSet;
037    }
038
039    /**
040     * Returns the named set.
041     *
042     * @post return != null
043     */
044    public NamedSet getNamedSet() {
045        return namedSet;
046    }
047
048    public String toString() {
049        return namedSet.getUniqueName();
050    }
051
052    public NamedSetExpr clone() {
053        return new NamedSetExpr(namedSet);
054    }
055
056    public int getCategory() {
057        return Category.Set;
058    }
059
060    public Exp accept(Validator validator) {
061        // A set is sometimes used in more than one cube. So, clone the
062        // expression and re-validate every time it is used.
063        //
064        // But keep the expression wrapped in a NamedSet, so that the
065        // expression is evaluated once per query. (We don't want the
066        // expression to be evaluated context-sensitive.)
067        NamedSet namedSet2 = namedSet.validate(validator);
068        if (namedSet2 == namedSet) {
069            return this;
070        }
071        return new NamedSetExpr(namedSet2);
072    }
073
074    public Calc accept(ExpCompiler compiler) {
075        // This is a deliberate breach of the usual rules for interpreting
076        // acceptable result styles. Usually the caller gets to call the shots:
077        // the callee iterates over the acceptable styles and implements in the
078        // first style it is able to. But in this case, we return iterable if
079        // the caller can handle it, even if it isn't the caller's first choice.
080        // This is because the .current and .currentOrdinal functions only
081        // work correctly on iterators.
082        final List<ResultStyle> styleList =
083            compiler.getAcceptableResultStyles();
084        if (!styleList.contains(ResultStyle.ITERABLE)
085            && !styleList.contains(ResultStyle.ANY))
086        {
087            return null;
088        }
089
090        return new AbstractIterCalc(
091            this,
092            new Calc[]{/* todo: compile namedSet.getExp() */})
093        {
094            public TupleIterable evaluateIterable(
095                Evaluator evaluator)
096            {
097                final Evaluator.NamedSetEvaluator eval = getEval(evaluator);
098                return eval.evaluateTupleIterable(evaluator);
099            }
100
101            public boolean dependsOn(Hierarchy hierarchy) {
102                // Given that a named set is never re-evaluated within the
103                // scope of a query, effectively it's independent of all
104                // dimensions.
105                return false;
106            }
107        };
108    }
109
110    public Evaluator.NamedSetEvaluator getEval(Evaluator evaluator) {
111        return evaluator.getNamedSetEvaluator(namedSet, true);
112    }
113
114    public Object accept(MdxVisitor visitor) {
115        Object o = visitor.visit(this);
116        if (visitor.shouldVisitChildren()) {
117            namedSet.getExp().accept(visitor);
118        }
119        return o;
120    }
121
122    public Type getType() {
123        return namedSet.getType();
124    }
125
126}
127
128// End NamedSetExpr.java