KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/olap/fun/SetFunDef.java#22 $
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, 3 March, 2002
12 */

13 package mondrian.olap.fun;
14
15 import mondrian.calc.*;
16 import mondrian.calc.impl.AbstractListCalc;
17 import mondrian.calc.impl.AbstractIterCalc;
18 import mondrian.calc.impl.AbstractVoidCalc;
19 import mondrian.calc.ExpCompiler.ResultStyle;
20 import mondrian.olap.*;
21 import mondrian.olap.type.*;
22 import mondrian.resource.MondrianResource;
23 import mondrian.mdx.ResolvedFunCall;
24
25 import java.io.PrintWriter JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Iterator JavaDoc;
28 import java.util.List JavaDoc;
29
30 /**
31  * <code>SetFunDef</code> implements the 'set' function (whose syntax is the
32  * brace operator, <code>{ ... }</code>).
33  *
34  * @author jhyde
35  * @since 3 March, 2002
36  * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/SetFunDef.java#22 $
37  */

38 public class SetFunDef extends FunDefBase {
39     static final ResolverImpl Resolver = new ResolverImpl();
40
41     SetFunDef(Resolver resolver, int[] argTypes) {
42         super(resolver, Category.Set, argTypes);
43     }
44
45     public void unparse(Exp[] args, PrintWriter JavaDoc pw) {
46         ExpBase.unparseList(pw, args, "{", ", ", "}");
47     }
48
49     public Type getResultType(Validator validator, Exp[] args) {
50         // All of the members in {<Member1>[,<MemberI>]...} must have the same
51
// Hierarchy. But if there are no members, we can't derive a
52
// hierarchy.
53
Type type0 = null;
54         if (args.length == 0) {
55             // No members to go on, so we can't guess the hierarchy.
56
type0 = MemberType.Unknown;
57         } else {
58             for (int i = 0; i < args.length; i++) {
59                 Exp arg = args[i];
60                 Type type = arg.getType();
61                 type = TypeUtil.toMemberOrTupleType(type);
62                 if (i == 0) {
63                     type0 = type;
64                 } else {
65                     if (!TypeUtil.isUnionCompatible(type0, type)) {
66                         throw MondrianResource.instance().ArgsMustHaveSameHierarchy.ex(getName());
67                     }
68                 }
69             }
70         }
71         return new SetType(type0);
72     }
73
74     public Calc compileCall(ResolvedFunCall call, ExpCompiler compiler) {
75         final Exp[] args = call.getArgs();
76         return new ListSetCalc(call, args, compiler,
77                     ExpCompiler.LIST_MUTABLE_LIST_RESULT_STYLE_ARRAY);
78     }
79
80     /**
81      * Compiled expression to implement the MDX set function, <code>{ ...
82      * }</code>.
83      *
84      * <p>The set function can contain expressions which yield sets together
85      * with expressions which yield individual members/tuples, provided that
86      * they all have the same type. It automatically removes null members
87      * or partially-null tuples from the list.
88      *
89      * <p>The implementation uses {@link VoidCalc} objects with side-effects
90      * to avoid generating lots of intermediate lists.
91      */

92     public static class ListSetCalc extends AbstractListCalc {
93         private List JavaDoc result = new ArrayList JavaDoc();
94         private final VoidCalc[] voidCalcs;
95
96         public ListSetCalc(Exp exp, Exp[] args, ExpCompiler compiler,
97                 ResultStyle[] resultStyles) {
98             super(exp, null);
99             voidCalcs = compileSelf(args, compiler, resultStyles);
100         }
101
102         public Calc[] getCalcs() {
103             return voidCalcs;
104         }
105
106         private VoidCalc[] compileSelf(Exp[] args,
107                 ExpCompiler compiler,
108                 ResultStyle[] resultStyles) {
109             VoidCalc[] voidCalcs = new VoidCalc[args.length];
110             for (int i = 0; i < args.length; i++) {
111                 voidCalcs[i] = createCalc(args[i], compiler, resultStyles);
112             }
113             return voidCalcs;
114         }
115
116         private VoidCalc createCalc(Exp arg,
117                 ExpCompiler compiler,
118                 ResultStyle[] resultStyles) {
119             final Type type = arg.getType();
120             if (type instanceof SetType) {
121                 // TODO use resultStyles
122
final ListCalc listCalc = compiler.compileList(arg);
123                 final Type elementType = ((SetType) type).getElementType();
124                 if (elementType instanceof MemberType) {
125                     return new AbstractVoidCalc(arg, new Calc[] {listCalc}) {
126                         public void evaluateVoid(Evaluator evaluator) {
127                             List JavaDoc list = listCalc.evaluateList(evaluator);
128                             // Add only members which are not null.
129
for (int i = 0; i < list.size(); i++) {
130                                 Member member = (Member) list.get(i);
131                                 if (member == null || member.isNull()) {
132                                     continue;
133                                 }
134                                 result.add(member);
135                             }
136                         }
137
138                         protected String JavaDoc getName() {
139                             return "Sublist";
140                         }
141                     };
142                 } else {
143                     return new AbstractVoidCalc(arg, new Calc[] {listCalc}) {
144                         public void evaluateVoid(Evaluator evaluator) {
145                             List JavaDoc list = listCalc.evaluateList(evaluator);
146                             // Add only tuples which are not null. Tuples with
147
// any null members are considered null.
148
list:
149                             for (int i = 0; i < list.size(); i++) {
150                                 Member[] members = (Member[]) list.get(i);
151                                 for (int j = 0; j < members.length; j++) {
152                                     Member member = members[j];
153                                     if (member == null || member.isNull()) {
154                                         continue list;
155                                     }
156                                 }
157                                 result.add(members);
158                             }
159                         }
160
161                         protected String JavaDoc getName() {
162                             return "Sublist";
163                         }
164                     };
165                 }
166             } else if (TypeUtil.couldBeMember(type)) {
167                 final MemberCalc listCalc = compiler.compileMember(arg);
168                 return new AbstractVoidCalc(arg, new Calc[] {listCalc}) {
169                     public void evaluateVoid(Evaluator evaluator) {
170                         Member member = listCalc.evaluateMember(evaluator);
171                         if (member == null || member.isNull()) {
172                             return;
173                         }
174                         result.add(member);
175                     }
176
177                     protected String JavaDoc getName() {
178                         return "Sublist";
179                     }
180                 };
181             } else {
182                 final TupleCalc tupleCalc = compiler.compileTuple(arg);
183                 return new AbstractVoidCalc(arg, new Calc[] {tupleCalc}) {
184                     public void evaluateVoid(Evaluator evaluator) {
185                         // Don't add null or partially null tuple to result.
186
Member[] members = tupleCalc.evaluateTuple(evaluator);
187                         if (members == null) {
188                             return;
189                         }
190                         assert !tupleContainsNullMember(members);
191
192                         result.add(members);
193                     }
194                 };
195             }
196         }
197
198         public List JavaDoc evaluateList(Evaluator evaluator) {
199             result.clear();
200             for (int i = 0; i < voidCalcs.length; i++) {
201                 voidCalcs[i].evaluateVoid(evaluator);
202             }
203             return new ArrayList JavaDoc(result);
204         }
205     }
206     public static class IterSetCalc extends AbstractIterCalc {
207         private final IterCalc[] iterCalcs;
208
209         public IterSetCalc(Exp exp, Exp[] args, ExpCompiler compiler,
210                 ResultStyle[] resultStyles) {
211             super(exp, null);
212             iterCalcs = compileSelf(args, compiler, resultStyles);
213         }
214
215         public Calc[] getCalcs() {
216             return iterCalcs;
217         }
218
219         private IterCalc[] compileSelf(Exp[] args,
220                 ExpCompiler compiler,
221                 ResultStyle[] resultStyles) {
222             IterCalc[] iterCalcs = new IterCalc[args.length];
223             for (int i = 0; i < args.length; i++) {
224                 iterCalcs[i] = createCalc(args[i], compiler, resultStyles);
225             }
226             return iterCalcs;
227         }
228
229         private IterCalc createCalc(Exp arg,
230                 ExpCompiler compiler,
231                 ResultStyle[] resultStyles) {
232
233             final Type type = arg.getType();
234             if (type instanceof SetType) {
235                 final Calc calc = compiler.compile(arg, resultStyles);
236                 final Type elementType = ((SetType) type).getElementType();
237                 if (elementType instanceof MemberType) {
238                     switch (calc.getResultStyle()) {
239                     case ITERABLE :
240                     return new AbstractIterCalc(arg, new Calc[] {calc}) {
241                         private final IterCalc iterCalc = (IterCalc) calc;
242                         public Iterable JavaDoc evaluateIterable(Evaluator evaluator) {
243                             Iterable JavaDoc iterable =
244                                 iterCalc.evaluateIterable(evaluator);
245                             return iterable;
246                         }
247                         protected String JavaDoc getName() {
248                             return "Sublist";
249                         }
250                     };
251                     case LIST :
252                     case MUTABLE_LIST :
253                     return new AbstractIterCalc(arg, new Calc[] {calc}) {
254                         private final ListCalc listCalc = (ListCalc) calc;
255                         public Iterable JavaDoc evaluateIterable(Evaluator evaluator) {
256                             List JavaDoc result = new ArrayList JavaDoc();
257                             List JavaDoc list = listCalc.evaluateList(evaluator);
258                             // Add only members which are not null.
259
for (int i = 0; i < list.size(); i++) {
260                                 Member member = (Member) list.get(i);
261                                 if (member == null || member.isNull()) {
262                                     continue;
263                                 }
264                                 result.add(member);
265                             }
266                             return result;
267                         }
268                         protected String JavaDoc getName() {
269                             return "Sublist";
270                         }
271                     };
272                     }
273                     throw ResultStyleException.generateBadType(
274                         new ResultStyle[] {
275                             ResultStyle.ITERABLE,
276                             ResultStyle.LIST,
277                             ResultStyle.MUTABLE_LIST
278                         }, calc.getResultStyle());
279                 } else {
280                     switch (calc.getResultStyle()) {
281                     case ITERABLE :
282                     return new AbstractIterCalc(arg, new Calc[] {calc}) {
283                         private final IterCalc iterCalc = (IterCalc) calc;
284                         public Iterable JavaDoc evaluateIterable(Evaluator evaluator) {
285                             Iterable JavaDoc iterable =
286                                 iterCalc.evaluateIterable(evaluator);
287                             return iterable;
288                         }
289                         protected String JavaDoc getName() {
290                             return "Sublist";
291                         }
292                     };
293                     case LIST :
294                     case MUTABLE_LIST :
295                     return new AbstractIterCalc(arg, new Calc[] {calc}) {
296                         private final ListCalc listCalc = (ListCalc) calc;
297                         public Iterable JavaDoc evaluateIterable(Evaluator evaluator) {
298                             List JavaDoc result = new ArrayList JavaDoc();
299                             List JavaDoc list = listCalc.evaluateList(evaluator);
300                             // Add only tuples which are not null. Tuples with
301
// any null members are considered null.
302
list:
303                             for (int i = 0; i < list.size(); i++) {
304                                 Member[] members = (Member[]) list.get(i);
305                                 for (int j = 0; j < members.length; j++) {
306                                     Member member = members[j];
307                                     if (member == null || member.isNull()) {
308                                         continue list;
309                                     }
310                                 }
311                                 result.add(members);
312                             }
313                             return result;
314                         }
315
316                         protected String JavaDoc getName() {
317                             return "Sublist";
318                         }
319                     };
320                     }
321                     throw ResultStyleException.generateBadType(
322                         new ResultStyle[] {
323                             ResultStyle.ITERABLE,
324                             ResultStyle.LIST,
325                             ResultStyle.MUTABLE_LIST
326                         },
327                         calc.getResultStyle());
328
329                 }
330             } else if (TypeUtil.couldBeMember(type)) {
331                 final MemberCalc memberCalc = compiler.compileMember(arg);
332                 return new AbstractIterCalc(arg, new Calc[] {memberCalc}) {
333                     public Iterable JavaDoc evaluateIterable(Evaluator evaluator) {
334                         final Member member =
335                             memberCalc.evaluateMember(evaluator);
336                         Iterable JavaDoc<Member> iterable = new Iterable JavaDoc<Member>() {
337                             public Iterator JavaDoc<Member> iterator() {
338                                 return new Iterator JavaDoc<Member>() {
339                                     private Member m = member;
340                                     public boolean hasNext() {
341                                         return (m != null);
342                                     }
343                                     public Member next() {
344                                         try {
345                                             return m;
346                                         } finally {
347                                             m = null;
348                                         }
349                                     }
350                                     public void remove() {
351                                         throw new UnsupportedOperationException JavaDoc("remove");
352                                     }
353                                 };
354                             }
355                         };
356                         return iterable;
357                     }
358                     protected String JavaDoc getName() {
359                         return "Sublist";
360                     }
361                 };
362             } else {
363                 final TupleCalc tupleCalc = compiler.compileTuple(arg);
364
365                 return new AbstractIterCalc(arg, new Calc[] {tupleCalc}) {
366                     public Iterable JavaDoc evaluateIterable(Evaluator evaluator) {
367                         final Member[] members = tupleCalc.evaluateTuple(evaluator);
368                         Iterable JavaDoc<Member[]> iterable = new Iterable JavaDoc<Member[]>() {
369                             public Iterator JavaDoc<Member[]> iterator() {
370                                 return new Iterator JavaDoc<Member[]>() {
371                                     private Member[] m = members;
372                                     public boolean hasNext() {
373                                         return (m != null);
374                                     }
375                                     public Member[] next() {
376                                         try {
377                                             return m;
378                                         } finally {
379                                             m = null;
380                                         }
381                                     }
382                                     public void remove() {
383                                         throw new UnsupportedOperationException JavaDoc("remove");
384                                     }
385                                 };
386                             }
387                         };
388                         return iterable;
389                     }
390                     protected String JavaDoc getName() {
391                         return "Sublist";
392                     }
393                 };
394             }
395         }
396
397         public Iterable JavaDoc evaluateIterable(final Evaluator evaluator) {
398             Iterable JavaDoc result = new Iterable JavaDoc<Member>() {
399                 public Iterator JavaDoc<Member> iterator() {
400                     return new Iterator JavaDoc<Member>() {
401                         int index = 0;
402                         Iterator JavaDoc<Member> currentIterator = null;
403                         Member member = null;
404                         public boolean hasNext() {
405                             if (member != null) {
406                                 return true;
407                             }
408                             if (currentIterator == null) {
409                                 if (index >= iterCalcs.length) {
410                                     return false;
411                                 }
412                                 IterCalc iterCalc = iterCalcs[index++];
413                                 Iterable JavaDoc iter =
414                                     iterCalc.evaluateIterable(evaluator);
415                                 currentIterator = iter.iterator();
416                             }
417                             while(true) {
418                                 boolean b = currentIterator.hasNext();
419                                 while (! b) {
420                                     if (index >= iterCalcs.length) {
421                                         return false;
422                                     }
423                                     IterCalc iterCalc = iterCalcs[index++];
424                                     Iterable JavaDoc iter =
425                                         iterCalc.evaluateIterable(evaluator);
426                                     currentIterator = iter.iterator();
427                                     b = currentIterator.hasNext();
428                                 }
429                                 member = currentIterator.next();
430                                 if (member != null) {
431                                     break;
432                                 }
433                             }
434                             return true;
435                         }
436                         public Member next() {
437                             try {
438                                 return member;
439                             } finally {
440                                 member = null;
441                             }
442                         }
443                         public void remove() {
444                             throw new UnsupportedOperationException JavaDoc("remove");
445                         }
446                     };
447                 }
448             };
449             return result;
450         }
451     }
452
453     private static class ResolverImpl extends ResolverBase {
454         public ResolverImpl() {
455             super(
456                     "{}",
457                     "{<Member> [, <Member>...]}",
458                     "Brace operator constructs a set.",
459                     Syntax.Braces);
460         }
461
462         public FunDef resolve(
463                 Exp[] args, Validator validator, int[] conversionCount) {
464             int[] parameterTypes = new int[args.length];
465             for (int i = 0; i < args.length; i++) {
466                 if (validator.canConvert(
467                         args[i], Category.Member, conversionCount)) {
468                     parameterTypes[i] = Category.Member;
469                     continue;
470                 }
471                 if (validator.canConvert(
472                         args[i], Category.Set, conversionCount)) {
473                     parameterTypes[i] = Category.Set;
474                     continue;
475                 }
476                 if (validator.canConvert(
477                         args[i], Category.Tuple, conversionCount)) {
478                     parameterTypes[i] = Category.Tuple;
479                     continue;
480                 }
481                 return null;
482             }
483             return new SetFunDef(this, parameterTypes);
484         }
485     }
486 }
487
488 // End SetFunDef.java
489
Popular Tags