KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > olap > fun > BuiltinFunTable


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/olap/fun/BuiltinFunTable.java#125 $
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) 2002-2002 Kana Software, Inc.
7 // Copyright (C) 2002-2007 Julian Hyde and others
8 // All Rights Reserved.
9 // You must accept the terms of that agreement to use this software.
10 //
11 // jhyde, 26 February, 2002
12 */

13 package mondrian.olap.fun;
14
15 import mondrian.calc.*;
16 import mondrian.calc.impl.*;
17 import mondrian.mdx.DimensionExpr;
18 import mondrian.mdx.ResolvedFunCall;
19 import mondrian.olap.*;
20 import mondrian.olap.fun.extra.NthQuartileFunDef;
21 import mondrian.olap.fun.extra.CalculatedChildFunDef;
22 import mondrian.olap.type.DimensionType;
23 import mondrian.olap.type.LevelType;
24 import mondrian.olap.type.Type;
25 import org.eigenbase.xom.XOMUtil;
26
27 import java.io.PrintWriter JavaDoc;
28 import java.util.*;
29
30 /**
31  * <code>BuiltinFunTable</code> contains a list of all built-in MDX functions.
32  *
33  * <p>Note: Boolean expressions return {@link Boolean#TRUE},
34  * {@link Boolean#FALSE} or null. null is returned if the expression can not be
35  * evaluated because some values have not been loaded from database yet.</p>
36  *
37  * @author jhyde
38  * @since 26 February, 2002
39  * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/BuiltinFunTable.java#125 $
40  */

41 public class BuiltinFunTable extends FunTableImpl {
42
43     /** the singleton */
44     private static BuiltinFunTable instance;
45
46     /**
47      * Creates a function table containing all of the builtin MDX functions.
48      * This method should only be called from {@link BuiltinFunTable#instance}.
49      */

50     protected BuiltinFunTable() {
51         super();
52     }
53
54     protected void defineFunctions() {
55         defineReserved("NULL");
56
57         // first char: p=Property, m=Method, i=Infix, P=Prefix
58
// 2nd:
59

60         // ARRAY FUNCTIONS
61
if (false) define(new FunDefBase(
62                 "SetToArray",
63                 "SetToArray(<Set>[, <Set>]...[, <Numeric Expression>])",
64                 "Converts one or more sets to an array for use in a user-defined function.",
65                 "fa*") {
66             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
67                 throw new UnsupportedOperationException JavaDoc();
68             }
69         });
70
71         //
72
// DIMENSION FUNCTIONS
73
define(HierarchyDimensionFunDef.instance);
74
75         define(new FunDefBase(
76                 "Dimension",
77                 "<Dimension>.Dimension",
78                 "Returns the dimension that contains a specified hierarchy.",
79                 "pdd") {
80             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
81                 Dimension dimension =
82                         ((DimensionExpr) call.getArg(0)).getDimension();
83                 return new ConstantCalc(
84                         DimensionType.forDimension(dimension),
85                         dimension);
86             }
87
88         });
89
90         define(new FunDefBase(
91                 "Dimension",
92                 "<Level>.Dimension",
93                 "Returns the dimension that contains a specified level.",
94                 "pdl") {
95             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
96                 final LevelCalc levelCalc =
97                         compiler.compileLevel(call.getArg(0));
98                 return new AbstractDimensionCalc(call, new Calc[] {levelCalc}) {
99                     public Dimension evaluateDimension(Evaluator evaluator) {
100                         Level level = levelCalc.evaluateLevel(evaluator);
101                         return level.getDimension();
102                     }
103                 };
104             }
105         });
106
107         define(new FunDefBase(
108                 "Dimension",
109                 "<Member>.Dimension",
110                 "Returns the dimension that contains a specified member.",
111                 "pdm") {
112             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
113                 final MemberCalc memberCalc =
114                         compiler.compileMember(call.getArg(0));
115                 return new AbstractDimensionCalc(call, new Calc[] {memberCalc}) {
116                     public Dimension evaluateDimension(Evaluator evaluator) {
117                         Member member = memberCalc.evaluateMember(evaluator);
118                         return member.getDimension();
119                     }
120                 };
121             }
122         });
123
124         define(new FunDefBase(
125                 "Dimensions",
126                 "Dimensions(<Numeric Expression>)",
127                 "Returns the dimension whose zero-based position within the cube is specified by a numeric expression.",
128                 "fdn") {
129             public Type getResultType(Validator validator, Exp[] args) {
130                 return DimensionType.Unknown;
131             }
132
133             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
134                 final IntegerCalc integerCalc =
135                         compiler.compileInteger(call.getArg(0));
136                 return new AbstractDimensionCalc(call, new Calc[] {integerCalc}) {
137                     public Dimension evaluateDimension(Evaluator evaluator) {
138                         int n = integerCalc.evaluateInteger(evaluator);
139                         return nthDimension(evaluator, n);
140                     }
141                 };
142             }
143
144             Dimension nthDimension(Evaluator evaluator, int n) {
145                 Cube cube = evaluator.getCube();
146                 Dimension[] dimensions = cube.getDimensions();
147                 if (n >= dimensions.length || n < 0) {
148                     throw newEvalException(
149                             this, "Index '" + n + "' out of bounds");
150                 }
151                 return dimensions[n];
152             }
153         });
154         define(new FunDefBase(
155                 "Dimensions",
156                 "Dimensions(<String Expression>)",
157                 "Returns the dimension whose name is specified by a string.",
158                 "fdS") {
159             public Type getResultType(Validator validator, Exp[] args) {
160                 return DimensionType.Unknown;
161             }
162
163             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
164                 final StringCalc stringCalc =
165                         compiler.compileString(call.getArg(0));
166                 return new AbstractDimensionCalc(call, new Calc[] {stringCalc}) {
167                     public Dimension evaluateDimension(Evaluator evaluator) {
168                         String JavaDoc dimensionName =
169                                 stringCalc.evaluateString(evaluator);
170                         return findDimension(dimensionName, evaluator);
171                     }
172                 };
173             }
174
175             Dimension findDimension(String JavaDoc s, Evaluator evaluator) {
176                 if (s.indexOf("[") == -1) {
177                     s = Util.quoteMdxIdentifier(s);
178                 }
179                 OlapElement o = evaluator.getSchemaReader().lookupCompound(
180                         evaluator.getCube(),
181                         explode(s),
182                         false,
183                         Category.Dimension);
184                 if (o instanceof Dimension) {
185                     return (Dimension) o;
186                 } else if (o == null) {
187                     throw newEvalException(this, "Dimension '" + s + "' not found");
188                 } else {
189                     throw newEvalException(this, "Dimensions(" + s + ") found " + o);
190                 }
191             }
192         });
193
194         //
195
// HIERARCHY FUNCTIONS
196
define(LevelHierarchyFunDef.instance);
197         define(MemberHierarchyFunDef.instance);
198
199         //
200
// LEVEL FUNCTIONS
201
define(MemberLevelFunDef.instance);
202
203         define(new FunDefBase(
204                 "Levels",
205                 "<Hierarchy>.Levels(<Numeric Expression>)",
206                 "Returns the level whose position in a hierarchy is specified by a numeric expression.",
207                 "mlhn") {
208             public Type getResultType(Validator validator, Exp[] args) {
209                 final Type argType = args[0].getType();
210                 return LevelType.forType(argType);
211             }
212
213             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
214                 final HierarchyCalc hierarchyCalc =
215                         compiler.compileHierarchy(call.getArg(0));
216                 final IntegerCalc ordinalCalc =
217                         compiler.compileInteger(call.getArg(1));
218                 return new AbstractLevelCalc(call, new Calc[] {hierarchyCalc, ordinalCalc}) {
219                     public Level evaluateLevel(Evaluator evaluator) {
220                         Hierarchy hierarchy =
221                                 hierarchyCalc.evaluateHierarchy(evaluator);
222                         int ordinal = ordinalCalc.evaluateInteger(evaluator);
223                         return nthLevel(hierarchy, ordinal);
224                     }
225                 };
226             }
227
228             Level nthLevel(Hierarchy hierarchy, int n) {
229                 Level[] levels = hierarchy.getLevels();
230
231                 if (n >= levels.length || n < 0) {
232                     throw newEvalException(
233                             this, "Index '" + n + "' out of bounds");
234                 }
235                 return levels[n];
236             }
237         });
238
239         define(new FunDefBase(
240                 "Levels",
241                 "Levels(<String Expression>)",
242                 "Returns the level whose name is specified by a string expression.",
243                 "flS") {
244             public Type getResultType(Validator validator, Exp[] args) {
245                 final Type argType = args[0].getType();
246                 return LevelType.forType(argType);
247             }
248             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
249                 final StringCalc stringCalc =
250                         compiler.compileString(call.getArg(0));
251                 return new AbstractLevelCalc(call, new Calc[] {stringCalc}) {
252                     public Level evaluateLevel(Evaluator evaluator) {
253                         String JavaDoc levelName =
254                                 stringCalc.evaluateString(evaluator);
255                         return findLevel(evaluator, levelName);
256                     }
257                 };
258             }
259
260             Level findLevel(Evaluator evaluator, String JavaDoc s) {
261                 Cube cube = evaluator.getCube();
262                 OlapElement o = (s.startsWith("[")) ?
263                         evaluator.getSchemaReader().lookupCompound(
264                                 cube,
265                                 explode(s),
266                                 false,
267                                 Category.Level) :
268                         // lookupCompound barfs if "s" doesn't have matching
269
// brackets, so don't even try
270
null;
271
272                 if (o instanceof Level) {
273                     return (Level) o;
274                 } else if (o == null) {
275                     throw newEvalException(this, "Level '" + s + "' not found");
276                 } else {
277                     throw newEvalException(this, "Levels('" + s + "') found " + o);
278                 }
279             }
280         });
281
282         //
283
// LOGICAL FUNCTIONS
284
define(IsEmptyFunDef.FunctionResolver);
285         define(IsEmptyFunDef.PostfixResolver);
286         define(IsNullFunDef.Resolver);
287         define(IsFunDef.Resolver);
288
289         //
290
// MEMBER FUNCTIONS
291
define(AncestorFunDef.Resolver);
292
293         define(new FunDefBase(
294                 "Cousin",
295                 "Cousin(<member>, <ancestor member>)",
296                 "Returns the member with the same relative position under <ancestor member> as the member specified.",
297                 "fmmm") {
298             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
299                 final MemberCalc memberCalc =
300                         compiler.compileMember(call.getArg(0));
301                 final MemberCalc ancestorMemberCalc =
302                         compiler.compileMember(call.getArg(1));
303                 return new AbstractMemberCalc(call, new Calc[] {memberCalc, ancestorMemberCalc}) {
304                     public Member evaluateMember(Evaluator evaluator) {
305                         Member member = memberCalc.evaluateMember(evaluator);
306                         Member ancestorMember = ancestorMemberCalc.evaluateMember(evaluator);
307                         return cousin(
308                                 evaluator.getSchemaReader(),
309                                 member,
310                                 ancestorMember);
311                     }
312                 };
313             }
314
315         });
316
317         define(DimensionCurrentMemberFunDef.instance);
318
319         define(HierarchyCurrentMemberFunDef.instance);
320
321         define(new FunDefBase(
322                 "DataMember",
323                 "<Member>.DataMember",
324                 "Returns the system-generated data member that is associated with a nonleaf member of a dimension.",
325                 "pmm") {
326             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
327                 final MemberCalc memberCalc =
328                         compiler.compileMember(call.getArg(0));
329                 return new AbstractMemberCalc(call, new Calc[] {memberCalc}) {
330                     public Member evaluateMember(Evaluator evaluator) {
331                         Member member = memberCalc.evaluateMember(evaluator);
332                         return member.getDataMember();
333                     }
334                 };
335             }
336
337         });
338
339         define(new FunDefBase(
340                 "DefaultMember",
341                 "<Dimension>.DefaultMember",
342                 "Returns the default member of a dimension.",
343                 "pmd") {
344             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
345                 final DimensionCalc dimensionCalc =
346                         compiler.compileDimension(call.getArg(0));
347                 return new AbstractMemberCalc(call, new Calc[] {dimensionCalc}) {
348                     public Member evaluateMember(Evaluator evaluator) {
349                         Dimension dimension =
350                                 dimensionCalc.evaluateDimension(evaluator);
351                         return evaluator.getSchemaReader()
352                                 .getHierarchyDefaultMember(
353                                         dimension.getHierarchies()[0]);
354                     }
355                 };
356             }
357         });
358
359         define(new FunDefBase(
360                 "DefaultMember",
361                 "<Hierarchy>.DefaultMember",
362                 "Returns the default member of a hierarchy.",
363                 "pmh") {
364             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
365                 final HierarchyCalc hierarchyCalc =
366                         compiler.compileHierarchy(call.getArg(0));
367                 return new AbstractMemberCalc(call, new Calc[] {hierarchyCalc}) {
368                     public Member evaluateMember(Evaluator evaluator) {
369                         Hierarchy hierarchy =
370                                 hierarchyCalc.evaluateHierarchy(evaluator);
371                         return evaluator.getSchemaReader()
372                                 .getHierarchyDefaultMember(hierarchy);
373                     }
374                 };
375             }
376         });
377
378         define(new FunDefBase(
379                 "FirstChild",
380                 "<Member>.FirstChild",
381                 "Returns the first child of a member.",
382                 "pmm") {
383             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
384                 final MemberCalc memberCalc =
385                         compiler.compileMember(call.getArg(0));
386                 return new AbstractMemberCalc(call, new Calc[] {memberCalc}) {
387                     public Member evaluateMember(Evaluator evaluator) {
388                         Member member = memberCalc.evaluateMember(evaluator);
389                         return firstChild(evaluator, member);
390                     }
391                 };
392             }
393
394             Member firstChild(Evaluator evaluator, Member member) {
395                 Member[] children = evaluator.getSchemaReader()
396                         .getMemberChildren(member);
397                 return (children.length == 0)
398                         ? member.getHierarchy().getNullMember()
399                         : children[0];
400             }
401         });
402
403         define(new FunDefBase(
404                 "FirstSibling",
405                 "<Member>.FirstSibling",
406                 "Returns the first child of the parent of a member.",
407                 "pmm") {
408             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
409                 final MemberCalc memberCalc =
410                         compiler.compileMember(call.getArg(0));
411                 return new AbstractMemberCalc(call, new Calc[] {memberCalc}) {
412                     public Member evaluateMember(Evaluator evaluator) {
413                         Member member = memberCalc.evaluateMember(evaluator);
414                         return firstSibling(member, evaluator);
415                     }
416                 };
417             }
418
419             Member firstSibling(Member member, Evaluator evaluator) {
420                 Member parent = member.getParentMember();
421                 Member[] children;
422                 if (parent == null) {
423                     if (member.isNull()) {
424                         return member;
425                     }
426                     children = evaluator.getSchemaReader().getHierarchyRootMembers(member.getHierarchy());
427                 } else {
428                     children = evaluator.getSchemaReader().getMemberChildren(parent);
429                 }
430                 return children[0];
431             }
432         });
433
434         define(LeadLagFunDef.LagResolver);
435
436         define(new FunDefBase(
437                 "LastChild",
438                 "<Member>.LastChild",
439                 "Returns the last child of a member.",
440                 "pmm") {
441             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
442                 final MemberCalc memberCalc =
443                         compiler.compileMember(call.getArg(0));
444                 return new AbstractMemberCalc(call, new Calc[] {memberCalc}) {
445                     public Member evaluateMember(Evaluator evaluator) {
446                         Member member = memberCalc.evaluateMember(evaluator);
447                         return lastChild(evaluator, member);
448                     }
449                 };
450             }
451
452             Member lastChild(Evaluator evaluator, Member member) {
453                 Member[] children =
454                         evaluator.getSchemaReader().getMemberChildren(member);
455                 return (children.length == 0)
456                         ? member.getHierarchy().getNullMember()
457                         : children[children.length - 1];
458             }
459         });
460
461         define(new FunDefBase(
462                 "LastSibling",
463                 "<Member>.LastSibling",
464                 "Returns the last child of the parent of a member.",
465                 "pmm") {
466             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
467                 final MemberCalc memberCalc =
468                         compiler.compileMember(call.getArg(0));
469                 return new AbstractMemberCalc(call, new Calc[] {memberCalc}) {
470                     public Member evaluateMember(Evaluator evaluator) {
471                         Member member = memberCalc.evaluateMember(evaluator);
472                         return firstSibling(member, evaluator);
473                     }
474                 };
475             }
476
477             Member firstSibling(Member member, Evaluator evaluator) {
478                 Member parent = member.getParentMember();
479                 Member[] children;
480                 final SchemaReader schemaReader = evaluator.getSchemaReader();
481                 if (parent == null) {
482                     if (member.isNull()) {
483                         return member;
484                     }
485                     children = schemaReader.getHierarchyRootMembers(
486                             member.getHierarchy());
487                 } else {
488                     children = schemaReader.getMemberChildren(parent);
489                 }
490                 return children[children.length - 1];
491             }
492         });
493
494         define(LeadLagFunDef.LeadResolver);
495
496         define(new FunDefBase(
497                 "Members",
498                 "Members(<String Expression>)",
499                 "Returns the member whose name is specified by a string expression.",
500                 "fmS") {
501             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
502                 throw new UnsupportedOperationException JavaDoc();
503             }
504         });
505
506         define(new FunDefBase(
507                 "NextMember",
508                 "<Member>.NextMember",
509                 "Returns the next member in the level that contains a specified member.",
510                 "pmm") {
511             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
512                 final MemberCalc memberCalc =
513                         compiler.compileMember(call.getArg(0));
514                 return new AbstractMemberCalc(call, new Calc[] {memberCalc}) {
515                     public Member evaluateMember(Evaluator evaluator) {
516                         Member member = memberCalc.evaluateMember(evaluator);
517                         return evaluator.getSchemaReader().getLeadMember(member, +1);
518                     }
519                 };
520             }
521
522         });
523
524         define(OpeningClosingPeriodFunDef.OpeningPeriodResolver);
525         define(OpeningClosingPeriodFunDef.ClosingPeriodResolver);
526
527         define(ParallelPeriodFunDef.Resolver);
528
529
530         define(new FunDefBase(
531                 "Parent",
532                 "<Member>.Parent",
533                 "Returns the parent of a member.",
534                 "pmm") {
535             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
536                 final MemberCalc memberCalc =
537                         compiler.compileMember(call.getArg(0));
538                 return new AbstractMemberCalc(call, new Calc[] {memberCalc}) {
539                     public Member evaluateMember(Evaluator evaluator) {
540                         Member member = memberCalc.evaluateMember(evaluator);
541                         return memberParent(evaluator, member);
542                     }
543                 };
544             }
545
546             Member memberParent(Evaluator evaluator, Member member) {
547                 Member parent = evaluator.getSchemaReader().getMemberParent(member);
548                 if (parent == null) {
549                     parent = member.getHierarchy().getNullMember();
550                 }
551                 return parent;
552             }
553
554         });
555
556         define(new FunDefBase(
557                 "PrevMember",
558                 "<Member>.PrevMember",
559                 "Returns the previous member in the level that contains a specified member.",
560                 "pmm") {
561             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
562                 final MemberCalc memberCalc =
563                         compiler.compileMember(call.getArg(0));
564                 return new AbstractMemberCalc(call, new Calc[] {memberCalc}) {
565                     public Member evaluateMember(Evaluator evaluator) {
566                         Member member = memberCalc.evaluateMember(evaluator);
567                         return evaluator.getSchemaReader().getLeadMember(member, -1);
568                     }
569                 };
570             }
571         });
572
573         define(new FunDefBase(
574                 "StrToMember",
575                 "StrToMember(<String Expression>)",
576                 "Returns a member from a unique name String in MDX format.",
577                 "fmS") {
578             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
579                 final StringCalc memberNameCalc =
580                         compiler.compileString(call.getArg(0));
581                 return new AbstractMemberCalc(call, new Calc[] {memberNameCalc}) {
582                     public Member evaluateMember(Evaluator evaluator) {
583                         String JavaDoc memberName =
584                                 memberNameCalc.evaluateString(evaluator);
585                         return strToMember(evaluator, memberName);
586                     }
587                 };
588             }
589
590             Member strToMember(Evaluator evaluator, String JavaDoc memberName) {
591                 Cube cube = evaluator.getCube();
592                 SchemaReader schemaReader = evaluator.getSchemaReader();
593                 String JavaDoc[] uniqueNameParts = Util.explode(memberName);
594                 Member member = (Member) schemaReader.lookupCompound(cube,
595                         uniqueNameParts, true, Category.Member);
596                 // Member member = schemaReader.getMemberByUniqueName(uniqueNameParts, false);
597
return member;
598             }
599         });
600
601         define(ValidMeasureFunDef.instance);
602
603         //
604
// NUMERIC FUNCTIONS
605
define(AggregateFunDef.resolver);
606
607         // Obsolete??
608
define(new MultiResolver(
609                 "$AggregateChildren",
610                 "$AggregateChildren(<Hierarchy>)",
611                 "Equivalent to 'Aggregate(<Hierarchy>.CurrentMember.Children); for internal use.",
612                 new String JavaDoc[] {"Inh"}) {
613             protected FunDef createFunDef(Exp[] args, FunDef dummyFunDef) {
614                 return new FunDefBase(dummyFunDef) {
615                     public void unparse(Exp[] args, PrintWriter JavaDoc pw) {
616                         pw.print(getName());
617                         pw.print("(");
618                         args[0].unparse(pw);
619                         pw.print(")");
620                     }
621
622                     public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
623                         final HierarchyCalc hierarchyCalc =
624                                 compiler.compileHierarchy(call.getArg(0));
625                         final Calc valueCalc = new ValueCalc(call);
626                         return new AbstractCalc(call) {
627                             public Object JavaDoc evaluate(Evaluator evaluator) {
628                                 Hierarchy hierarchy =
629                                         hierarchyCalc.evaluateHierarchy(evaluator);
630                                 return aggregateChildren(evaluator, hierarchy, valueCalc);
631                             }
632
633                             public Calc[] getCalcs() {
634                                 return new Calc[] {hierarchyCalc, valueCalc};
635                             }
636                         };
637                     }
638
639                     Object JavaDoc aggregateChildren(
640                             Evaluator evaluator, Hierarchy hierarchy, final Calc valueFunCall) {
641                         Member member = evaluator.getParent().getContext(hierarchy.getDimension());
642                         List members =
643                                 (List) member.getPropertyValue(
644                                         Property.CONTRIBUTING_CHILDREN.name);
645                         Aggregator aggregator =
646                                 (Aggregator) evaluator.getProperty(
647                                         Property.AGGREGATION_TYPE.name, null);
648                         if (aggregator == null) {
649                             throw FunUtil.newEvalException(null, "Could not find an aggregator in the current evaluation context");
650                         }
651                         Aggregator rollup = aggregator.getRollup();
652                         if (rollup == null) {
653                             throw FunUtil.newEvalException(null, "Don't know how to rollup aggregator '" + aggregator + "'");
654                         }
655                         return rollup.aggregate(evaluator.push(), members, valueFunCall);
656                     }
657                 };
658             }
659         });
660
661         define(AvgFunDef.Resolver);
662
663         define(CorrelationFunDef.Resolver);
664
665         define(CountFunDef.Resolver);
666
667         define(new FunDefBase(
668                 "Count",
669                 "<Set>.Count",
670                 "Returns the number of tuples in a set including empty cells.",
671                 "pnx") {
672             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
673                 final ListCalc memberListCalc =
674                         compiler.compileList(call.getArg(0));
675                 return new AbstractIntegerCalc(call, new Calc[] {memberListCalc}) {
676                     public int evaluateInteger(Evaluator evaluator) {
677                         List memberList =
678                                 memberListCalc.evaluateList(evaluator);
679                         return count(evaluator, memberList, true);
680                     }
681                 };
682             }
683         });
684
685         define(CovarianceFunDef.CovarianceResolver);
686         define(CovarianceFunDef.CovarianceNResolver);
687
688         define(new FunDefBase(
689                 "IIf",
690                 "IIf(<Logical Expression>, <String Expression1>, <String Expression2>)",
691                 "Returns one of two string values determined by a logical test.",
692                 "fSbSS") {
693             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
694                 final BooleanCalc booleanCalc =
695                         compiler.compileBoolean(call.getArg(0));
696                 final StringCalc calc1 = compiler.compileString(call.getArg(1));
697                 final StringCalc calc2 = compiler.compileString(call.getArg(2));
698                 return new AbstractStringCalc(call, new Calc[] {booleanCalc, calc1, calc2}) {
699                     public String JavaDoc evaluateString(Evaluator evaluator) {
700                         final boolean b =
701                                 booleanCalc.evaluateBoolean(evaluator);
702                         StringCalc calc = b ? calc1 : calc2;
703                         return calc.evaluateString(evaluator);
704                     }
705                 };
706             }
707         });
708
709         define(new FunDefBase(
710                 "IIf",
711                 "IIf(<Logical Expression>, <Numeric Expression1>, <Numeric Expression2>)",
712                 "Returns one of two numeric values determined by a logical test.",
713                 "fnbnn") {
714             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
715                 final BooleanCalc booleanCalc =
716                         compiler.compileBoolean(call.getArg(0));
717                 final Calc calc1 = compiler.compileScalar(call.getArg(1), true);
718                 final Calc calc2 = compiler.compileScalar(call.getArg(2), true);
719                 return new GenericCalc(call) {
720                     public Object JavaDoc evaluate(Evaluator evaluator) {
721                         final boolean b =
722                                 booleanCalc.evaluateBoolean(evaluator);
723                         Calc calc = b ? calc1 : calc2;
724                         return calc.evaluate(evaluator);
725                     }
726
727                     public Calc[] getCalcs() {
728                         return new Calc[] {booleanCalc, calc1, calc2};
729                     }
730                 };
731             }
732
733         });
734
735         define(LinReg.InterceptResolver);
736         define(LinReg.PointResolver);
737         define(LinReg.R2Resolver);
738         define(LinReg.SlopeResolver);
739         define(LinReg.VarianceResolver);
740
741         define(MinMaxFunDef.MaxResolver);
742
743         define(MedianFunDef.Resolver);
744
745         define(MinMaxFunDef.MinResolver);
746
747         define(new FunDefBase(
748                 "Ordinal",
749                 "<Level>.Ordinal",
750                 "Returns the zero-based ordinal value associated with a level.",
751                 "pnl") {
752             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
753                 final LevelCalc levelCalc =
754                         compiler.compileLevel(call.getArg(0));
755                 return new AbstractIntegerCalc(call, new Calc[] {levelCalc}) {
756                     public int evaluateInteger(Evaluator evaluator) {
757                         final Level level = levelCalc.evaluateLevel(evaluator);
758                         return level.getDepth();
759                     }
760                 };
761             }
762
763         });
764
765         define(RankFunDef.Resolver);
766
767         define(CacheFunDef.Resolver);
768
769         define(StdevFunDef.StdevResolver);
770         define(StdevFunDef.StddevResolver);
771
772         define(StdevPFunDef.StdevpResolver);
773         define(StdevPFunDef.StddevpResolver);
774
775         define(SumFunDef.Resolver);
776
777         define(new FunDefBase(
778                 "Value",
779                 "<Measure>.Value",
780                 "Returns the value of a measure.",
781                 "pnm") {
782             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
783                 final MemberCalc memberCalc =
784                         compiler.compileMember(call.getArg(0));
785                 return new AbstractCalc(call) {
786                     public Object JavaDoc evaluate(Evaluator evaluator) {
787                         Member member = memberCalc.evaluateMember(evaluator);
788                         Member old = evaluator.setContext(member);
789                         Object JavaDoc value = evaluator.evaluateCurrent();
790                         evaluator.setContext(old);
791                         return value;
792                     }
793
794                     public boolean dependsOn(Dimension dimension) {
795                         if (super.dependsOn(dimension)) {
796                             return true;
797                         }
798                         if (memberCalc.getType().usesDimension(dimension, true) ) {
799                             return false;
800                         }
801                         return true;
802                     }
803                     public Calc[] getCalcs() {
804                         return new Calc[] {memberCalc};
805                     }
806                 };
807             }
808
809         });
810
811         define(VarFunDef.VarResolver);
812         define(VarFunDef.VarianceResolver);
813
814         define(VarPFunDef.VariancePResolver);
815         define(VarPFunDef.VarPResolver);
816
817         //
818
// SET FUNCTIONS
819

820         define(AddCalculatedMembersFunDef.resolver);
821
822         define(new FunDefBase(
823                 "Ascendants",
824                 "Ascendants(<Member>)",
825                 "Returns the set of the ascendants of a specified member.",
826                 "fxm") {
827             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
828                 final MemberCalc memberCalc =
829                         compiler.compileMember(call.getArg(0));
830                 return new AbstractListCalc(call, new Calc[] {memberCalc}) {
831                     public List evaluateList(Evaluator evaluator) {
832                         Member member = memberCalc.evaluateMember(evaluator);
833                         return ascendants(member);
834                     }
835                 };
836             }
837
838             List<Member> ascendants(Member member) {
839                 if (member.isNull()) {
840                     return Collections.emptyList();
841                 }
842                 Member[] members = member.getAncestorMembers();
843                 final List<Member> result =
844                     new ArrayList<Member>(members.length + 1);
845                 result.add(member);
846                 XOMUtil.addAll(result, members);
847                 return result;
848             }
849         });
850
851         define(TopBottomCountFunDef.BottomCountResolver);
852         define(TopBottomPercentSumFunDef.BottomPercentResolver);
853         define(TopBottomPercentSumFunDef.BottomSumResolver);
854         define(TopBottomCountFunDef.TopCountResolver);
855         define(TopBottomPercentSumFunDef.TopPercentResolver);
856         define(TopBottomPercentSumFunDef.TopSumResolver);
857
858         define(new FunDefBase(
859                 "Children",
860                 "<Member>.Children",
861                 "Returns the children of a member.",
862                 "pxm") {
863             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
864                 final MemberCalc memberCalc =
865                         compiler.compileMember(call.getArg(0));
866                 return new AbstractListCalc(call, new Calc[] {memberCalc}, false) {
867                     public List evaluateList(Evaluator evaluator) {
868                         // Return the list of children. The list is immutable,
869
// hence 'false' above.
870
Member member = memberCalc.evaluateMember(evaluator);
871                         Member[] children = getNonEmptyMemberChildren(evaluator, member);
872                         return Arrays.asList(children);
873                     }
874                 };
875             }
876
877         });
878
879         define(CrossJoinFunDef.Resolver);
880
881         define(NonEmptyCrossJoinFunDef.Resolver);
882
883         define(CrossJoinFunDef.StarResolver);
884
885         define(DescendantsFunDef.Resolver);
886
887         define(new FunDefBase(
888                 "Distinct",
889                 "Distinct(<Set>)",
890                 "Eliminates duplicate tuples from a set.",
891                 "fxx") {
892             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
893                 final ListCalc listCalc =
894                         compiler.compileList(call.getArg(0));
895                 return new AbstractListCalc(call, new Calc[] {listCalc}) {
896                     public List evaluateList(Evaluator evaluator) {
897                         List list = listCalc.evaluateList(evaluator);
898                         return distinct(list);
899                     }
900                 };
901             }
902
903             List<Object JavaDoc> distinct(List list) {
904                 Set<MemberHelper> set = new HashSet<MemberHelper>(list.size());
905                 List<Object JavaDoc> result = new ArrayList<Object JavaDoc>();
906
907                 for (Object JavaDoc element : list) {
908                     MemberHelper lookupObj = new MemberHelper(element);
909
910                     if (set.add(lookupObj)) {
911                         result.add(element);
912                     }
913                 }
914                 return result;
915             }
916         });
917
918         define(DrilldownLevelFunDef.Resolver);
919
920         if (false) define(new FunDefBase(
921                 "DrilldownLevelBottom",
922                 "DrilldownLevelBottom(<Set>, <Count>[, [<Level>][, <Numeric Expression>]])",
923                 "Drills down the bottom N members of a set, at a specified level, to one level below.",
924                 "fx*") {
925             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
926                 throw new UnsupportedOperationException JavaDoc();
927             }
928         });
929
930         if (false) define(new FunDefBase(
931                 "DrilldownLevelTop",
932                 "DrilldownLevelTop(<Set>, <Count>[, [<Level>][, <Numeric Expression>]])",
933                 "Drills down the top N members of a set, at a specified level, to one level below.",
934                 "fx*") {
935             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
936                 throw new UnsupportedOperationException JavaDoc();
937             }
938         });
939
940         define(DrilldownMemberFunDef.Resolver);
941
942         if (false) define(new FunDefBase(
943                 "DrilldownMemberBottom",
944                 "DrilldownMemberBottom(<Set1>, <Set2>, <Count>[, [<Numeric Expression>][, RECURSIVE]])",
945                 "Like DrilldownMember except that it includes only the bottom N children.",
946                 "fx*") {
947             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
948                 throw new UnsupportedOperationException JavaDoc();
949             }
950         });
951
952         if (false) define(new FunDefBase(
953                 "DrilldownMemberTop",
954                 "DrilldownMemberTop(<Set1>, <Set2>, <Count>[, [<Numeric Expression>][, RECURSIVE]])",
955                 "Like DrilldownMember except that it includes only the top N children.",
956                 "fx*") {
957             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
958                 throw new UnsupportedOperationException JavaDoc();
959             }
960         });
961
962         if (false) define(new FunDefBase(
963                 "DrillupLevel",
964                 "DrillupLevel(<Set>[, <Level>])",
965                 "Drills up the members of a set that are below a specified level.",
966                 "fx*") {
967             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
968                 throw new UnsupportedOperationException JavaDoc();
969             }
970         });
971
972         if (false) define(new FunDefBase(
973                 "DrillupMember",
974                 "DrillupMember(<Set1>, <Set2>)",
975                 "Drills up the members in a set that are present in a second specified set.",
976                 "fx*") {
977             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
978                 throw new UnsupportedOperationException JavaDoc();
979             }
980         });
981
982         define(ExceptFunDef.Resolver);
983
984         if (false) define(new FunDefBase(
985                 "Extract",
986                 "Extract(<Set>, <Dimension>[, <Dimension>...])",
987                 "Returns a set of tuples from extracted dimension elements. The opposite of Crossjoin.",
988                 "fx*") {
989             public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
990                 throw new UnsupportedOperationException JavaDoc();
991             }
992         });
993
994         define(FilterFunDef.instance);
995
996         define(GenerateFunDef.ListResolver);
997         define(GenerateFunDef.StringResolver);
998         define(HeadTailFunDef.HeadResolver);
999
1000        define(HierarchizeFunDef.Resolver);
1001
1002        define(IntersectFunDef.resolver);
1003        define(LastPeriodsFunDef.Resolver);
1004
1005        define(new FunDefBase(
1006                "Members",
1007                "<Dimension>.Members",
1008                "Returns the set of members in a dimension.",
1009                "pxd") {
1010            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1011                final DimensionCalc dimensionCalc =
1012                        compiler.compileDimension(call.getArg(0));
1013                return new AbstractListCalc(call, new Calc[] {dimensionCalc}) {
1014                    public List evaluateList(Evaluator evaluator) {
1015                        Dimension dimension =
1016                                dimensionCalc.evaluateDimension(evaluator);
1017                        return dimensionMembers(dimension, evaluator, false);
1018                    }
1019                };
1020            }
1021
1022        });
1023
1024        define(new FunDefBase(
1025                "AllMembers",
1026                "<Dimension>.AllMembers",
1027                "Returns a set that contains all members, including calculated members, of the specified dimension.",
1028                "pxd") {
1029            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1030                final DimensionCalc dimensionCalc =
1031                        compiler.compileDimension(call.getArg(0));
1032                return new AbstractListCalc(call, new Calc[] {dimensionCalc}) {
1033                    public List evaluateList(Evaluator evaluator) {
1034                        Dimension dimension =
1035                                dimensionCalc.evaluateDimension(evaluator);
1036                        return dimensionMembers(dimension, evaluator, true);
1037                    }
1038                };
1039            }
1040
1041        });
1042
1043        define(new FunDefBase(
1044                "Members",
1045                "<Hierarchy>.Members",
1046                "Returns the set of members in a hierarchy.",
1047                "pxh") {
1048            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1049                final HierarchyCalc hierarchyCalc =
1050                        compiler.compileHierarchy(call.getArg(0));
1051                return new AbstractListCalc(call, new Calc[] {hierarchyCalc}) {
1052                    public List evaluateList(Evaluator evaluator) {
1053                        Hierarchy hierarchy =
1054                                hierarchyCalc.evaluateHierarchy(evaluator);
1055                        return hierarchyMembers(hierarchy, evaluator, false);
1056                    }
1057                };
1058            }
1059
1060        });
1061
1062        define(new FunDefBase(
1063                "AllMembers",
1064                "<Hierarchy>.AllMembers",
1065                "Returns a set that contains all members, including calculated members, of the specified hierarchy.",
1066                "pxh") {
1067            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1068                final HierarchyCalc hierarchyCalc =
1069                        compiler.compileHierarchy(call.getArg(0));
1070                return new AbstractListCalc(call, new Calc[] {hierarchyCalc}) {
1071                    public List evaluateList(Evaluator evaluator) {
1072                        Hierarchy hierarchy =
1073                                hierarchyCalc.evaluateHierarchy(evaluator);
1074                        return hierarchyMembers(hierarchy, evaluator, true);
1075                    }
1076                };
1077            }
1078        });
1079
1080        define(new FunDefBase(
1081                "Members",
1082                "<Level>.Members",
1083                "Returns the set of members in a level.",
1084                "pxl") {
1085            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1086                final LevelCalc levelCalc =
1087                        compiler.compileLevel(call.getArg(0));
1088                return new AbstractListCalc(call, new Calc[] {levelCalc}) {
1089                    public List evaluateList(Evaluator evaluator) {
1090                        Level level = levelCalc.evaluateLevel(evaluator);
1091                        return levelMembers(level, evaluator, false);
1092                    }
1093                };
1094            }
1095        });
1096
1097        define(new FunDefBase(
1098                "AllMembers",
1099                "<Level>.AllMembers",
1100                "Returns a set that contains all members, including calculated members, of the specified level.",
1101                "pxl") {
1102            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1103                final LevelCalc levelCalc =
1104                        compiler.compileLevel(call.getArg(0));
1105                return new AbstractListCalc(call, new Calc[] {levelCalc}) {
1106                    public List evaluateList(Evaluator evaluator) {
1107                        Level level = levelCalc.evaluateLevel(evaluator);
1108                        return levelMembers(level, evaluator, true);
1109                    }
1110                };
1111            }
1112        });
1113
1114        define(XtdFunDef.MtdResolver);
1115        define(OrderFunDef.Resolver);
1116        define(PeriodsToDateFunDef.Resolver);
1117        define(XtdFunDef.QtdResolver);
1118
1119        define(new FunDefBase(
1120                "StripCalculatedMembers",
1121                "StripCalculatedMembers(<Set>)",
1122                "Removes calculated members from a set.",
1123                "fxx") {
1124            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1125                final ListCalc listCalc =
1126                        compiler.compileList(call.getArg(0));
1127                return new AbstractListCalc(call, new Calc[] {listCalc}) {
1128                    public List evaluateList(Evaluator evaluator) {
1129                        final List<Member> list = listCalc.evaluateList(evaluator);
1130                        removeCalculatedMembers(list);
1131                        return list;
1132                    }
1133                };
1134            }
1135
1136        });
1137
1138        define(new FunDefBase(
1139                "Siblings",
1140                "<Member>.Siblings",
1141                "Returns the siblings of a specified member, including the member itself.",
1142                "pxm") {
1143            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1144                final MemberCalc memberCalc =
1145                        compiler.compileMember(call.getArg(0));
1146                return new AbstractListCalc(call, new Calc[] {memberCalc}) {
1147                    public List evaluateList(Evaluator evaluator) {
1148                        final Member member =
1149                                memberCalc.evaluateMember(evaluator);
1150                        return memberSiblings(member, evaluator);
1151                    }
1152                };
1153            }
1154
1155            List memberSiblings(Member member, Evaluator evaluator) {
1156                if (member.isNull()) {
1157                    // the null member has no siblings -- not even itself
1158
return Collections.EMPTY_LIST;
1159                }
1160                Member parent = member.getParentMember();
1161                final SchemaReader schemaReader = evaluator.getSchemaReader();
1162                Member[] siblings = (parent == null)
1163                    ? schemaReader.getHierarchyRootMembers(member.getHierarchy())
1164                    : schemaReader.getMemberChildren(parent);
1165
1166                return Arrays.asList(siblings);
1167            }
1168        });
1169
1170        define(StrToSetFunDef.Resolver);
1171        define(SubsetFunDef.Resolver);
1172        define(HeadTailFunDef.TailResolver);
1173        define(ToggleDrillStateFunDef.Resolver);
1174        define(UnionFunDef.Resolver);
1175        define(VisualTotalsFunDef.Resolver);
1176        define(XtdFunDef.WtdResolver);
1177        define(XtdFunDef.YtdResolver);
1178        define(RangeFunDef.instance); // "<member> : <member>" operator
1179
define(SetFunDef.Resolver); // "{ <member> [,...] }" operator
1180

1181        //
1182
// STRING FUNCTIONS
1183
define(FormatFunDef.Resolver);
1184
1185        define(new FunDefBase(
1186                "Caption",
1187                "<Dimension>.Caption",
1188                "Returns the caption of a dimension.",
1189                "pSd") {
1190            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1191                final DimensionCalc dimensionCalc =
1192                        compiler.compileDimension(call.getArg(0));
1193                return new AbstractStringCalc(call, new Calc[] {dimensionCalc}) {
1194                    public String JavaDoc evaluateString(Evaluator evaluator) {
1195                        final Dimension dimension =
1196                                dimensionCalc.evaluateDimension(evaluator);
1197                        return dimension.getCaption();
1198                    }
1199                };
1200            }
1201        });
1202
1203        define(new FunDefBase(
1204                "Caption",
1205                "<Hierarchy>.Caption",
1206                "Returns the caption of a hierarchy.",
1207                "pSh") {
1208            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1209                final HierarchyCalc hierarchyCalc =
1210                        compiler.compileHierarchy(call.getArg(0));
1211                return new AbstractStringCalc(call, new Calc[] {hierarchyCalc}) {
1212                    public String JavaDoc evaluateString(Evaluator evaluator) {
1213                        final Hierarchy hierarchy =
1214                                hierarchyCalc.evaluateHierarchy(evaluator);
1215                        return hierarchy.getCaption();
1216                    }
1217                };
1218            }
1219
1220        });
1221
1222        define(new FunDefBase(
1223                "Caption",
1224                "<Level>.Caption",
1225                "Returns the caption of a level.",
1226                "pSl") {
1227            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1228                final LevelCalc levelCalc =
1229                        compiler.compileLevel(call.getArg(0));
1230                return new AbstractStringCalc(call, new Calc[] {levelCalc}) {
1231                    public String JavaDoc evaluateString(Evaluator evaluator) {
1232                        final Level level = levelCalc.evaluateLevel(evaluator);
1233                        return level.getCaption();
1234                    }
1235                };
1236            }
1237        });
1238
1239        define(new FunDefBase(
1240                "Caption",
1241                "<Member>.Caption",
1242                "Returns the caption of a member.",
1243                "pSm") {
1244            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1245                final MemberCalc memberCalc =
1246                        compiler.compileMember(call.getArg(0));
1247                return new AbstractStringCalc(call, new Calc[] {memberCalc}) {
1248                    public String JavaDoc evaluateString(Evaluator evaluator) {
1249                        final Member member =
1250                                memberCalc.evaluateMember(evaluator);
1251                        return member.getCaption();
1252                    }
1253                };
1254            }
1255        });
1256
1257        define(new FunDefBase(
1258                "Name",
1259                "<Dimension>.Name",
1260                "Returns the name of a dimension.",
1261                "pSd") {
1262            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1263                final DimensionCalc dimensionCalc =
1264                        compiler.compileDimension(call.getArg(0));
1265                return new AbstractStringCalc(call, new Calc[] {dimensionCalc}) {
1266                    public String JavaDoc evaluateString(Evaluator evaluator) {
1267                        final Dimension dimension =
1268                                dimensionCalc.evaluateDimension(evaluator);
1269                        return dimension.getName();
1270                    }
1271                };
1272            }
1273        });
1274
1275        define(new FunDefBase(
1276                "Name",
1277                "<Hierarchy>.Name",
1278                "Returns the name of a hierarchy.",
1279                "pSh") {
1280            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1281                final HierarchyCalc hierarchyCalc =
1282                        compiler.compileHierarchy(call.getArg(0));
1283                return new AbstractStringCalc(call, new Calc[] {hierarchyCalc}) {
1284                    public String JavaDoc evaluateString(Evaluator evaluator) {
1285                        final Hierarchy hierarchy =
1286                                hierarchyCalc.evaluateHierarchy(evaluator);
1287                        return hierarchy.getName();
1288                    }
1289                };
1290            }
1291        });
1292
1293        define(new FunDefBase(
1294                "Name",
1295                "<Level>.Name",
1296                "Returns the name of a level.",
1297                "pSl") {
1298            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1299                final LevelCalc levelCalc =
1300                        compiler.compileLevel(call.getArg(0));
1301                return new AbstractStringCalc(call, new Calc[] {levelCalc}) {
1302                    public String JavaDoc evaluateString(Evaluator evaluator) {
1303                        final Level level = levelCalc.evaluateLevel(evaluator);
1304                        return level.getName();
1305                    }
1306                };
1307            }
1308        });
1309
1310        define(new FunDefBase(
1311                "Name",
1312                "<Member>.Name",
1313                "Returns the name of a member.",
1314                "pSm") {
1315            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1316                final MemberCalc memberCalc =
1317                        compiler.compileMember(call.getArg(0));
1318                return new AbstractStringCalc(call, new Calc[] {memberCalc}) {
1319                    public String JavaDoc evaluateString(Evaluator evaluator) {
1320                        final Member member =
1321                                memberCalc.evaluateMember(evaluator);
1322                        return member.getName();
1323                    }
1324                };
1325            }
1326        });
1327
1328        define(SetToStrFunDef.instance);
1329
1330        define(TupleToStrFunDef.instance);
1331
1332        define(new FunDefBase(
1333                "UniqueName",
1334                "<Dimension>.UniqueName",
1335                "Returns the unique name of a dimension.",
1336                "pSd") {
1337            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1338                final DimensionCalc dimensionCalc =
1339                        compiler.compileDimension(call.getArg(0));
1340                return new AbstractStringCalc(call, new Calc[] {dimensionCalc}) {
1341                    public String JavaDoc evaluateString(Evaluator evaluator) {
1342                        final Dimension dimension =
1343                                dimensionCalc.evaluateDimension(evaluator);
1344                        return dimension.getUniqueName();
1345                    }
1346                };
1347            }
1348        });
1349
1350        define(new FunDefBase(
1351                "UniqueName",
1352                "<Hierarchy>.UniqueName",
1353                "Returns the unique name of a hierarchy.",
1354                "pSh") {
1355            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1356                final HierarchyCalc hierarchyCalc =
1357                        compiler.compileHierarchy(call.getArg(0));
1358                return new AbstractStringCalc(call, new Calc[] {hierarchyCalc}) {
1359                    public String JavaDoc evaluateString(Evaluator evaluator) {
1360                        final Hierarchy hierarchy =
1361                                hierarchyCalc.evaluateHierarchy(evaluator);
1362                        return hierarchy.getUniqueName();
1363                    }
1364                };
1365            }
1366        });
1367
1368        define(new FunDefBase(
1369                "UniqueName",
1370                "<Level>.UniqueName",
1371                "Returns the unique name of a level.",
1372                "pSl") {
1373            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1374                final LevelCalc levelCalc =
1375                        compiler.compileLevel(call.getArg(0));
1376                return new AbstractStringCalc(call, new Calc[] {levelCalc}) {
1377                    public String JavaDoc evaluateString(Evaluator evaluator) {
1378                        final Level level = levelCalc.evaluateLevel(evaluator);
1379                        return level.getUniqueName();
1380                    }
1381                };
1382            }
1383        });
1384
1385        define(new FunDefBase(
1386                "UniqueName",
1387                "<Member>.UniqueName",
1388                "Returns the unique name of a member.",
1389                "pSm") {
1390            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1391                final MemberCalc memberCalc =
1392                        compiler.compileMember(call.getArg(0));
1393                return new AbstractStringCalc(call, new Calc[] {memberCalc}) {
1394                    public String JavaDoc evaluateString(Evaluator evaluator) {
1395                        final Member member =
1396                                memberCalc.evaluateMember(evaluator);
1397                        return member.getUniqueName();
1398                    }
1399                };
1400            }
1401        });
1402
1403        //
1404
// TUPLE FUNCTIONS
1405
if (false) define(new FunDefBase(
1406                "Current",
1407                "<Set>.Current",
1408                "Returns the current tuple from a set during an iteration.",
1409                "ptx") {
1410            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1411                throw new UnsupportedOperationException JavaDoc();
1412            }
1413        });
1414
1415        // we do not support the <String expression> arguments
1416
if (false) define(new FunDefBase(
1417                "Item",
1418                "<Set>.Item(<String Expression>[, <String Expression>...] | <Index>)",
1419                "Returns a tuple from a set.",
1420                "mx*") {
1421            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1422                throw new UnsupportedOperationException JavaDoc();
1423            }
1424        });
1425
1426        define(SetItemFunDef.intResolver);
1427        define(SetItemFunDef.stringResolver);
1428        define(TupleItemFunDef.instance);
1429        define(StrToTupleFunDef.Resolver);
1430
1431        // special resolver for "()"
1432
define(TupleFunDef.Resolver);
1433
1434        //
1435
// GENERIC VALUE FUNCTIONS
1436
define(CoalesceEmptyFunDef.Resolver);
1437        define(CaseTestFunDef.Resolver);
1438        define(CaseMatchFunDef.Resolver);
1439        define(PropertiesFunDef.Resolver);
1440
1441        //
1442
// PARAMETER FUNCTIONS
1443
define(new ParameterFunDef.ParameterResolver());
1444        define(new ParameterFunDef.ParamRefResolver());
1445
1446        //
1447
// OPERATORS
1448
define(new FunDefBase(
1449                "+",
1450                "<Numeric Expression> + <Numeric Expression>",
1451                "Adds two numbers.",
1452                "innn") {
1453            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1454                final DoubleCalc calc0 = compiler.compileDouble(call.getArg(0));
1455                final DoubleCalc calc1 = compiler.compileDouble(call.getArg(1));
1456                return new AbstractDoubleCalc(call, new Calc[] {calc0, calc1}) {
1457                    public double evaluateDouble(Evaluator evaluator) {
1458                        final double v0 = calc0.evaluateDouble(evaluator);
1459                        final double v1 = calc1.evaluateDouble(evaluator);
1460                        if (v0 == DoubleNull) {
1461                            if (v1 == DoubleNull) {
1462                                return DoubleNull;
1463                            } else {
1464                                return v1;
1465                            }
1466                        } else {
1467                            if (v1 == DoubleNull) {
1468                                return v0;
1469                            } else {
1470                                return v0 + v1;
1471                            }
1472                        }
1473                    }
1474                };
1475            }
1476
1477        });
1478
1479        define(new FunDefBase(
1480                "-",
1481                "<Numeric Expression> - <Numeric Expression>",
1482                "Subtracts two numbers.",
1483                "innn") {
1484            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1485                final DoubleCalc calc0 = compiler.compileDouble(call.getArg(0));
1486                final DoubleCalc calc1 = compiler.compileDouble(call.getArg(1));
1487                return new AbstractDoubleCalc(call, new Calc[] {calc0, calc1}) {
1488                    public double evaluateDouble(Evaluator evaluator) {
1489                        final double v0 = calc0.evaluateDouble(evaluator);
1490                        final double v1 = calc1.evaluateDouble(evaluator);
1491                        if (v0 == DoubleNull) {
1492                            if (v1 == DoubleNull) {
1493                                return DoubleNull;
1494                            } else {
1495                                return - v1;
1496                            }
1497                        } else {
1498                            if (v1 == DoubleNull) {
1499                                return v0;
1500                            } else {
1501                                return v0 - v1;
1502                            }
1503                        }
1504                    }
1505                };
1506            }
1507        });
1508
1509        define(new FunDefBase(
1510                "*",
1511                "<Numeric Expression> * <Numeric Expression>",
1512                "Multiplies two numbers.",
1513                "innn") {
1514            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1515                final DoubleCalc calc0 = compiler.compileDouble(call.getArg(0));
1516                final DoubleCalc calc1 = compiler.compileDouble(call.getArg(1));
1517                return new AbstractDoubleCalc(call, new Calc[] {calc0, calc1}) {
1518                    public double evaluateDouble(Evaluator evaluator) {
1519                        final double v0 = calc0.evaluateDouble(evaluator);
1520                        final double v1 = calc1.evaluateDouble(evaluator);
1521                        // Multiply and divide return null if EITHER arg is null.
1522
if (v0 == DoubleNull || v1 == DoubleNull) {
1523                            return DoubleNull;
1524                        } else {
1525                            return v0 * v1;
1526                        }
1527                    }
1528                };
1529            }
1530        });
1531
1532        define(new FunDefBase(
1533                "/",
1534                "<Numeric Expression> / <Numeric Expression>",
1535                "Divides two numbers.",
1536                "innn") {
1537            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1538                final DoubleCalc calc0 = compiler.compileDouble(call.getArg(0));
1539                final DoubleCalc calc1 = compiler.compileDouble(call.getArg(1));
1540                return new AbstractDoubleCalc(call, new Calc[] {calc0, calc1}) {
1541                    public double evaluateDouble(Evaluator evaluator) {
1542                        final double v0 = calc0.evaluateDouble(evaluator);
1543                        final double v1 = calc1.evaluateDouble(evaluator);
1544                        // Multiply and divide return null if EITHER arg is null.
1545
if (v0 == DoubleNull || v1 == DoubleNull) {
1546                            return DoubleNull;
1547                        } else {
1548                            return v0 / v1;
1549                        }
1550                    }
1551                };
1552            }
1553
1554            // todo: use this, via reflection
1555
public double evaluate(double d1, double d2) {
1556                return d1 / d2;
1557            }
1558        });
1559
1560        define(new FunDefBase(
1561                "-",
1562                "- <Numeric Expression>",
1563                "Returns the negative of a number.",
1564                "Pnn") {
1565            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1566                final DoubleCalc calc = compiler.compileDouble(call.getArg(0));
1567                return new AbstractDoubleCalc(call, new Calc[] {calc}) {
1568                    public double evaluateDouble(Evaluator evaluator) {
1569                        final double v = calc.evaluateDouble(evaluator);
1570                        if (v == DoubleNull) {
1571                            return DoubleNull;
1572                        } else {
1573                            return - v;
1574                        }
1575                    }
1576                };
1577            }
1578        });
1579
1580        define(new FunDefBase(
1581                "||",
1582                "<String Expression> || <String Expression>",
1583                "Concatenates two strings.",
1584                "iSSS") {
1585            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1586                final StringCalc calc0 = compiler.compileString(call.getArg(0));
1587                final StringCalc calc1 = compiler.compileString(call.getArg(1));
1588                return new AbstractStringCalc(call, new Calc[] {calc0, calc1}) {
1589                    public String JavaDoc evaluateString(Evaluator evaluator) {
1590                        final String JavaDoc s0 = calc0.evaluateString(evaluator);
1591                        final String JavaDoc s1 = calc1.evaluateString(evaluator);
1592                        return s0 + s1;
1593                    }
1594                };
1595            }
1596
1597        });
1598
1599        define(new FunDefBase(
1600                "AND",
1601                "<Logical Expression> AND <Logical Expression>",
1602                "Returns the conjunction of two conditions.",
1603                "ibbb") {
1604            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1605                final BooleanCalc calc0 = compiler.compileBoolean(call.getArg(0));
1606                final BooleanCalc calc1 = compiler.compileBoolean(call.getArg(1));
1607                return new AbstractBooleanCalc(call, new Calc[] {calc0, calc1}) {
1608                    public boolean evaluateBoolean(Evaluator evaluator) {
1609                        boolean b0 = calc0.evaluateBoolean(evaluator);
1610                        // don't short-circuit evaluation if we're evaluating
1611
// the axes; that way, we can combine all measures
1612
// referenced in the AND expression in a single query
1613
if (!evaluator.isEvalAxes() && !b0) {
1614                            return false;
1615                        }
1616                        boolean b1 = calc1.evaluateBoolean(evaluator);
1617                        return b0 && b1;
1618                    }
1619                };
1620            }
1621        });
1622
1623        define(new FunDefBase(
1624                "OR",
1625                "<Logical Expression> OR <Logical Expression>",
1626                "Returns the disjunction of two conditions.",
1627                "ibbb") {
1628            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1629                final BooleanCalc calc0 = compiler.compileBoolean(call.getArg(0));
1630                final BooleanCalc calc1 = compiler.compileBoolean(call.getArg(1));
1631                return new AbstractBooleanCalc(call, new Calc[] {calc0, calc1}) {
1632                    public boolean evaluateBoolean(Evaluator evaluator) {
1633                        boolean b0 = calc0.evaluateBoolean(evaluator);
1634                        // don't short-circuit evaluation if we're evaluating
1635
// the axes; that way, we can combine all measures
1636
// referenced in the OR expression in a single query
1637
if (!evaluator.isEvalAxes() && b0) {
1638                            return true;
1639                        }
1640                        boolean b1 = calc1.evaluateBoolean(evaluator);
1641                        return b0 || b1;
1642                    }
1643                };
1644            }
1645        });
1646
1647        define(new FunDefBase(
1648                "XOR",
1649                "<Logical Expression> XOR <Logical Expression>",
1650                "Returns whether two conditions are mutually exclusive.",
1651                "ibbb") {
1652            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1653                final BooleanCalc calc0 = compiler.compileBoolean(call.getArg(0));
1654                final BooleanCalc calc1 = compiler.compileBoolean(call.getArg(1));
1655                return new AbstractBooleanCalc(call, new Calc[] {calc0, calc1}) {
1656                    public boolean evaluateBoolean(Evaluator evaluator) {
1657                        final boolean b0 = calc0.evaluateBoolean(evaluator);
1658                        final boolean b1 = calc1.evaluateBoolean(evaluator);
1659                        return b0 != b1;
1660                    }
1661                };
1662            }
1663        });
1664
1665        define(new FunDefBase(
1666                "NOT",
1667                "NOT <Logical Expression>",
1668                "Returns the negation of a condition.",
1669                "Pbb") {
1670            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1671                final BooleanCalc calc = compiler.compileBoolean(call.getArg(0));
1672                return new AbstractBooleanCalc(call, new Calc[] {calc}) {
1673                    public boolean evaluateBoolean(Evaluator evaluator) {
1674                        return !calc.evaluateBoolean(evaluator);
1675                    }
1676                };
1677            }
1678        });
1679
1680        define(new FunDefBase(
1681                "=",
1682                "<String Expression> = <String Expression>",
1683                "Returns whether two expressions are equal.",
1684                "ibSS") {
1685            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1686                final StringCalc calc0 = compiler.compileString(call.getArg(0));
1687                final StringCalc calc1 = compiler.compileString(call.getArg(1));
1688                return new AbstractBooleanCalc(call, new Calc[] {calc0, calc1}) {
1689                    public boolean evaluateBoolean(Evaluator evaluator) {
1690                        final String JavaDoc b0 = calc0.evaluateString(evaluator);
1691                        final String JavaDoc b1 = calc1.evaluateString(evaluator);
1692                        if (b0 == null || b1 == null) {
1693                            return BooleanNull;
1694                        }
1695                        return b0.equals(b1);
1696                    }
1697                };
1698            }
1699        });
1700
1701        define(new FunDefBase(
1702                "=",
1703                "<Numeric Expression> = <Numeric Expression>",
1704                "Returns whether two expressions are equal.",
1705                "ibnn") {
1706            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1707                final DoubleCalc calc0 = compiler.compileDouble(call.getArg(0));
1708                final DoubleCalc calc1 = compiler.compileDouble(call.getArg(1));
1709                return new AbstractBooleanCalc(call, new Calc[] {calc0, calc1}) {
1710                    public boolean evaluateBoolean(Evaluator evaluator) {
1711                        final double v0 = calc0.evaluateDouble(evaluator);
1712                        final double v1 = calc1.evaluateDouble(evaluator);
1713                        if (v0 == Double.NaN || v1 == Double.NaN || v0 == DoubleNull || v1 == DoubleNull) {
1714                            return BooleanNull;
1715                        }
1716                        return v0 == v1;
1717                    }
1718                };
1719            }
1720        });
1721
1722        define(new FunDefBase(
1723                "<>",
1724                "<String Expression> <> <String Expression>",
1725                "Returns whether two expressions are not equal.",
1726                "ibSS") {
1727            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1728                final StringCalc calc0 = compiler.compileString(call.getArg(0));
1729                final StringCalc calc1 = compiler.compileString(call.getArg(1));
1730                return new AbstractBooleanCalc(call, new Calc[] {calc0, calc1}) {
1731                    public boolean evaluateBoolean(Evaluator evaluator) {
1732                        final String JavaDoc b0 = calc0.evaluateString(evaluator);
1733                        final String JavaDoc b1 = calc1.evaluateString(evaluator);
1734                        if (b0 == null || b1 == null) {
1735                            return BooleanNull;
1736                        }
1737                        return !b0.equals(b1);
1738                    }
1739                };
1740            }
1741        });
1742
1743        define(new FunDefBase(
1744                "<>",
1745                "<Numeric Expression> <> <Numeric Expression>",
1746                "Returns whether two expressions are not equal.",
1747                "ibnn") {
1748            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1749                final DoubleCalc calc0 = compiler.compileDouble(call.getArg(0));
1750                final DoubleCalc calc1 = compiler.compileDouble(call.getArg(1));
1751                return new AbstractBooleanCalc(call, new Calc[] {calc0, calc1}) {
1752                    public boolean evaluateBoolean(Evaluator evaluator) {
1753                        final double v0 = calc0.evaluateDouble(evaluator);
1754                        final double v1 = calc1.evaluateDouble(evaluator);
1755                        if (v0 == Double.NaN || v1 == Double.NaN || v0 == DoubleNull || v1 == DoubleNull) {
1756                            return BooleanNull;
1757                        }
1758                        return v0 != v1;
1759                    }
1760                };
1761            }
1762        });
1763
1764        define(new FunDefBase(
1765                "<",
1766                "<Numeric Expression> < <Numeric Expression>",
1767                "Returns whether an expression is less than another.",
1768                "ibnn") {
1769            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1770                final DoubleCalc calc0 = compiler.compileDouble(call.getArg(0));
1771                final DoubleCalc calc1 = compiler.compileDouble(call.getArg(1));
1772                return new AbstractBooleanCalc(call, new Calc[] {calc0, calc1}) {
1773                    public boolean evaluateBoolean(Evaluator evaluator) {
1774                        final double v0 = calc0.evaluateDouble(evaluator);
1775                        final double v1 = calc1.evaluateDouble(evaluator);
1776                        if (v0 == Double.NaN || v1 == Double.NaN || v0 == DoubleNull || v1 == DoubleNull) {
1777                            return BooleanNull;
1778                        }
1779                        return v0 < v1;
1780                    }
1781                };
1782            }
1783        });
1784
1785        define(new FunDefBase(
1786                "<",
1787                "<String Expression> < <String Expression>",
1788                "Returns whether an expression is less than another.",
1789                "ibSS") {
1790            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1791                final StringCalc calc0 = compiler.compileString(call.getArg(0));
1792                final StringCalc calc1 = compiler.compileString(call.getArg(1));
1793                return new AbstractBooleanCalc(call, new Calc[] {calc0, calc1}) {
1794                    public boolean evaluateBoolean(Evaluator evaluator) {
1795                        final String JavaDoc b0 = calc0.evaluateString(evaluator);
1796                        final String JavaDoc b1 = calc1.evaluateString(evaluator);
1797                        if (b0 == null || b1 == null) {
1798                            return BooleanNull;
1799                        }
1800                        return b0.compareTo(b1) < 0;
1801                    }
1802                };
1803            }
1804        });
1805
1806        define(new FunDefBase(
1807                "<=",
1808                "<Numeric Expression> <= <Numeric Expression>",
1809                "Returns whether an expression is less than or equal to another.",
1810                "ibnn") {
1811            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1812                final DoubleCalc calc0 = compiler.compileDouble(call.getArg(0));
1813                final DoubleCalc calc1 = compiler.compileDouble(call.getArg(1));
1814                return new AbstractBooleanCalc(call, new Calc[] {calc0, calc1}) {
1815                    public boolean evaluateBoolean(Evaluator evaluator) {
1816                        final double v0 = calc0.evaluateDouble(evaluator);
1817                        final double v1 = calc1.evaluateDouble(evaluator);
1818                        if (v0 == Double.NaN || v1 == Double.NaN || v0 == DoubleNull || v1 == DoubleNull) {
1819                            return BooleanNull;
1820                        }
1821                        return v0 <= v1;
1822                    }
1823                };
1824            }
1825        });
1826
1827        define(new FunDefBase(
1828                "<=",
1829                "<String Expression> <= <String Expression>",
1830                "Returns whether an expression is less than or equal to another.",
1831                "ibSS") {
1832            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1833                final StringCalc calc0 = compiler.compileString(call.getArg(0));
1834                final StringCalc calc1 = compiler.compileString(call.getArg(1));
1835                return new AbstractBooleanCalc(call, new Calc[] {calc0, calc1}) {
1836                    public boolean evaluateBoolean(Evaluator evaluator) {
1837                        final String JavaDoc b0 = calc0.evaluateString(evaluator);
1838                        final String JavaDoc b1 = calc1.evaluateString(evaluator);
1839                        if (b0 == null || b1 == null) {
1840                            return BooleanNull;
1841                        }
1842                        return b0.compareTo(b1) <= 0;
1843                    }
1844                };
1845            }
1846        });
1847
1848        define(new FunDefBase(
1849                ">",
1850                "<Numeric Expression> > <Numeric Expression>",
1851                "Returns whether an expression is greater than another.",
1852                "ibnn") {
1853            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1854                final DoubleCalc calc0 = compiler.compileDouble(call.getArg(0));
1855                final DoubleCalc calc1 = compiler.compileDouble(call.getArg(1));
1856                return new AbstractBooleanCalc(call, new Calc[] {calc0, calc1}) {
1857                    public boolean evaluateBoolean(Evaluator evaluator) {
1858                        final double v0 = calc0.evaluateDouble(evaluator);
1859                        final double v1 = calc1.evaluateDouble(evaluator);
1860                        if (v0 == Double.NaN || v1 == Double.NaN || v0 == DoubleNull || v1 == DoubleNull) {
1861                            return BooleanNull;
1862                        }
1863                        return v0 > v1;
1864                    }
1865                };
1866            }
1867        });
1868
1869        define(new FunDefBase(
1870                ">",
1871                "<String Expression> > <String Expression>",
1872                "Returns whether an expression is greater than another.",
1873                "ibSS") {
1874            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1875                final StringCalc calc0 = compiler.compileString(call.getArg(0));
1876                final StringCalc calc1 = compiler.compileString(call.getArg(1));
1877                return new AbstractBooleanCalc(call, new Calc[] {calc0, calc1}) {
1878                    public boolean evaluateBoolean(Evaluator evaluator) {
1879                        final String JavaDoc b0 = calc0.evaluateString(evaluator);
1880                        final String JavaDoc b1 = calc1.evaluateString(evaluator);
1881                        if (b0 == null || b1 == null) {
1882                            return BooleanNull;
1883                        }
1884                        return b0.compareTo(b1) > 0;
1885                    }
1886                };
1887            }
1888        });
1889
1890        define(new FunDefBase(
1891                ">=",
1892                "<Numeric Expression> >= <Numeric Expression>",
1893                "Returns whether an expression is greater than or equal to another.",
1894                "ibnn") {
1895            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1896                final DoubleCalc calc0 = compiler.compileDouble(call.getArg(0));
1897                final DoubleCalc calc1 = compiler.compileDouble(call.getArg(1));
1898                return new AbstractBooleanCalc(call, new Calc[] {calc0, calc1}) {
1899                    public boolean evaluateBoolean(Evaluator evaluator) {
1900                        final double v0 = calc0.evaluateDouble(evaluator);
1901                        final double v1 = calc1.evaluateDouble(evaluator);
1902                        if (v0 == Double.NaN || v1 == Double.NaN || v0 == DoubleNull || v1 == DoubleNull) {
1903                            return BooleanNull;
1904                        }
1905                        return v0 >= v1;
1906                    }
1907                };
1908            }
1909        });
1910
1911        define(new FunDefBase(
1912                ">=",
1913                "<String Expression> >= <String Expression>",
1914                "Returns whether an expression is greater than or equal to another.",
1915                "ibSS") {
1916            public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
1917                final StringCalc calc0 = compiler.compileString(call.getArg(0));
1918                final StringCalc calc1 = compiler.compileString(call.getArg(1));
1919                return new AbstractBooleanCalc(call, new Calc[] {calc0, calc1}) {
1920                    public boolean evaluateBoolean(Evaluator evaluator) {
1921                        final String JavaDoc b0 = calc0.evaluateString(evaluator);
1922                        final String JavaDoc b1 = calc1.evaluateString(evaluator);
1923                        if (b0 == null || b1 == null) {
1924                            return BooleanNull;
1925                        }
1926                        return b0.compareTo(b1) >= 0;
1927                    }
1928                };
1929            }
1930        });
1931
1932        // NON-STANDARD FUNCTIONS
1933

1934        define(NthQuartileFunDef.FirstQResolver);
1935
1936        define(NthQuartileFunDef.ThirdQResolver);
1937
1938        define(CalculatedChildFunDef.instance);
1939
1940        define(CastFunDef.Resolver);
1941    }
1942
1943    /** Returns (creating if necessary) the singleton. */
1944    public static BuiltinFunTable instance() {
1945        if (instance == null) {
1946            instance = new BuiltinFunTable();
1947            instance.init();
1948        }
1949        return instance;
1950    }
1951
1952    protected Member[] getNonEmptyMemberChildren(Evaluator evaluator, Member member) {
1953        SchemaReader sr = evaluator.getSchemaReader();
1954        if (evaluator.isNonEmpty()) {
1955            return sr.getMemberChildren(member, evaluator);
1956        } else {
1957            return sr.getMemberChildren(member);
1958        }
1959    }
1960
1961    /**
1962     * Returns members of a level which are not empty (according to the
1963     * criteria expressed by the evaluator). Calculated members are included.
1964     */

1965    protected static Member[] getNonEmptyLevelMembers(
1966            Evaluator evaluator,
1967            Level level) {
1968        SchemaReader sr = evaluator.getSchemaReader();
1969        if (evaluator.isNonEmpty()) {
1970            final Member[] members = sr.getLevelMembers(level, evaluator);
1971            return Util.addLevelCalculatedMembers(sr, level, members);
1972        }
1973        return sr.getLevelMembers(level, true);
1974    }
1975
1976    static List<Member> levelMembers(
1977            Level level,
1978            Evaluator evaluator,
1979            final boolean includeCalcMembers) {
1980        Member[] members = getNonEmptyLevelMembers(evaluator, level);
1981        List<Member> memberList =
1982            new ArrayList<Member>(Arrays.asList(members));
1983        if (!includeCalcMembers) {
1984            FunUtil.removeCalculatedMembers(memberList);
1985        }
1986        FunUtil.hierarchize(memberList, false);
1987        return memberList;
1988    }
1989
1990    static List<Member> hierarchyMembers(
1991            Hierarchy hierarchy,
1992            Evaluator evaluator,
1993            final boolean includeCalcMembers) {
1994        final List<Member> memberList;
1995        if (evaluator.isNonEmpty()) {
1996            // Allow the SQL generator to generate optimized SQL since we know
1997
// we're only interested in non-empty members of this level.
1998
memberList = new ArrayList<Member>();
1999            for (Level level : hierarchy.getLevels()) {
2000                Member[] members = getNonEmptyLevelMembers(evaluator, level);
2001                memberList.addAll(Arrays.asList(members));
2002            }
2003        } else {
2004            memberList = FunUtil.addMembers(
2005                evaluator.getSchemaReader(),
2006                new ArrayList<Member>(), hierarchy);
2007            if (!includeCalcMembers && memberList != null) {
2008                FunUtil.removeCalculatedMembers(memberList);
2009            }
2010        }
2011        FunUtil.hierarchize(memberList, false);
2012        return memberList;
2013    }
2014
2015    static List<Member> dimensionMembers(
2016            Dimension dimension,
2017            Evaluator evaluator,
2018            final boolean includeCalcMembers) {
2019        Hierarchy hierarchy = dimension.getHierarchy();
2020        return hierarchyMembers(hierarchy, evaluator, includeCalcMembers);
2021    }
2022}
2023
2024// End BuiltinFunTable.java
2025
Popular Tags