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><Member>.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]) > 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] < 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