KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > calc > impl > AbstractExpCompiler


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/calc/impl/AbstractExpCompiler.java#16 $
3 // This software is subject to the terms of the Common Public License
4 // Agreement, available at the following URL:
5 // http://www.opensource.org/licenses/cpl.html.
6 // Copyright (C) 2006-2007 Julian Hyde
7 // All Rights Reserved.
8 // You must accept the terms of that agreement to use this software.
9 */

10 package mondrian.calc.impl;
11
12 import mondrian.olap.*;
13 import mondrian.olap.fun.*;
14 import mondrian.olap.type.*;
15 import mondrian.olap.type.DimensionType;
16 import mondrian.olap.type.LevelType;
17 import mondrian.resource.MondrianResource;
18 import mondrian.rolap.RolapMember;
19 import mondrian.calc.*;
20
21 import java.util.HashMap JavaDoc;
22 import java.util.Map JavaDoc;
23
24 /**
25  * Abstract implementation of the {@link mondrian.calc.ExpCompiler} interface.
26  *
27  * @author jhyde
28  * @version $Id: //open/mondrian/src/main/mondrian/calc/impl/AbstractExpCompiler.java#16 $
29  * @since Sep 29, 2005
30  */

31 public class AbstractExpCompiler implements ExpCompiler {
32     private final Evaluator evaluator;
33     private final Validator validator;
34     private final Map JavaDoc<Parameter, ParameterSlotImpl> parameterSlots =
35         new HashMap JavaDoc<Parameter, ParameterSlotImpl>();
36     private ResultStyle[] resultStyles;
37
38     public AbstractExpCompiler(Evaluator evaluator, Validator validator) {
39         this(evaluator, validator, ANY_RESULT_STYLE_ARRAY);
40     }
41     public AbstractExpCompiler(Evaluator evaluator, Validator validator,
42             ResultStyle[] resultStyles) {
43         this.evaluator = evaluator;
44         this.validator = validator;
45         this.resultStyles = (resultStyles == null)
46             ? ANY_RESULT_STYLE_ARRAY : resultStyles;
47     }
48
49     public Evaluator getEvaluator() {
50         return evaluator;
51     }
52
53     public Validator getValidator() {
54         return validator;
55     }
56
57     /**
58      * Uses the current ResultStyle to compile the expression.
59      *
60      * @param exp
61      * @return
62      */

63     public Calc compile(Exp exp) {
64         return exp.accept(this);
65     }
66
67     /**
68      * Uses a new ResultStyle to compile the expression.
69      *
70      * @param exp
71      * @param preferredResultTypes
72      * @return
73      */

74     public Calc compile(Exp exp, ResultStyle[] preferredResultTypes) {
75         assert preferredResultTypes != null;
76         if (Util.PreJdk15) {
77             // Copy and replace ITERABLE
78
// A number of functions declare that they can accept
79
// ITERABLEs so here is where that those are
80
// converted to innocent, for jdk1.4, LISTs
81
ResultStyle[] tmp = new ResultStyle[preferredResultTypes.length];
82             for (int i = 0; i < preferredResultTypes.length; i++) {
83                 tmp[i] = (preferredResultTypes[i] == ResultStyle.ITERABLE)
84                     ? ResultStyle.LIST : preferredResultTypes[i];
85             }
86             preferredResultTypes = tmp;
87         }
88         ResultStyle[] save = this.resultStyles;
89         try {
90             this.resultStyles = preferredResultTypes;
91             return compile(exp);
92         } finally {
93             this.resultStyles = save;
94         }
95     }
96
97     public MemberCalc compileMember(Exp exp) {
98         final Type type = exp.getType();
99         if (type instanceof DimensionType) {
100             final DimensionCalc dimensionCalc = compileDimension(exp);
101             return new DimensionCurrentMemberFunDef.CalcImpl(
102                     new DummyExp(TypeUtil.toMemberType(type)), dimensionCalc);
103         } else if (type instanceof HierarchyType) {
104             final HierarchyCalc hierarchyCalc = compileHierarchy(exp);
105             return new HierarchyCurrentMemberFunDef.CalcImpl(
106                     new DummyExp(TypeUtil.toMemberType(type)), hierarchyCalc);
107         } else if (type instanceof NullType) {
108             throw MondrianResource.instance().NullNotSupported.ex();
109         }
110         assert type instanceof MemberType;
111         return (MemberCalc) compile(exp);
112     }
113
114     public LevelCalc compileLevel(Exp exp) {
115         final Type type = exp.getType();
116         if (type instanceof MemberType) {
117             // <Member> --> <Member>.Level
118
final MemberCalc memberCalc = compileMember(exp);
119             return new MemberLevelFunDef.CalcImpl(
120                     new DummyExp(LevelType.forType(type)),
121                     memberCalc);
122         }
123         assert type instanceof LevelType;
124         return (LevelCalc) compile(exp);
125     }
126
127     public DimensionCalc compileDimension(Exp exp) {
128         final Type type = exp.getType();
129         if (type instanceof HierarchyType) {
130             final HierarchyCalc hierarchyCalc = compileHierarchy(exp);
131             return new HierarchyDimensionFunDef.CalcImpl(
132                     exp, hierarchyCalc);
133         }
134         assert type instanceof DimensionType : type;
135         return (DimensionCalc) compile(exp);
136     }
137
138     public HierarchyCalc compileHierarchy(Exp exp) {
139         final Type type = exp.getType();
140         if (type instanceof DimensionType ||
141                 type instanceof MemberType) {
142             // <Dimension> --> <Dimension>.CurrentMember.Hierarchy
143
final MemberCalc memberCalc = compileMember(exp);
144             return new MemberHierarchyFunDef.CalcImpl(
145                     new DummyExp(HierarchyType.forType(type)),
146                     memberCalc);
147         }
148         if (type instanceof LevelType) {
149             // <Level> --> <Level>.Hierarchy
150
final LevelCalc levelCalc = compileLevel(exp);
151             return new LevelHierarchyFunDef.CalcImpl(
152                     new DummyExp(HierarchyType.forType(type)),
153                     levelCalc);
154         }
155         assert type instanceof HierarchyType;
156         return (HierarchyCalc) compile(exp);
157     }
158
159     public IntegerCalc compileInteger(Exp exp) {
160         final Calc calc = compileScalar(exp, false);
161         if (calc instanceof IntegerCalc) {
162             return (IntegerCalc) calc;
163         } else if (calc instanceof DoubleCalc) {
164             final DoubleCalc doubleCalc = (DoubleCalc) calc;
165             return new AbstractIntegerCalc(exp, new Calc[] {doubleCalc}) {
166                 public int evaluateInteger(Evaluator evaluator) {
167                     return (int) doubleCalc.evaluateDouble(evaluator);
168                 }
169             };
170         } else {
171             return (IntegerCalc) calc;
172         }
173     }
174
175     public StringCalc compileString(Exp exp) {
176         return (StringCalc) compile(exp);
177     }
178
179     public ListCalc compileList(Exp exp) {
180         return compileList(exp, false);
181     }
182
183     public ListCalc compileList(Exp exp, boolean mutable) {
184         ListCalc listCalc = (mutable)
185             ? (ListCalc) compile(exp, MUTABLE_LIST_RESULT_STYLE_ARRAY)
186             : (ListCalc) compile(exp, LIST_RESULT_STYLE_ARRAY);
187         return listCalc;
188     }
189
190     public IterCalc compileIter(Exp exp) {
191         return (IterCalc) compile(exp, ITERABLE_RESULT_STYLE_ARRAY);
192     }
193
194     public BooleanCalc compileBoolean(Exp exp) {
195         return (BooleanCalc) compileScalar(exp, false);
196     }
197
198     public DoubleCalc compileDouble(Exp exp) {
199         return (DoubleCalc) compileScalar(exp, false);
200     }
201
202     public TupleCalc compileTuple(Exp exp) {
203         return (TupleCalc) compile(exp);
204     }
205
206     public Calc compileScalar(Exp exp, boolean convert) {
207         final Type type = exp.getType();
208         if (type instanceof MemberType) {
209             MemberType memberType = (MemberType) type;
210             MemberCalc calc = compileMember(exp);
211             return new MemberValueCalc(
212                     new DummyExp(memberType.getValueType()),
213                     new MemberCalc[] {calc});
214         } else if (type instanceof DimensionType) {
215             final DimensionCalc dimensionCalc = compileDimension(exp);
216             MemberType memberType = MemberType.forType(type);
217             final MemberCalc dimensionCurrentMemberCalc =
218                     new DimensionCurrentMemberFunDef.CalcImpl(
219                             new DummyExp(memberType),
220                             dimensionCalc);
221             return new MemberValueCalc(
222                     new DummyExp(memberType.getValueType()),
223                     new MemberCalc[] {dimensionCurrentMemberCalc});
224         } else if (type instanceof HierarchyType) {
225             HierarchyType hierarchyType = (HierarchyType) type;
226             MemberType memberType =
227                     MemberType.forHierarchy(hierarchyType.getHierarchy());
228             final HierarchyCalc hierarchyCalc = compileHierarchy(exp);
229             final MemberCalc hierarchyCurrentMemberCalc =
230                     new HierarchyCurrentMemberFunDef.CalcImpl(
231                             new DummyExp(memberType), hierarchyCalc);
232             return new MemberValueCalc(
233                     new DummyExp(memberType.getValueType()),
234                     new MemberCalc[] {hierarchyCurrentMemberCalc});
235         } else if (type instanceof TupleType) {
236             TupleType tupleType = (TupleType) type;
237             TupleCalc tupleCalc = compileTuple(exp);
238             final TupleValueCalc scalarCalc = new TupleValueCalc(
239                     new DummyExp(tupleType.getValueType()), tupleCalc);
240             return scalarCalc.optimize();
241         } else if (type instanceof ScalarType) {
242             if (convert) {
243                 if (type instanceof BooleanType) {
244                     return compileBoolean(exp);
245                 } else if (type instanceof NumericType) {
246                     return compileDouble(exp);
247                 } else if (type instanceof StringType) {
248                     return compileString(exp);
249                 } else {
250                     return compile(exp);
251                 }
252             } else {
253                 return compile(exp);
254             }
255         } else {
256             return compile(exp);
257         }
258     }
259
260     public ParameterSlot registerParameter(Parameter parameter) {
261         ParameterSlot slot = parameterSlots.get(parameter);
262         if (slot != null) {
263             return slot;
264         }
265         int index = parameterSlots.size();
266         ParameterSlotImpl slot2 = new ParameterSlotImpl(parameter, index);
267         parameterSlots.put(parameter, slot2);
268         slot2.value = parameter.getValue();
269
270         // Compile the expression only AFTER the parameter has been
271
// registered with a slot. Otherwise a cycle is possible.
272
Calc calc = parameter.getDefaultExp().accept(this);
273         slot2.setDefaultValueCalc(calc);
274         return slot2;
275     }
276
277     public ResultStyle[] getAcceptableResultStyles() {
278         return resultStyles;
279     }
280
281     /**
282      * Implementation of {@link ParameterSlot}.
283      */

284     private static class ParameterSlotImpl implements ParameterSlot {
285         private final Parameter parameter;
286         private final int index;
287         private Calc defaultValueCalc;
288         private Object JavaDoc value;
289         private Object JavaDoc cachedDefaultValue;
290
291         public ParameterSlotImpl(
292             Parameter parameter, int index)
293         {
294             this.parameter = parameter;
295             this.index = index;
296         }
297
298         public int getIndex() {
299             return index;
300         }
301
302         public Calc getDefaultValueCalc() {
303             return defaultValueCalc;
304         }
305
306         public Parameter getParameter() {
307             return parameter;
308         }
309
310         private void setDefaultValueCalc(Calc calc) {
311             this.defaultValueCalc = calc;
312         }
313
314         public void setParameterValue(Object JavaDoc value) {
315             this.value = value;
316         }
317
318         public Object JavaDoc getParameterValue() {
319             return value;
320         }
321
322         public void setCachedDefaultValue(Object JavaDoc value) {
323             this.cachedDefaultValue = value;
324         }
325
326         public Object JavaDoc getCachedDefaultValue() {
327             return cachedDefaultValue;
328         }
329     }
330 }
331
332 // End AbtractExpCompiler.java
333
Popular Tags