KickJava   Java API By Example, From Geeks To Geeks.

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


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

10 package mondrian.olap.fun;
11
12 import mondrian.olap.*;
13 import mondrian.olap.type.*;
14 import mondrian.calc.Calc;
15 import mondrian.calc.ExpCompiler;
16 import mondrian.calc.ListCalc;
17 import mondrian.calc.StringCalc;
18 import mondrian.calc.impl.AbstractListCalc;
19 import mondrian.calc.impl.ConstantCalc;
20 import mondrian.calc.impl.AbstractStringCalc;
21 import mondrian.mdx.ResolvedFunCall;
22
23 import java.util.List JavaDoc;
24 import java.util.Arrays JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.HashSet JavaDoc;
27 import java.util.Set JavaDoc;
28
29 /**
30  * Definition of the <code>Generate</code> MDX function.
31  *
32  * @author jhyde
33  * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/GenerateFunDef.java#6 $
34  * @since Mar 23, 2006
35  */

36 class GenerateFunDef extends FunDefBase {
37     static final ReflectiveMultiResolver ListResolver =
38         new ReflectiveMultiResolver(
39             "Generate",
40             "Generate(<Set1>, <Set2>[, ALL])",
41             "Applies a set to each member of another set and joins the resulting sets by union.",
42             new String JavaDoc[] {"fxxx", "fxxxy"},
43             GenerateFunDef.class);
44
45     static final ReflectiveMultiResolver StringResolver =
46         new ReflectiveMultiResolver(
47             "Generate",
48             "Generate(<Set>, <String>[, <String>])",
49             "Applies a set to a string expression and joins resulting sets by string concatenation.",
50             new String JavaDoc[] {"fSxS", "fSxSS"},
51             GenerateFunDef.class);
52
53     private static final String JavaDoc[] ReservedWords = new String JavaDoc[] {"ALL"};
54
55     public GenerateFunDef(FunDef dummyFunDef) {
56         super(dummyFunDef);
57     }
58
59     public Type getResultType(Validator validator, Exp[] args) {
60         final Type type = args[1].getType();
61         if (type instanceof StringType) {
62             // Generate(<Set>, <String>[, <String>])
63
return type;
64         } else {
65             final Type memberType = TypeUtil.toMemberOrTupleType(type);
66             return new SetType(memberType);
67         }
68     }
69
70     public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
71         final ListCalc listCalc = compiler.compileList(call.getArg(0));
72         final boolean tuple = ((SetType) listCalc.getType()).getElementType()
73             instanceof TupleType;
74         if (call.getArg(1).getType() instanceof StringType) {
75             final StringCalc stringCalc = compiler.compileString(call.getArg(1));
76             final StringCalc delimCalc;
77             if (call.getArgCount() == 3) {
78                 delimCalc = compiler.compileString(call.getArg(2));
79             } else {
80                 delimCalc = ConstantCalc.constantString("");
81             }
82
83             return new GenerateStringCalcImpl(
84                 call, listCalc, stringCalc, tuple, delimCalc);
85         } else {
86             final ListCalc listCalc2 = compiler.compileList(call.getArg(1));
87             final String JavaDoc literalArg = getLiteralArg(call, 2, "", ReservedWords);
88             final boolean all = literalArg.equalsIgnoreCase("ALL");
89
90             return new GenerateListCalcImpl(
91                 call, listCalc, listCalc2, tuple, all);
92         }
93     }
94
95     private static class GenerateListCalcImpl extends AbstractListCalc {
96         private final ListCalc listCalc1;
97         private final ListCalc listCalc2;
98         private final boolean tuple;
99         private final boolean all;
100
101         public GenerateListCalcImpl(
102             ResolvedFunCall call,
103             ListCalc listCalc1,
104             ListCalc listCalc2,
105             boolean tuple, boolean all) {
106             super(call, new Calc[]{listCalc1, listCalc2});
107             this.listCalc1 = listCalc1;
108             this.listCalc2 = listCalc2;
109             this.tuple = tuple;
110             this.all = all;
111         }
112
113         public List JavaDoc evaluateList(Evaluator evaluator) {
114             List JavaDoc<Object JavaDoc> result = new ArrayList JavaDoc<Object JavaDoc>();
115             if (tuple) {
116                 final List JavaDoc<Member[]> list1 = listCalc1.evaluateList(evaluator);
117                 final Evaluator evaluator2 = evaluator.push();
118                 if (all) {
119                     for (Member[] members : list1) {
120                         evaluator2.setContext(members);
121                         final List JavaDoc<Object JavaDoc> result2 =
122                             listCalc2.evaluateList(evaluator2);
123                         result.addAll(result2);
124                     }
125                 } else {
126                     final Set JavaDoc<Object JavaDoc> emitted = new HashSet JavaDoc<Object JavaDoc>();
127                     for (Member[] members : list1) {
128                         evaluator2.setContext(members);
129                         final List JavaDoc<Object JavaDoc> result2 =
130                             listCalc2.evaluateList(evaluator2);
131                         addDistinct(result, result2, emitted);
132                     }
133                 }
134             } else {
135                 final List JavaDoc<Member> list1 = listCalc1.evaluateList(evaluator);
136                 final Evaluator evaluator2 = evaluator.push();
137                 if (all) {
138                     for (Member member : list1) {
139                         evaluator2.setContext(member);
140                         final List JavaDoc<Object JavaDoc> result2 =
141                             listCalc2.evaluateList(evaluator2);
142                         result.addAll(result2);
143                     }
144                 } else {
145                     Set JavaDoc<Object JavaDoc> emitted = new HashSet JavaDoc<Object JavaDoc>();
146                     for (Member member : list1) {
147                         evaluator2.setContext(member);
148                         final List JavaDoc<Object JavaDoc> result2 =
149                             listCalc2.evaluateList(evaluator2);
150                         addDistinct(result, result2, emitted);
151                     }
152                 }
153             }
154             return result;
155         }
156
157         private void addDistinct(
158             List JavaDoc<Object JavaDoc> result,
159             List JavaDoc<Object JavaDoc> result2,
160             Set JavaDoc<Object JavaDoc> emitted) {
161
162             for (Object JavaDoc row : result2) {
163                 Object JavaDoc entry = row;
164                 if (entry instanceof Member []) {
165                     // wrap array for correct distinctness test
166
entry = new ArrayHolder<Member>((Member []) entry);
167                 }
168                 if (emitted.add(entry)) {
169                     result.add(row);
170                 }
171             }
172         }
173
174         public boolean dependsOn(Dimension dimension) {
175             return anyDependsButFirst(getCalcs(), dimension);
176         }
177     }
178
179     private static class GenerateStringCalcImpl extends AbstractStringCalc {
180         private final ListCalc listCalc;
181         private final StringCalc stringCalc;
182         private final boolean tuple;
183         private final StringCalc sepCalc;
184
185         public GenerateStringCalcImpl(
186             ResolvedFunCall call,
187             ListCalc listCalc,
188             StringCalc stringCalc,
189             boolean tuple, StringCalc sepCalc) {
190             super(call, new Calc[]{listCalc, stringCalc});
191             this.listCalc = listCalc;
192             this.stringCalc = stringCalc;
193             this.tuple = tuple;
194             this.sepCalc = sepCalc;
195         }
196
197         public String JavaDoc evaluateString(Evaluator evaluator) {
198             StringBuilder JavaDoc buf = new StringBuilder JavaDoc();
199             int k = 0;
200             if (tuple) {
201                 final List JavaDoc<Member[]> list1 = listCalc.evaluateList(evaluator);
202                 final Evaluator evaluator2 = evaluator.push();
203                 for (Member[] members : list1) {
204                     evaluator2.setContext(members);
205                     if (k++ > 0) {
206                         String JavaDoc sep = sepCalc.evaluateString(evaluator2);
207                         buf.append(sep);
208                     }
209                     final String JavaDoc result2 =
210                         stringCalc.evaluateString(evaluator2);
211                     buf.append(result2);
212                 }
213             } else {
214                 final List JavaDoc<Member> list1 = listCalc.evaluateList(evaluator);
215                 final Evaluator evaluator2 = evaluator.push();
216                 for (Member member : list1) {
217                     evaluator2.setContext(member);
218                     if (k++ > 0) {
219                         String JavaDoc sep = sepCalc.evaluateString(evaluator2);
220                         buf.append(sep);
221                     }
222                     final String JavaDoc result2 =
223                         stringCalc.evaluateString(evaluator2);
224                     buf.append(result2);
225                 }
226             }
227             return buf.toString();
228         }
229
230         public boolean dependsOn(Dimension dimension) {
231             return anyDependsButFirst(getCalcs(), dimension);
232         }
233     }
234 }
235
236 // End GenerateFunDef.java
237
Popular Tags