KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > calc > ExpCompiler


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/calc/ExpCompiler.java#11 $
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;
11
12 import org.eigenbase.util.property.StringProperty;
13 import mondrian.olap.*;
14 import mondrian.util.ObjectFactory;
15 import mondrian.util.CreationException;
16
17 /**
18  * Mediates the compilation of an expression ({@link mondrian.olap.Exp})
19  * into a compiled expression ({@link Calc}).
20  *
21  * @author jhyde
22  * @version $Id: //open/mondrian/src/main/mondrian/calc/ExpCompiler.java#11 $
23  * @since Sep 28, 2005
24  */

25 public interface ExpCompiler {
26     /**
27      * Returns the evaluator to be used for evaluating expressions during the
28      * compilation process.
29      */

30     Evaluator getEvaluator();
31     Validator getValidator();
32
33     /**
34      * Compiles an expression.
35      *
36      * @param exp Expression
37      * @return Compiled expression
38      */

39     Calc compile(Exp exp);
40
41     /**
42      * Compiles an expression to a given result type.
43      *
44      * @param exp Expression
45      * @param preferredResultTypes List of result types, in descending order
46      * of preference. Never null.
47      * @return Compiled expression, or null if none can satisfy
48      */

49     Calc compile(Exp exp, ResultStyle[] preferredResultTypes);
50
51     /**
52      * Compiles an expression which yields a {@link Member} result.
53      */

54     MemberCalc compileMember(Exp exp);
55
56     /**
57      * Compiles an expression which yields a {@link Level} result.
58      */

59     LevelCalc compileLevel(Exp exp);
60
61     /**
62      * Compiles an expression which yields a {@link Dimension} result.
63      */

64     DimensionCalc compileDimension(Exp exp);
65
66     /**
67      * Compiles an expression which yields a {@link Hierarchy} result.
68      */

69     HierarchyCalc compileHierarchy(Exp exp);
70
71     /**
72      * Compiles an expression which yields an <code>int</code> result.
73      * The expression is implicitly converted into a scalar.
74      */

75     IntegerCalc compileInteger(Exp exp);
76
77     /**
78      * Compiles an expression which yields a {@link String} result.
79      * The expression is implicitly converted into a scalar.
80      */

81     StringCalc compileString(Exp exp);
82
83     /**
84      * Compiles an expression which yields an immutable {@link java.util.List}
85      * result.
86      *
87      * <p>Always equivalent to <code>{@link #compileList}(exp, false)</code>.
88      */

89     ListCalc compileList(Exp exp);
90
91     /**
92      * Compiles an expression which yields {@link java.util.List} result.
93      *
94      * <p>Such an expression is generally a list of {@link Member} objects or a
95      * list of tuples (each represented by a {@link Member} array).
96      *
97      * <p>See {@link #compileList(mondrian.olap.Exp)}.
98      *
99      * @param exp Expression
100      * @param mutable Whether resulting list is mutable
101      */

102     ListCalc compileList(Exp exp, boolean mutable);
103
104     /**
105      * Compiles an expression which yields an immutable {@
106      * link * java.lang.Iterable} * result.
107      */

108     IterCalc compileIter(Exp exp);
109
110     /**
111      * Compiles an expression which yields a <code>boolean</code> result.
112      */

113     BooleanCalc compileBoolean(Exp exp);
114
115     /**
116      * Compiles an expression which yields a <code>double</code> result.
117      */

118     DoubleCalc compileDouble(Exp exp);
119
120     /**
121      * Compiles an expression which yields a tuple result.
122      */

123     TupleCalc compileTuple(Exp exp);
124
125     /**
126      * Compiles an expression to yield a scalar result.
127      *
128      * <p>If the expression yields a member or tuple, the calculator will
129      * automatically apply that member or tuple to the current dimensional
130      * context and return the value of the current measure.
131      *
132      * @param exp Expression
133      * @param convert
134      * @return Calculation which returns the scalar value of the expression
135      */

136     Calc compileScalar(Exp exp, boolean convert);
137
138     /**
139      * Implements a parameter, returning a unique slot which will hold the
140      * parameter's value.
141      *
142      * @param parameter Parameter
143      * @return Slot
144      */

145     ParameterSlot registerParameter(Parameter parameter);
146
147     /**
148      * Returns a list of the {@link mondrian.calc.ExpCompiler.ResultStyle}s
149      * acceptable to the caller.
150      */

151     ResultStyle[] getAcceptableResultStyles();
152
153     /**
154      * Enumeration of ways that a compiled expression can return its result to
155      * its caller.
156      *
157      * <p>In future, we may have an "ITERABLE" result style, which allows us
158      * to handle large lists without holding them in memory.
159      */

160     enum ResultStyle {
161         /**
162          * Indicates that caller will accept any applicable style.
163          */

164         ANY,
165
166         /**
167          * Indicates that the expression returns its result as a list which may
168          * safely be modified by the caller.
169          */

170         MUTABLE_LIST,
171
172         /**
173          * Indicates that the expression returns its result as a list which must
174          * not be modified by the caller.
175          */

176         LIST,
177
178         /**
179          * Indicates that the expression returns its result as an Iterable
180          * which must not be modified by the caller.
181          */

182         ITERABLE,
183
184         /**
185          * Indicates that the expression results its result as an immutable
186          * value. This is typical for expressions which return string and
187          * numeric values.
188          */

189         VALUE
190     }
191
192     ResultStyle[] ANY_RESULT_STYLE_ARRAY =
193         new ResultStyle[] {
194             ResultStyle.ANY
195         };
196     ResultStyle[] ITERABLE_RESULT_STYLE_ARRAY =
197         new ResultStyle[] {
198             ResultStyle.ITERABLE
199         };
200     ResultStyle[] MUTABLE_LIST_RESULT_STYLE_ARRAY =
201         new ResultStyle[] {
202             ResultStyle.MUTABLE_LIST
203         };
204     ResultStyle[] LIST_RESULT_STYLE_ARRAY =
205         new ResultStyle[] {
206             ResultStyle.LIST
207         };
208
209     ResultStyle[] ITERABLE_ANY_RESULT_STYLE_ARRAY =
210         new ResultStyle[] {
211             ResultStyle.ITERABLE,
212             ResultStyle.ANY
213         };
214     ResultStyle[] ITERABLE_LIST_RESULT_STYLE_ARRAY =
215         new ResultStyle[] {
216             ResultStyle.ITERABLE,
217             ResultStyle.LIST
218         };
219     ResultStyle[] ITERABLE_MUTABLE_LIST_RESULT_STYLE_ARRAY =
220         new ResultStyle[] {
221             ResultStyle.ITERABLE,
222             ResultStyle.MUTABLE_LIST
223         };
224     ResultStyle[] ITERABLE_LIST_MUTABLE_LIST_RESULT_STYLE_ARRAY =
225         new ResultStyle[] {
226             ResultStyle.ITERABLE,
227             ResultStyle.LIST,
228             ResultStyle.MUTABLE_LIST
229         };
230     ResultStyle[] LIST_MUTABLE_LIST_RESULT_STYLE_ARRAY =
231         new ResultStyle[] {
232             ResultStyle.LIST,
233             ResultStyle.MUTABLE_LIST
234         };
235     ResultStyle[] MUTABLE_LIST_LIST_RESULT_STYLE_ARRAY =
236         new ResultStyle[] {
237             ResultStyle.MUTABLE_LIST,
238             ResultStyle.LIST
239         };
240
241
242     /**
243      * The <code>ExpCompiler.Factory</code> is used to access
244      * <code>ExpCompiler</code> implementations. Each call returns
245      * a new instance. This factory supports overriding the default
246      * instance by use of a <code>ThreadLocal</code> and by defining a
247      * <code>System</code> property with the <code>ExpCompiler</code>
248      * class name.
249      */

250     public class Factory extends ObjectFactory<ExpCompiler> {
251         private static final Factory factory;
252         private static final Class JavaDoc[] CLASS_ARRAY;
253         static {
254             factory = new Factory();
255             CLASS_ARRAY = new Class JavaDoc[] {
256                     Evaluator.class,
257                     Validator.class,
258                     ResultStyle[].class
259                 };
260         }
261
262         /**
263          * Create a <code>ExpCompiler</code> instance, each call returns a
264          * new compiler.
265          *
266          * @param evaluator the <code>Evaluator</code> to use with the compiler
267          * @param validator the <code>Validator</code> to use with the compiler
268          * @return the new <code>ExpCompiler</code> compiler
269          * @throws CreationException if the compiler can not be created
270          */

271         public static ExpCompiler getExpCompiler(final Evaluator evaluator,
272             final Validator validator)
273                 throws CreationException {
274             return getExpCompiler(evaluator, validator, ANY_RESULT_STYLE_ARRAY);
275         }
276
277         /**
278          *
279          *
280          * @param evaluator the <code>Evaluator</code> to use with the compiler
281          * @param validator the <code>Validator</code> to use with the compiler
282          * @param resultStyles the initial <code>ResultStyle</code> array
283          * for the compiler
284          * @return the new <code>ExpCompiler</code> compiler
285          * @throws CreationException if the compiler can not be created
286          */

287         public static ExpCompiler getExpCompiler(final Evaluator evaluator,
288             final Validator validator,
289             final ResultStyle[] resultStyles)
290                 throws CreationException {
291             return factory.getObject(CLASS_ARRAY,
292                             new Object JavaDoc[] {
293                                 evaluator,
294                                 validator,
295                                 resultStyles
296                             });
297         }
298
299         /**
300          * <code>ThreadLocal</code> used to hold the class name of an
301          * <code>ExpCompiler</code> implementation.
302          * Generally, this should only be used for testing.
303          */

304         private static final ThreadLocal JavaDoc<String JavaDoc> ClassName =
305             new ThreadLocal JavaDoc<String JavaDoc>();
306
307         /**
308          * Get the class name of a <code>ExpCompiler</code> implementation
309          * or null.
310          *
311          * @return the class name or null.
312         */

313         public static String JavaDoc getThreadLocalClassName() {
314             return ClassName.get();
315         }
316         /**
317          * Sets the class name of a <code>ExpCompiler</code> implementation.
318          * This should be called (obviously) before calling the
319          * <code>ExpCompiler.Factory</code> <code>getExpCompiler</code>
320          * method to get the <code>ExpCompiler</code> implementation.
321          * Generally, this is only used for testing.
322          *
323          * @param className Class name
324          */

325         public static void setThreadLocalClassName(String JavaDoc className) {
326             ClassName.set(className);
327         }
328         /**
329          * Clears the class name (regardless of whether a class name was set).
330          * When a class name is set using <code>setThreadLocalClassName</code>,
331          * the setting whould be done in a try-block and a call to this
332          * clear method should be in the finally-clause of that try-block.
333          */

334         public static void clearThreadLocalClassName() {
335             ClassName.set(null);
336         }
337
338         /**
339          * The constructor for the <code>ExpCompiler.Factory</code>.
340          * This passes the <code>ExpCompiler</code> class to the
341          * <code>ObjectFactory</code> base class.
342         */

343         private Factory() {
344             super(ExpCompiler.class);
345         }
346         /**
347          * Get the class name set in the <code>ThreadLocal</code> or null.
348          *
349          * @return class name or null.
350          */

351         protected String JavaDoc getClassName() {
352             return getThreadLocalClassName();
353         }
354
355         /**
356          * Return the <code>ExpCompiler.Factory</code property name.
357          *
358          * @return <code>ExpCompiler.Factory</code> property name
359          */

360         protected StringProperty getStringProperty() {
361             return MondrianProperties.instance().ExpCompilerClass;
362         }
363         /**
364          * The <code>ExpCompiler.Factory</code>'s implementation of the
365          * <code>ObjectFactory</code>'s abstract method which returns
366          * the default <code>ExpCompiler</code> instance.
367          *
368          * @param parameterTypes array of classes: Evaluator, Validator and
369          * ResultStyle
370          * @param parameterValues the Evaluator, Validator and ResultStyle
371          * values
372          * @return <code>ExpCompiler</code> instance
373          * @throws CreationException if the <code>ExpCompiler</code> can not be
374          * created.
375          */

376         protected ExpCompiler getDefault(final Class JavaDoc[] parameterTypes,
377             final Object JavaDoc[] parameterValues)
378                 throws CreationException {
379             // Strong typed above so don't need to check here
380
Evaluator evaluator = (Evaluator) parameterValues[0];
381             Validator validator = (Validator) parameterValues[1];
382             ResultStyle[] resultStyles = (ResultStyle[]) parameterValues[2];
383
384             // Here there is bleed-through from the "calc.impl" implementation
385
// directory into the "calc" interface definition directory.
386
// This can be avoided if we were to use reflection to
387
// create this the default ExpCompiler implementation.
388
return new mondrian.calc.impl.BetterExpCompiler(
389                             evaluator, validator, resultStyles);
390         }
391
392         /**
393          * Get the underlying Factory object.
394          * <p>
395          * This is for testing only.
396          *
397          * @return the <code>ExpCompiler.Factory</code> object
398          */

399         public static Factory getFactory() {
400             return factory;
401         }
402         
403         /**
404          * Get the current override contect.
405          * <p>
406          * This is for testing only.
407          *
408          * @return the override context object.
409          */

410         public Object JavaDoc removeContext() {
411             return new Context();
412         }
413         
414         /**
415          * Restore the current overrides.
416          * <p>
417          * This is for testing only.
418          *
419          * @param context the current override object.
420          */

421         public void restoreContext(final Object JavaDoc context) {
422             if (context instanceof Context) {
423                 ((Context) context).restore();
424             }
425         }
426         
427         /**
428          * The <code>ExpCompiler</code> only has two override mechanisms: the
429          * <code>ThreadLocal</code> and <code>System</code>
430          * <code>Properties</code>. This class captures and clears the current
431          * values for both in the constructor and then replaces them
432          * in the <code>restore</code> method.
433          * <p>
434          * This is for testing only.
435          */

436         public static class Context implements ObjectFactory.Context {
437             private final String JavaDoc threadLocalClassName;
438             private final String JavaDoc systemPropertyClassName;
439             Context() {
440                 this.threadLocalClassName =
441                         ExpCompiler.Factory.getThreadLocalClassName();
442                 if (this.threadLocalClassName != null) {
443                     ExpCompiler.Factory.clearThreadLocalClassName();
444                 }
445
446                 this.systemPropertyClassName =
447                         System.getProperty(ExpCompiler.class.getName());
448                 if (this.systemPropertyClassName != null) {
449                     System.getProperties().remove(ExpCompiler.class.getName());
450                 }
451             }
452             private void restore() {
453                 if (this.threadLocalClassName != null) {
454                     ExpCompiler.Factory.setThreadLocalClassName(
455                         this.threadLocalClassName);
456                 }
457                 if (this.systemPropertyClassName != null) {
458                     System.setProperty(ExpCompiler.class.getName(),
459                             this.systemPropertyClassName);
460                 }
461             }
462         }
463     }
464 }
465
466 // End ExpCompiler.java
467
Popular Tags