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) 2001-2005 Julian Hyde
008// Copyright (C) 2005-2011 Pentaho and others
009// All Rights Reserved.
010*/
011package mondrian.olap;
012
013import mondrian.calc.ParameterSlot;
014import mondrian.calc.TupleIterable;
015
016import java.util.*;
017
018/**
019 * An <code>Evaluator</code> holds the context necessary to evaluate an
020 * expression.
021 *
022 * @author jhyde
023 * @since 27 July, 2001
024 */
025public interface Evaluator {
026
027    /**
028     * Returns the current cube.
029     */
030    Cube getCube();
031
032    /**
033     * Returns the current query.
034     */
035    Query getQuery();
036
037    /**
038     * Returns the start time of the current query.
039     */
040    Date getQueryStartTime();
041
042    /**
043     * Creates a savepoint encapsulating the current state of the evalutor.
044     * You can restore the evaluator to this state by calling
045     * {@link #restore(int)} with the value returned by this method.
046     *
047     * <p>This method is typically called before evaluating an expression which
048     * is known to corrupt the evaluation context.
049     *
050     * <p>Multiple savepoints may be active at the same time for the same
051     * evaluator. And, it is allowable to restore to the save savepoint more
052     * than once (or not at all). However, when you have rolled back to a
053     * particular savepoint you may not restore to a later savepoint.
054     *
055     * @return Evaluator with each given member overriding the state of the
056     *   current Evaluator for its hierarchy
057     */
058    int savepoint();
059
060    /**
061     * Creates a new Evaluator with each given member overriding the context of
062     * the current Evaluator for its hierarchy. Other hierarchies retain the
063     * same context as this Evaluator.
064     *
065     * <p>In mondrian-3.3 and later, a more efficient way to save the state of
066     * an evaluator is to call {@link #savepoint} followed by
067     * {@link #restore(int)}. We recommend using those methods.
068     *
069     * @param members Array of members to add to the context
070     * @return Evaluator with each given member overriding the state of the
071     *   current Evaluator for its hierarchy
072     *
073     * @deprecated Use {@link #savepoint()} followed by
074     *   {@link #setContext(Member[])}; will be removed in mondrian-4
075     */
076    Evaluator push(Member[] members);
077
078    /**
079     * Creates a new Evaluator with the same context as this evaluator.
080     *
081     * <p>This method is typically called before evaluating an expression which
082     * may corrupt the evaluation context.
083     *
084     * <p>In mondrian-3.3 and later, a more efficient way to save the state of
085     * an evaluator is to call {@link #savepoint} followed by
086     * {@link #restore(int)}. We recommend using those methods most of the time.
087     *
088     * <p>However, it makes sense to use this method in the constructor of an
089     * iterator. It allows the iterator to modify its evaluation context without
090     * affecting the evaluation context of the calling code. This behavior
091     * cannot be achieved using {@code savepoint}.
092     *
093     * @return Evaluator with each given member overriding the state of the
094     *   current Evaluator for its hierarchy
095     */
096    Evaluator push();
097
098    /**
099     * Creates a new Evaluator with the same context except for one member.
100     *
101     * <p>This method is typically called before evaluating an expression which
102     * may corrupt the evaluation context.
103     *
104     * <p>In mondrian-3.3 and later, a more efficient way to save the state of
105     * an evaluator is to call {@link #savepoint} followed by
106     * {@link #restore(int)}. We recommend using those methods.
107     *
108     * @param member Member to add to the context
109     * @return Evaluator with each given member overriding the state of the
110     *   current Evaluator for its hierarchy
111     *
112     * @deprecated Use {@link #savepoint()} followed by
113     *   {@link #setContext(Member)}; will be removed in mondrian-4
114     */
115    Evaluator push(Member member);
116
117    /**
118     * Creates a new evaluator with the same state except nonEmpty property
119     *
120     * <p>In mondrian-3.3 and later, a more efficient way to save the state of
121     * an evaluator is to call {@link #savepoint} followed by
122     * {@link #restore(int)}. We recommend using those methods.
123     *
124     * @deprecated Use {@link #savepoint()} followed by
125     *     {@link #setNonEmpty(boolean)}; will be removed in mondrian-4
126     */
127    Evaluator push(boolean nonEmpty);
128
129    /**
130     * Creates a new evaluator with the same state except nonEmpty
131     * and nativeEnabled properties.
132     *
133     * <p>In mondrian-3.3 and later, a more efficient way to save the state of
134     * an evaluator is to call {@link #savepoint} followed by
135     * {@link #restore(int)}. We recommend using those methods.
136     *
137     * @deprecated Use {@link #savepoint()} followed by
138     *     {@link #setNonEmpty(boolean)} and
139     *     {@link #setNativeEnabled(boolean)}; will be removed in mondrian-4.
140     */
141    Evaluator push(boolean nonEmpty, boolean nativeEnabled);
142
143    /**
144     * Restores previous evaluator.
145     *
146     * @param savepoint Savepoint returned by {@link #savepoint()}
147     */
148    void restore(int savepoint);
149
150    /**
151     * Makes <code>member</code> the current member of its hierarchy.
152     *
153     * @param member  New member
154     *
155     * @return Previous member of this hierarchy
156     */
157    Member setContext(Member member);
158
159    /**
160     * Makes <code>member</code> the current member of its hierarchy.
161     *
162     * <p>If {@code safe}, checks whether this is the first time that
163     * a member of this hierarchy has been changed since {@link #savepoint()}
164     * was called. If so, saves the previous member. If {@code safe} is false,
165     * never saves the previous member.
166     *
167     * <p>Use {@code safe = false} only if you are sure that the context has
168     * been set before. For example,
169     *
170     * <blockquote>
171     * <code>int n = 0;<br/>
172     * for (Member member : members) {<br/>
173     * &nbsp;&nbsp;evaluator.setContext(member, n++ &gt; 0);<br/>
174     * }<br/></code></blockquote>
175     *
176     * @param member  New member
177     * @param safe    Whether to store the member of this hierarchy that was
178     *                current last time that {@link #savepoint()} was called.
179     */
180    void setContext(Member member, boolean safe);
181
182    /**
183     * Sets the context to a list of members.
184     *
185     * <p>Equivalent to
186     *
187     * <blockquote><code>for (Member member : memberList) {<br/>
188     * &nbsp;&nbsp;setContext(member);<br/>
189     * }<br/></code></blockquote>
190     *
191     * @param memberList List of members
192     */
193    void setContext(List<Member> memberList);
194
195    /**
196     * Sets the context to a list of members, optionally skipping the check
197     * whether it is necessary to store the previous member of each hierarchy.
198     *
199     * <p>Equivalent to
200     *
201     * <blockquote><code>for (Member member : memberList) {<br/>
202     * &nbsp;&nbsp;setContext(member, safe);<br/>
203     * }<br/></code></blockquote>
204     *
205     * @param memberList List of members
206     * @param safe    Whether to store the member of each hierarchy that was
207     *                current last time that {@link #savepoint()} was called.
208     */
209    void setContext(List<Member> memberList, boolean safe);
210
211    /**
212     * Sets the context to an array of members.
213     *
214     * <p>Equivalent to
215     *
216     * <blockquote><code>for (Member member : memberList) {<br/>
217     * &nbsp;&nbsp;setContext(member);<br/>
218     * }<br/></code></blockquote>
219     *
220     * @param members Array of members
221     */
222    void setContext(Member[] members);
223
224    /**
225     * Sets the context to an array of members, optionally skipping the check
226     * whether it is necessary to store the previous member of each hierarchy.
227     *
228     * <p>Equivalent to
229     *
230     * <blockquote><code>for (Member member : memberList) {<br/>
231     * &nbsp;&nbsp;setContext(member, safe);<br/>
232     * }<br/></code></blockquote>
233     *
234     * @param members Array of members
235     * @param safe    Whether to store the member of each hierarchy that was
236     *                current last time that {@link #savepoint()} was called.
237     */
238    void setContext(Member[] members, boolean safe);
239
240    Member getContext(Hierarchy hierarchy);
241
242    /**
243     * Calculates and returns the value of the cell at the current context.
244     */
245    Object evaluateCurrent();
246
247    /**
248     * Returns the format string for this cell. This is computed by evaluating
249     * the format expression in the current context, and therefore different
250     * cells may have different format strings.
251     */
252    public String getFormatString();
253
254    /**
255     * Formats a value as a string according to the current context's
256     * format.
257     */
258    String format(Object o);
259
260    /**
261     * Formats a value as a string according to the current context's
262     * format, using a given format string.
263     */
264    String format(Object o, String formatString);
265
266    /**
267     * Obsolete method.
268     *
269     * @deprecated Will be removed in mondrian-4
270     */
271    int getDepth();
272
273    /**
274     * Returns parent evaluator.
275     *
276     * @deprecated Will be removed in mondrian-4
277     */
278    Evaluator getParent();
279
280    /**
281     * Returns the connection's locale.
282     */
283    Locale getConnectionLocale();
284
285    /**
286     * Retrieves the value of property <code>name</code>. If more than one
287     * member in the current context defines that property, the one with the
288     * highest solve order has precedence.
289     *
290     * <p>If the property is not defined, default value is returned.
291     */
292    Object getProperty(String name, Object defaultValue);
293
294    /**
295     * Returns a {@link SchemaReader} appropriate for the current
296     * access-control context.
297     */
298    SchemaReader getSchemaReader();
299
300    /**
301     * Simple caching of the result of an <code>Exp</code>. The
302     * key for the cache consists of all members of the current
303     * context that <code>exp</code> depends on. Members of
304     * independent hierarchies are not part of the key.
305     *
306     * @see mondrian.calc.Calc#dependsOn(Hierarchy)
307     */
308    Object getCachedResult(ExpCacheDescriptor key);
309
310    /**
311     * Returns true for an axis that is NON EMPTY.
312     *
313     * <p>May be used by expression
314     * evaluators to optimize their result. For example, a top-level crossjoin
315     * may be optimized by removing all non-empty set elements before
316     * performing the crossjoin. This is possible because of the identity
317     *
318     * <blockquote><code>nonempty(crossjoin(a, b)) ==
319     * nonempty(crossjoin(nonempty(a), nonempty(b));</code></blockquote>
320     */
321    boolean isNonEmpty();
322
323    /**
324     * Sets whether an expression evaluation should filter out empty cells.
325     * Allows expressions to modify non empty flag to evaluate their children.
326     */
327    void setNonEmpty(boolean nonEmpty);
328
329    /**
330     * Creates an exception which indicates that an error has occurred during
331     * the runtime evaluation of a function. The caller should then throw that
332     * exception.
333     */
334    RuntimeException newEvalException(Object context, String s);
335
336    /**
337     * Returns an evaluator for a set.
338     *
339     * @param exp Expression
340     * @param create Whether to create evaluator if not found
341     * @return Evaluator of named set
342     */
343    SetEvaluator getSetEvaluator(Exp exp, boolean create);
344
345    /**
346     * Returns an evaluator for a named set.
347     *
348     * @param namedSet Named set
349     * @param create Whether to create evaluator if not found
350     * @return Evaluator of named set
351     */
352    NamedSetEvaluator getNamedSetEvaluator(NamedSet namedSet, boolean create);
353
354    /**
355     * Returns an array of the members which make up the current context.
356     */
357    Member[] getMembers();
358
359    /**
360     * Returns an array of the non-All members which make up the current
361     * context.
362     *
363     * <p>Notes:<ul>
364     * <li>The 0th element is a measure, but otherwise the order of the
365     *     members is unspecified.
366     * <li>No hierarchy occurs more than once.
367     * <li>In rare circumstances, some of the members may be an 'All' member.
368     * <li>The list may contain calculated members.
369     * </ul>
370     */
371    Member[] getNonAllMembers();
372
373    /**
374     * Returns the number of times that this evaluator has told a lie when
375     * retrieving cell values.
376     */
377    int getMissCount();
378
379    /**
380     * Returns the value of a parameter, evaluating its default value if it is
381     * not set.
382     */
383    Object getParameterValue(ParameterSlot slot);
384
385    /**
386     * @return the iteration length of the current context
387     */
388    int getIterationLength();
389
390    /**
391     * Sets the iteration length for the current evaluator context
392     *
393     * @param length length to be set
394     */
395    void setIterationLength(int length);
396
397    /**
398     * @return true if evaluating axes
399     */
400    boolean isEvalAxes();
401
402    /**
403     * Indicate whether the evaluator is evaluating the axes
404     *
405     * @param evalAxes true if evaluating axes
406     */
407    void setEvalAxes(boolean evalAxes);
408
409    /**
410     * Returns a new Aggregator whose aggregation context adds a given list of
411     * tuples, and whose evaluation context is the same as this
412     * Aggregator.
413     *
414     * @param list List of tuples
415     * @return Aggregator with <code>list</code> added to its aggregation
416     *   context
417     */
418    Evaluator pushAggregation(List<List<Member>> list);
419
420    /**
421     * Returns whether hierarchies unrelated to the measure in the current
422     * context should be ignored.
423     *
424     * @return whether hierarchies unrelated to the measure in the current
425     *     context should be ignored
426     */
427    boolean shouldIgnoreUnrelatedDimensions();
428
429    /**
430     * Returns the base (non-virtual) cube that the current measure in the
431     * context belongs to.
432     * @return Cube
433     */
434    Cube getMeasureCube();
435
436    /**
437     * Returns whether it is necessary to check whether to return null for
438     * an unrelated dimension. If false, we never need to check: we can assume
439     * that {@link #needToReturnNullForUnrelatedDimension(mondrian.olap.Member[])}
440     * will always return false.
441     *
442     * @return whether it is necessary to check whether to return null for
443     * an unrelated dimension
444     */
445    boolean mightReturnNullForUnrelatedDimension();
446
447    /**
448     * If IgnoreMeasureForNonJoiningDimension is set to true and one or more
449     * members are on unrelated dimension for the measure in current context
450     * then returns true.
451     *
452     * <p>You must not call this method unless
453     * {@link #mightReturnNullForUnrelatedDimension()} has returned true.
454     *
455     * @param members Dimensions for the members need to be checked whether
456     *     related or unrelated
457     *
458     * @return boolean
459     */
460    boolean needToReturnNullForUnrelatedDimension(Member[] members);
461
462    /**
463     * Returns whether native evaluation is enabled in this context.
464     *
465     * @return whether native evaluation is enabled in this context
466     */
467    boolean nativeEnabled();
468
469    /**
470     * Sets whether native evaluation should be used.
471     *
472     * @param nativeEnabled Whether native evaluation should be used
473     */
474   void setNativeEnabled(boolean nativeEnabled);
475
476    /**
477     * Returns whether the current context is an empty cell.
478     *
479     * @return Whether the current context is an empty cell
480     */
481    boolean currentIsEmpty();
482
483    /**
484     * Returns the member that was the current evaluation context for a
485     * particular hierarchy before the most recent change in context.
486     *
487     * @param hierarchy Hierarchy
488     * @return Previous context member for given hierarchy
489     */
490    Member getPreviousContext(Hierarchy hierarchy);
491
492    /**
493     * Returns the query timing context for this execution.
494     *
495     * @return query timing context
496     */
497    QueryTiming getTiming();
498
499    /**
500     * Interface for evaluating a particular named set.
501     */
502    interface NamedSetEvaluator {
503        /**
504         * Returns an iterator over the tuples of the named set. Applicable if
505         * the named set is a set of tuples.
506         *
507         * <p>The iterator from this iterable maintains the current ordinal
508         * property required for the methods {@link #currentOrdinal()} and
509         * {@link #currentTuple()}.
510         *
511         * @param eval Evaluator for current context
512         *
513         * @return Iterable over the tuples of the set
514         */
515        TupleIterable evaluateTupleIterable(Evaluator eval);
516
517        /**
518         * Returns the ordinal of the current member or tuple in the named set.
519         *
520         * @return Ordinal of the current member or tuple in the named set
521         */
522        int currentOrdinal();
523
524        /**
525         * Returns the current member in the named set.
526         *
527         * <p>Applicable if the named set is a set of members.
528         *
529         * @return Current member
530         */
531        Member currentMember();
532
533        /**
534         * Returns the current tuple in the named set.
535         *
536         * <p>Applicable if the named set is a set of tuples.
537         *
538         * @return Current tuple.
539         */
540        Member[] currentTuple();
541    }
542
543    /**
544     * Interface for generically evaluating a set.
545     */
546    interface SetEvaluator {
547        /**
548         * Returns an iterator over the tuples of the named set. Applicable if
549         * the named set is a set of tuples.
550         *
551         * <p>The iterator from this iterable maintains the current ordinal
552         * property required for the methods {@link #currentOrdinal()} and
553         * {@link #currentTuple()}.
554         *
555         * @return Iterable over the tuples of the set
556         */
557        TupleIterable evaluateTupleIterable();
558
559        /**
560         * Returns the ordinal of the current member or tuple in the named set.
561         *
562         * @return Ordinal of the current member or tuple in the named set
563         */
564        int currentOrdinal();
565
566        /**
567         * Returns the current member in the named set.
568         *
569         * <p>Applicable if the named set is a set of members.
570         *
571         * @return Current member
572         */
573        Member currentMember();
574
575        /**
576         * Returns the current tuple in the named set.
577         *
578         * <p>Applicable if the named set is a set of tuples.
579         *
580         * @return Current tuple.
581         */
582        Member[] currentTuple();
583    }
584}
585
586// End Evaluator.java