001    /*
002    // $Id: //open/mondrian/src/main/mondrian/calc/Calc.java#7 $
003    // This software is subject to the terms of the Common Public License
004    // Agreement, available at the following URL:
005    // http://www.opensource.org/licenses/cpl.html.
006    // Copyright (C) 2006-2007 Julian Hyde
007    // All Rights Reserved.
008    // You must accept the terms of that agreement to use this software.
009    */
010    package mondrian.calc;
011    
012    import mondrian.olap.Evaluator;
013    import mondrian.olap.Dimension;
014    import mondrian.olap.type.Type;
015    
016    /**
017     * <code>Calc</code> is the base class for all calculable expressions.
018     *
019     * <h3>Logical and physical expression languages</h3>
020     *
021     * Mondrian has two expression languages:<ul>
022     * <li>The logical language of parsed MDX fragments ({@link mondrian.olap.Exp}).
023     * <li>The phyiscal language of compiled expressions ({@link Calc}).
024     * </ul></p>
025     *
026     * The two languages allow us to separate logical (how an
027     * MDX expression was specified) from physical (how it is to be evaluated).
028     * The physical language is more strongly typed, and certain constructs which
029     * are implicit in the logical language (such as the addition of calls
030     * to the <code>&lt;Member&gt;.CurrentMember</code> function) are made
031     * explicit in the physical language.<p/>
032     *
033     * <h3>Compilation</h3>
034     *
035     * Expressions are generally created from using an expression compiler
036     * ({@link ExpCompiler}). There are often more than one evaluation strategy
037     * for a given expression, and compilation process gives us an opportunity to
038     * choose the optimal one.<p/>
039     *
040     * <h3>Implementing expressions</h3>
041     *
042     * The <code>Calc</code> interface has sub-interfaces for various types:
043     * {@link IntegerCalc},
044     * {@link BooleanCalc},
045     * {@link DoubleCalc},
046     * {@link StringCalc} are scalar expressions;
047     * {@link MemberCalc},
048     * {@link LevelCalc},
049     * {@link HierarchyCalc},
050     * {@link DimensionCalc} yield elements of the OLAP model.<p/>
051     *
052     * Each of these sub-interfaces has an abstract implementation:
053     * {@link mondrian.calc.impl.AbstractIntegerCalc},
054     * {@link mondrian.calc.impl.AbstractBooleanCalc},
055     * {@link mondrian.calc.impl.AbstractDoubleCalc},
056     * {@link mondrian.calc.impl.AbstractStringCalc},
057     * {@link mondrian.calc.impl.AbstractMemberCalc},
058     * {@link mondrian.calc.impl.AbstractLevelCalc},
059     * {@link mondrian.calc.impl.AbstractHierarchyCalc},
060     * {@link mondrian.calc.impl.AbstractDimensionCalc}.<p/>
061     *
062     * {@link mondrian.calc.impl.GenericCalc} is an adapter which implements all of these interfaces
063     * and will try to convert any given result to the correct type. Use it
064     * sparingly: if you know the expected result type, it is better to write a
065     * class which implements a specific <code><em>Type</em>Calc</code> interface.
066     *
067     * @author jhyde
068     * @since Sep 26, 2005
069     * @version $Id: //open/mondrian/src/main/mondrian/calc/Calc.java#7 $
070     */
071    public interface Calc {
072        /**
073         * Evaluates this expression.
074         *
075         * @param evaluator Provides dimensional context in which to evaluate
076         *                  this expression
077         * @return Result of expression evaluation
078         */
079        Object evaluate(Evaluator evaluator);
080    
081        /**
082         * Returns whether this expression depends upon a given dimension.
083         *
084         * <p>If it does not depend on the dimension, then re-evaluating the
085         * expression with a different member of this context must produce the
086         * same answer.<p/>
087         *
088         * Some examples:<ul>
089         *
090         * <li>The expression
091         * <blockquote><code>[Measures].[Unit Sales]</code></blockquote>
092         * depends on all dimensions except <code>[Measures]</code>.
093         *
094         * <li>The boolean expression
095         * <blockquote><code>([Measures].[Unit Sales],
096         * [Time].[1997]) &gt; 1000</code></blockquote>
097         * depends on all dimensions except [Measures] and [Time].
098         *
099         * <li>The list expression
100         * <blockquote><code>Filter([Store].[USA].Children,
101         * [Measures].[Unit Sales] &lt; 50)</code></pre></blockquote>
102         * depends upon all dimensions <em>except</em> [Store] and [Measures].
103         * How so? Normally the scalar expression would depend upon all dimensions
104         * except [Measures], but the <code>Filter</code> function sets the [Store]
105         * context before evaluating the scalar expression, so it is not inherited
106         * from the surrounding context.
107         *
108         * </ul><p/>
109         *
110         * @param dimension Dimension
111         * @return Whether this expression's result depends upon the current member
112         *   of the dimension
113         */
114        boolean dependsOn(Dimension dimension);
115    
116        /**
117         * Returns the type of this expression.
118         */
119        Type getType();
120    
121        /**
122         * Prints this expression, by accepting a visiting {@link CalcWriter}.
123         *
124         * @param calcWriter Writer
125         */
126        void accept(CalcWriter calcWriter);
127    
128        /**
129         * Returns style in which the result of evaluating this expression is
130         * returned.
131         *
132         * <p>One application of this method is for the compiler to figure out
133         * whether the compiled expression is returning a mutable list. If a mutable
134         * list is required, the compiler can create a mutable copy.
135         *
136         * @see ExpCompiler#compileList(mondrian.olap.Exp, boolean)
137         */
138        ResultStyle getResultStyle();
139    }
140    
141    // End Calc.java