KickJava   Java API By Example, From Geeks To Geeks.

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


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

11 package mondrian.olap.fun;
12
13 import mondrian.calc.*;
14 import mondrian.calc.impl.*;
15 import mondrian.olap.*;
16 import mondrian.mdx.ResolvedFunCall;
17
18 import java.util.*;
19
20 /**
21  * Definition of the <code>Order</code> MDX function.
22  *
23  * @author jhyde
24  * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/OrderFunDef.java#14 $
25  * @since Mar 23, 2006
26  */

27 class OrderFunDef extends FunDefBase {
28
29     static final ReflectiveMultiResolver Resolver = new ReflectiveMultiResolver(
30             "Order",
31             "Order(<Set>, <Value Expression>[, ASC | DESC | BASC | BDESC])",
32             "Arranges members of a set, optionally preserving or breaking the hierarchy.",
33             new String JavaDoc[]{"fxxvy", "fxxv"},
34             OrderFunDef.class,
35             Flag.getNames());
36
37     public OrderFunDef(FunDef dummyFunDef) {
38         super(dummyFunDef);
39     }
40
41     public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
42         final ListCalc listCalc = compiler.compileList(call.getArg(0), true);
43         final Calc expCalc = compiler.compileScalar(call.getArg(1), true);
44         final Flag order = getLiteralArg(call, 2, Flag.ASC, Flag.class);
45
46         if (expCalc instanceof MemberValueCalc) {
47             MemberValueCalc memberValueCalc = (MemberValueCalc) expCalc;
48             List<Calc> constantList = new ArrayList<Calc>();
49             List<Calc> variableList = new ArrayList<Calc>();
50             final MemberCalc[] calcs = (MemberCalc[]) memberValueCalc.getCalcs();
51             for (MemberCalc memberCalc : calcs) {
52                 if (memberCalc instanceof ConstantCalc &&
53                     !listCalc.dependsOn(
54                         memberCalc.getType().getHierarchy().getDimension())) {
55                     constantList.add(memberCalc);
56                 } else {
57                     variableList.add(memberCalc);
58                 }
59             }
60             if (constantList.isEmpty()) {
61                 // All members are non-constant -- cannot optimize
62
} else if (variableList.isEmpty()) {
63                 // All members are constant. Optimize by setting entire context
64
// first.
65
return new ContextCalc(
66                         calcs,
67                         new CalcImpl(
68                                 call,
69                                 listCalc,
70                                 new ValueCalc(
71                                         new DummyExp(expCalc.getType())),
72                             order.descending,
73                             order.brk));
74             } else {
75                 // Some members are constant. Evaluate these before evaluating
76
// the list expression.
77
return new ContextCalc(
78                     constantList.toArray(
79                         new MemberCalc[constantList.size()]),
80                         new CalcImpl(
81                                 call,
82                                 listCalc,
83                                 new MemberValueCalc(
84                                     new DummyExp(expCalc.getType()),
85                                     variableList.toArray(
86                                         new MemberCalc[variableList.size()])),
87                             order.descending,
88                             order.brk));
89             }
90         }
91         return new CalcImpl(call, listCalc, expCalc, order.descending, order.brk);
92     }
93
94     /**
95      * Enumeration of the flags allowed to the <code>ORDER</code> MDX function.
96      */

97     enum Flag {
98         ASC(false, false),
99         DESC(true, false),
100         BASC(false, true),
101         BDESC(true, true);
102
103         private final boolean descending;
104         private final boolean brk;
105
106         Flag(boolean descending, boolean brk) {
107             this.descending = descending;
108             this.brk = brk;
109         }
110
111         public static String JavaDoc[] getNames() {
112             List<String JavaDoc> names = new ArrayList<String JavaDoc>();
113             for (Flag flags : Flag.class.getEnumConstants()) {
114                 names.add(flags.name());
115             }
116             return names.toArray(new String JavaDoc[names.size()]);
117         }
118     }
119
120     private class CalcImpl extends AbstractListCalc {
121         private final ListCalc listCalc;
122         private final Calc expCalc;
123         private final boolean desc;
124         private final boolean brk;
125
126         public CalcImpl(
127             ResolvedFunCall call,
128             ListCalc listCalc,
129             Calc expCalc,
130             boolean desc,
131             boolean brk)
132         {
133             super(call, new Calc[]{listCalc, expCalc});
134             assert listCalc.getResultStyle() == ExpCompiler.ResultStyle.MUTABLE_LIST;
135             this.listCalc = listCalc;
136             this.expCalc = expCalc;
137             this.desc = desc;
138             this.brk = brk;
139         }
140
141         public List evaluateList(Evaluator evaluator) {
142             List list = listCalc.evaluateList(evaluator);
143             sortMembers(evaluator.push(), list, expCalc, desc, brk);
144             return list;
145         }
146
147         public Calc[] getCalcs() {
148             return new Calc[] {listCalc, expCalc};
149         }
150
151         public List<Object JavaDoc> getArguments() {
152             return Collections.singletonList(
153                 (Object JavaDoc) (desc ?
154                     (brk ? Flag.BDESC : Flag.DESC) :
155                     (brk ? Flag.BASC : Flag.ASC)));
156         }
157
158         public boolean dependsOn(Dimension dimension) {
159             return anyDependsButFirst(getCalcs(), dimension);
160         }
161     }
162
163     private static class ContextCalc extends GenericCalc {
164         private final MemberCalc[] memberCalcs;
165         private final Calc calc;
166         private final Calc[] calcs;
167         private final Member[] members; // workspace
168

169         protected ContextCalc(MemberCalc[] memberCalcs, Calc calc) {
170             super(new DummyExp(calc.getType()));
171             this.memberCalcs = memberCalcs;
172             this.calc = calc;
173             this.calcs = new Calc[memberCalcs.length + 1];
174             System.arraycopy(memberCalcs, 0, this.calcs, 0, memberCalcs.length);
175             this.calcs[this.calcs.length - 1] = calc;
176             this.members = new Member[memberCalcs.length];
177         }
178
179         public Calc[] getCalcs() {
180             return calcs;
181         }
182
183         public Object JavaDoc evaluate(Evaluator evaluator) {
184             // Evaluate each of the members, and set as context in the
185
// sub-evaluator.
186
for (int i = 0; i < memberCalcs.length; i++) {
187                 members[i] = memberCalcs[i].evaluateMember(evaluator);
188             }
189             final Evaluator subEval = evaluator.push(members);
190             // Evaluate the expression in the new context.
191
return calc.evaluate(subEval);
192         }
193
194         public boolean dependsOn(Dimension dimension) {
195             if (anyDepends(memberCalcs, dimension)) {
196                 return true;
197             }
198             // Member calculations generate members, which mask the actual
199
// expression from the inherited context.
200
for (MemberCalc memberCalc : memberCalcs) {
201                 if (memberCalc.getType().usesDimension(dimension, true)) {
202                     return false;
203                 }
204             }
205             return calc.dependsOn(dimension);
206         }
207         public ExpCompiler.ResultStyle getResultStyle() {
208             return calc.getResultStyle();
209         }
210     }
211 }
212
213 // End OrderFunDef.java
214
Popular Tags