KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/olap/fun/FilterFunDef.java#7 $
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.calc.Calc;
13 import mondrian.calc.ExpCompiler;
14 import mondrian.calc.ExpCompiler.ResultStyle;
15 import mondrian.calc.IterCalc;
16 import mondrian.calc.ListCalc;
17 import mondrian.calc.BooleanCalc;
18 import mondrian.calc.impl.AbstractListCalc;
19 import mondrian.calc.impl.AbstractIterCalc;
20 import mondrian.mdx.ResolvedFunCall;
21 import mondrian.olap.type.SetType;
22 import mondrian.olap.type.MemberType;
23 import mondrian.olap.*;
24
25 import java.util.List JavaDoc;
26 import java.util.ArrayList JavaDoc;
27 import java.util.Iterator JavaDoc;
28
29 /**
30  * Definition of the <code>Filter</code> MDX function.
31  *
32  * @author jhyde
33  * @version $Id: //open/mondrian/src/main/mondrian/olap/fun/FilterFunDef.java#7 $
34  * @since Mar 23, 2006
35  */

36 class FilterFunDef extends FunDefBase {
37     static final FilterFunDef instance = new FilterFunDef();
38
39     private FilterFunDef() {
40         super(
41                 "Filter",
42                 "Filter(<Set>, <Search Condition>)",
43                 "Returns the set resulting from filtering a set based on a search condition.",
44                 "fxxb");
45     }
46
47     public Calc compileCall(final ResolvedFunCall call, ExpCompiler compiler) {
48         ResultStyle[] rs = compiler.getAcceptableResultStyles();
49         // What is the desired return type?
50
for (int i = 0; i < rs.length; i++) {
51             switch (rs[i]) {
52             case ITERABLE :
53             case ANY :
54                 // Consumer wants ITERABLE or ANY
55
return compileCallIterable(call, compiler);
56             case MUTABLE_LIST:
57             case LIST :
58                 // Consumer wants MUTABLE_LIST or LIST
59
return compileCallList(call, compiler);
60             }
61         }
62         throw ResultStyleException.generate(
63             new ResultStyle[] {
64                 ResultStyle.ITERABLE,
65                 ResultStyle.LIST,
66                 ResultStyle.MUTABLE_LIST,
67                 ResultStyle.ANY
68             },
69             rs
70         );
71     }
72
73
74     /**
75      * Returns an IterCalc.
76      * Here we would like to get either a IterCalc or ListCalc (mutable)
77      * from the inner expression. For the IterCalc, its Iterator
78      * can be wrapped with another Iterator that filters each element.
79      * For the mutable list, remove all members that are filtered.
80      *
81      * @param call
82      * @param compiler
83      * @return
84      */

85     protected Calc compileCallIterable(final ResolvedFunCall call,
86             ExpCompiler compiler) {
87         // want iterable, mutable list or immutable list in that order
88
Calc imlcalc = compiler.compile(call.getArg(0),
89                     ExpCompiler.ITERABLE_LIST_MUTABLE_LIST_RESULT_STYLE_ARRAY);
90         BooleanCalc bcalc = compiler.compileBoolean(call.getArg(1));
91         Calc[] calcs = new Calc[] {imlcalc, bcalc};
92
93         // check returned calc ResultStyles
94
checkIterListResultStyles(imlcalc);
95
96         if (((SetType) imlcalc.getType()).getElementType() instanceof MemberType) {
97             if (imlcalc.getResultStyle() == ResultStyle.ITERABLE) {
98                 return new IterMemberIterCalc(call, calcs);
99             } else if (imlcalc.getResultStyle() == ResultStyle.LIST) {
100                 return new ImMutableMemberIterCalc(call, calcs);
101             } else {
102                 return new MutableMemberIterCalc(call, calcs);
103             }
104
105         } else {
106
107             if (imlcalc.getResultStyle() == ResultStyle.ITERABLE) {
108                 return new IterMemberArrayIterCalc(call, calcs);
109             } else if (imlcalc.getResultStyle() == ResultStyle.LIST) {
110                 return new ImMutableMemberArrayIterCalc(call, calcs);
111             } else {
112                 return new MutableMemberArrayIterCalc(call, calcs);
113             }
114         }
115     }
116
117     private static abstract class BaseIterCalc extends AbstractIterCalc {
118         protected BaseIterCalc(ResolvedFunCall call, Calc[] calcs) {
119             super(call, calcs);
120         }
121         public Iterable JavaDoc evaluateIterable(Evaluator evaluator) {
122             ResolvedFunCall call = (ResolvedFunCall) exp;
123             // Use a native evaluator, if more efficient.
124
// TODO: Figure this out at compile time.
125
SchemaReader schemaReader = evaluator.getSchemaReader();
126             NativeEvaluator nativeEvaluator =
127                     schemaReader.getNativeSetEvaluator(
128                             call.getFunDef(), call.getArgs(), evaluator, this);
129             if (nativeEvaluator != null) {
130                 return (Iterable JavaDoc) nativeEvaluator.execute(
131                         ResultStyle.ITERABLE);
132             } else {
133                 return makeIterable(evaluator);
134             }
135         }
136         protected abstract Iterable JavaDoc makeIterable(Evaluator evaluator);
137
138         public boolean dependsOn(Dimension dimension) {
139             return anyDependsButFirst(getCalcs(), dimension);
140         }
141     }
142     //
143
// Member Iter Calcs
144
//
145
private static class MutableMemberIterCalc extends BaseIterCalc {
146         MutableMemberIterCalc(ResolvedFunCall call, Calc[] calcs) {
147             super(call, calcs);
148         }
149         protected Iterable JavaDoc makeIterable(Evaluator evaluator) {
150             Calc[] calcs = getCalcs();
151             ListCalc lcalc = (ListCalc) calcs[0];
152             BooleanCalc bcalc = (BooleanCalc) calcs[1];
153
154             final Evaluator evaluator2 = evaluator.push();
155             List JavaDoc members = lcalc.evaluateList(evaluator);
156
157             Iterator JavaDoc it = members.iterator();
158             while (it.hasNext()) {
159                 Member member = (Member) it.next();
160                 evaluator2.setContext(member);
161                 if (! bcalc.evaluateBoolean(evaluator2)) {
162                     it.remove();
163                 }
164             }
165             return members;
166         }
167     }
168     private static class ImMutableMemberIterCalc extends BaseIterCalc {
169         ImMutableMemberIterCalc(ResolvedFunCall call, Calc[] calcs) {
170             super(call, calcs);
171         }
172         protected Iterable JavaDoc makeIterable(Evaluator evaluator) {
173             Calc[] calcs = getCalcs();
174             ListCalc lcalc = (ListCalc) calcs[0];
175             BooleanCalc bcalc = (BooleanCalc) calcs[1];
176
177             final Evaluator evaluator2 = evaluator.push();
178             List JavaDoc members = lcalc.evaluateList(evaluator);
179
180             // Not mutable, must create new list
181
List JavaDoc result = new ArrayList JavaDoc();
182             for (int i = 0, count = members.size(); i < count; i++) {
183                 Member member = (Member) members.get(i);
184                 evaluator2.setContext(member);
185                 if (bcalc.evaluateBoolean(evaluator2)) {
186                     result.add(member);
187                 }
188             }
189             return result;
190         }
191     }
192     private static class IterMemberIterCalc extends BaseIterCalc {
193         IterMemberIterCalc(ResolvedFunCall call, Calc[] calcs) {
194             super(call, calcs);
195         }
196         protected Iterable JavaDoc makeIterable(Evaluator evaluator) {
197             Calc[] calcs = getCalcs();
198             IterCalc icalc = (IterCalc) calcs[0];
199             final BooleanCalc bcalc = (BooleanCalc) calcs[1];
200
201             final Evaluator evaluator2 = evaluator.push();
202             // This does dynamics, just in time,
203
// as needed filtering
204
final Iterable JavaDoc<Member> iter = (Iterable JavaDoc<Member>)
205                     icalc.evaluateIterable(evaluator);
206
207             Iterable JavaDoc result = new Iterable JavaDoc<Member>() {
208                 public Iterator JavaDoc<Member> iterator() {
209                     return new Iterator JavaDoc<Member>() {
210                         Iterator JavaDoc<Member> it = iter.iterator();
211                         Member m = null;
212                         public boolean hasNext() {
213                             if (m != null) {
214                                 return true;
215                             }
216                             if (! it.hasNext()) {
217                                 return false;
218                             }
219                             this.m = it.next();
220                             evaluator2.setContext(this.m);
221                             while (! bcalc.evaluateBoolean(evaluator2)) {
222                                 if (! it.hasNext()) {
223                                     return false;
224                                 }
225                                 this.m = it.next();
226                                 evaluator2.setContext(this.m);
227                             }
228                             return true;
229                         }
230                         public Member next() {
231                             try {
232                                 return this.m;
233                             } finally {
234                                 this.m = null;
235                             }
236                         }
237                         public void remove() {
238                             throw new UnsupportedOperationException JavaDoc("remove");
239                         }
240                     };
241                 }
242             };
243             return result;
244         }
245     }
246
247     //
248
// Member[] Iter Calcs
249
//
250
private static class MutableMemberArrayIterCalc extends BaseIterCalc {
251         MutableMemberArrayIterCalc(ResolvedFunCall call, Calc[] calcs) {
252             super(call, calcs);
253         }
254         protected Iterable JavaDoc makeIterable(Evaluator evaluator) {
255             Calc[] calcs = getCalcs();
256             ListCalc lcalc = (ListCalc) calcs[0];
257             BooleanCalc bcalc = (BooleanCalc) calcs[1];
258
259             final Evaluator evaluator2 = evaluator.push();
260             List JavaDoc members = lcalc.evaluateList(evaluator);
261
262             Iterator JavaDoc it = members.iterator();
263             while (it.hasNext()) {
264                 Member[] member = (Member[]) it.next();
265                 evaluator2.setContext(member);
266                 if (! bcalc.evaluateBoolean(evaluator2)) {
267                     it.remove();
268                 }
269             }
270             return members;
271         }
272     }
273     private static class ImMutableMemberArrayIterCalc extends BaseIterCalc {
274         ImMutableMemberArrayIterCalc(ResolvedFunCall call, Calc[] calcs) {
275             super(call, calcs);
276         }
277         protected Iterable JavaDoc makeIterable(Evaluator evaluator) {
278             Calc[] calcs = getCalcs();
279             ListCalc lcalc = (ListCalc) calcs[0];
280             BooleanCalc bcalc = (BooleanCalc) calcs[1];
281
282             final Evaluator evaluator2 = evaluator.push();
283             List JavaDoc members = lcalc.evaluateList(evaluator);
284
285             // Not mutable, must create new list
286
List JavaDoc result = new ArrayList JavaDoc();
287             for (int i = 0, count = members.size(); i < count; i++) {
288                 Member[] member = (Member[]) members.get(i);
289                 evaluator2.setContext(member);
290                 if (bcalc.evaluateBoolean(evaluator2)) {
291                     result.add(member);
292                 }
293             }
294             return result;
295         }
296     }
297     private static class IterMemberArrayIterCalc extends BaseIterCalc {
298         IterMemberArrayIterCalc(ResolvedFunCall call, Calc[] calcs) {
299             super(call, calcs);
300         }
301         protected Iterable JavaDoc makeIterable(Evaluator evaluator) {
302             Calc[] calcs = getCalcs();
303             IterCalc icalc = (IterCalc) calcs[0];
304             final BooleanCalc bcalc = (BooleanCalc) calcs[1];
305
306             final Evaluator evaluator2 = evaluator.push();
307
308             // This does dynamics, just in time,
309
// as needed filtering
310
final Iterable JavaDoc<Member[]> iter = (Iterable JavaDoc<Member[]>)
311                     icalc.evaluateIterable(evaluator);
312             Iterable JavaDoc result = new Iterable JavaDoc<Member[]>() {
313                 public Iterator JavaDoc<Member[]> iterator() {
314                     return new Iterator JavaDoc<Member[]>() {
315                         Iterator JavaDoc<Member[]> it = iter.iterator();
316                         Member[] m = null;
317                         public boolean hasNext() {
318                             if (m != null) {
319                                 return true;
320                             }
321                             if (! it.hasNext()) {
322                                 return false;
323                             }
324                             this.m = it.next();
325                             evaluator2.setContext(this.m);
326                             while (! bcalc.evaluateBoolean(evaluator2)) {
327                                 if (! it.hasNext()) {
328                                     return false;
329                                 }
330                                 this.m = it.next();
331                                 evaluator2.setContext(this.m);
332                             }
333                             return true;
334                         }
335                         public Member[] next() {
336                             try {
337                                 return this.m;
338                             } finally {
339                                 this.m = null;
340                             }
341                         }
342                         public void remove() {
343                             throw new UnsupportedOperationException JavaDoc("remove");
344                         }
345                     };
346                 }
347             };
348             return result;
349         }
350     }
351
352
353     /**
354      * Returns an ListCalc.
355      *
356      * @param call
357      * @param compiler
358      * @return
359      */

360     protected Calc compileCallList(final ResolvedFunCall call,
361             ExpCompiler compiler) {
362         Calc ilcalc = compiler.compile(call.getArg(0),
363                 ExpCompiler.MUTABLE_LIST_LIST_RESULT_STYLE_ARRAY
364                 );
365         BooleanCalc bcalc = compiler.compileBoolean(call.getArg(1));
366         Calc[] calcs = new Calc[] {ilcalc, bcalc};
367
368         // Note that all of the ListCalc's return will be mutable
369
if (((SetType) ilcalc.getType()).getElementType() instanceof MemberType) {
370             switch (ilcalc.getResultStyle()) {
371             case LIST :
372                 return new ImMutableMemberListCalc(call, calcs);
373             case MUTABLE_LIST :
374                 return new MutableMemberListCalc(call, calcs);
375             }
376             throw ResultStyleException.generateBadType(
377                 new ResultStyle[] {
378                     ResultStyle.LIST,
379                     ResultStyle.MUTABLE_LIST
380                 },
381                 ilcalc.getResultStyle());
382
383         } else {
384
385             switch (ilcalc.getResultStyle()) {
386             case LIST :
387                 return new ImMutableMemberArrayListCalc(call, calcs);
388             case MUTABLE_LIST :
389                 return new MutableMemberArrayListCalc(call, calcs);
390             }
391             throw ResultStyleException.generateBadType(
392                 new ResultStyle[] {
393                     ResultStyle.LIST,
394                     ResultStyle.MUTABLE_LIST
395                 },
396                 ilcalc.getResultStyle());
397         }
398     }
399     private static abstract class BaseListCalc extends AbstractListCalc {
400         protected BaseListCalc(ResolvedFunCall call, Calc[] calcs) {
401             super(call, calcs);
402         }
403         public List JavaDoc evaluateList(Evaluator evaluator) {
404             ResolvedFunCall call = (ResolvedFunCall) exp;
405             // Use a native evaluator, if more efficient.
406
// TODO: Figure this out at compile time.
407
SchemaReader schemaReader = evaluator.getSchemaReader();
408             NativeEvaluator nativeEvaluator =
409                     schemaReader.getNativeSetEvaluator(
410                             call.getFunDef(), call.getArgs(), evaluator, this);
411             if (nativeEvaluator != null) {
412                 return (List JavaDoc) nativeEvaluator.execute(
413                         ResultStyle.MUTABLE_LIST);
414             } else {
415                 return makeList(evaluator);
416             }
417         }
418         protected abstract List JavaDoc makeList(Evaluator evaluator);
419
420         public boolean dependsOn(Dimension dimension) {
421             return anyDependsButFirst(getCalcs(), dimension);
422         }
423     }
424     //
425
// Member List Calcs
426
//
427
private static class MutableMemberListCalc extends BaseListCalc {
428         MutableMemberListCalc(ResolvedFunCall call, Calc[] calcs) {
429             super(call, calcs);
430         }
431         protected List JavaDoc makeList(Evaluator evaluator) {
432             Calc[] calcs = getCalcs();
433             ListCalc lcalc = (ListCalc) calcs[0];
434             BooleanCalc bcalc = (BooleanCalc) calcs[1];
435
436             final Evaluator evaluator2 = evaluator.push();
437             List JavaDoc members = lcalc.evaluateList(evaluator);
438
439             Iterator JavaDoc it = members.iterator();
440             while (it.hasNext()) {
441                 Member member = (Member) it.next();
442                 evaluator2.setContext(member);
443                 if (! bcalc.evaluateBoolean(evaluator2)) {
444                     it.remove();
445                 }
446             }
447             return members;
448         }
449     }
450     private static class ImMutableMemberListCalc extends BaseListCalc {
451         ImMutableMemberListCalc(ResolvedFunCall call, Calc[] calcs) {
452             super(call, calcs);
453         }
454         protected List JavaDoc makeList(Evaluator evaluator) {
455             Calc[] calcs = getCalcs();
456             ListCalc lcalc = (ListCalc) calcs[0];
457             BooleanCalc bcalc = (BooleanCalc) calcs[1];
458
459             final Evaluator evaluator2 = evaluator.push();
460             List JavaDoc members = lcalc.evaluateList(evaluator);
461
462             // Not mutable, must create new list
463
List JavaDoc result = new ArrayList JavaDoc();
464             for (int i = 0, count = members.size(); i < count; i++) {
465                 Member member = (Member) members.get(i);
466                 evaluator2.setContext(member);
467                 if (bcalc.evaluateBoolean(evaluator2)) {
468                     result.add(member);
469                 }
470             }
471             return result;
472         }
473     }
474     //
475
// Member[] List Calcs
476
//
477
private static class MutableMemberArrayListCalc extends BaseListCalc {
478         MutableMemberArrayListCalc(ResolvedFunCall call, Calc[] calcs) {
479             super(call, calcs);
480         }
481         protected List JavaDoc makeList(Evaluator evaluator) {
482             Calc[] calcs = getCalcs();
483             ListCalc lcalc = (ListCalc) calcs[0];
484             BooleanCalc bcalc = (BooleanCalc) calcs[1];
485
486             final Evaluator evaluator2 = evaluator.push();
487             List JavaDoc members = lcalc.evaluateList(evaluator);
488
489             Iterator JavaDoc it = members.iterator();
490             while (it.hasNext()) {
491                 Member[] member = (Member[]) it.next();
492                 evaluator2.setContext(member);
493                 if (! bcalc.evaluateBoolean(evaluator2)) {
494                     it.remove();
495                 }
496             }
497             return members;
498         }
499     }
500     private static class ImMutableMemberArrayListCalc extends BaseListCalc {
501         ImMutableMemberArrayListCalc(ResolvedFunCall call, Calc[] calcs) {
502             super(call, calcs);
503         }
504         protected List JavaDoc makeList(Evaluator evaluator) {
505             Calc[] calcs = getCalcs();
506             ListCalc lcalc = (ListCalc) calcs[0];
507             BooleanCalc bcalc = (BooleanCalc) calcs[1];
508
509             final Evaluator evaluator2 = evaluator.push();
510             List JavaDoc members = lcalc.evaluateList(evaluator);
511
512             // Not mutable, must create new list
513
List JavaDoc result = new ArrayList JavaDoc();
514             for (int i = 0, count = members.size(); i < count; i++) {
515                 Member[] member = (Member[]) members.get(i);
516                 evaluator2.setContext(member);
517                 if (bcalc.evaluateBoolean(evaluator2)) {
518                     result.add(member);
519                 }
520             }
521             return result;
522         }
523     }
524
525 /*
526  TODO: Previous code, remove if new code passes code review
527     public Calc compileCall(final ResolvedFunCall call, ExpCompiler compiler) {
528         final ListCalc listCalc = compiler.compileList(call.getArg(0));
529         final BooleanCalc calc = compiler.compileBoolean(call.getArg(1));
530         if (((SetType) listCalc.getType()).getElementType() instanceof MemberType) {
531             return new AbstractListCalc(call, new Calc[] {listCalc, calc}) {
532                 public List evaluateList(Evaluator evaluator) {
533                     // Use a native evaluator, if more efficient.
534                     // TODO: Figure this out at compile time.
535                     SchemaReader schemaReader = evaluator.getSchemaReader();
536                     NativeEvaluator nativeEvaluator =
537                             schemaReader.getNativeSetEvaluator(
538                                     call.getFunDef(), call.getArgs(), evaluator, this);
539                     if (nativeEvaluator != null) {
540                         return (List) nativeEvaluator.execute();
541                     }
542
543                     List members = listCalc.evaluateList(evaluator);
544                     List result = new ArrayList();
545                     Evaluator evaluator2 = evaluator.push();
546                     for (int i = 0, count = members.size(); i < count; i++) {
547                         Member member = (Member) members.get(i);
548                         evaluator2.setContext(member);
549                         if (calc.evaluateBoolean(evaluator2)) {
550                             result.add(member);
551                         }
552                     }
553                     return result;
554                 }
555
556                 public boolean dependsOn(Dimension dimension) {
557                     return anyDependsButFirst(getCalcs(), dimension);
558                 }
559             };
560         } else {
561             return new AbstractListCalc(call, new Calc[] {listCalc, calc}) {
562                 public List evaluateList(Evaluator evaluator) {
563                     // Use a native evaluator, if more efficient.
564                     // TODO: Figure this out at compile time.
565                     SchemaReader schemaReader = evaluator.getSchemaReader();
566                     NativeEvaluator nativeEvaluator =
567                             schemaReader.getNativeSetEvaluator(
568                                     call.getFunDef(), call.getArgs(), evaluator, this);
569                     if (nativeEvaluator != null) {
570                         return (List) nativeEvaluator.execute();
571                     }
572
573                     List tupleList = listCalc.evaluateList(evaluator);
574                     List result = new ArrayList();
575                     Evaluator evaluator2 = evaluator.push();
576                     for (int i = 0, count = tupleList.size(); i < count; i++) {
577                         Member[] members = (Member []) tupleList.get(i);
578                         evaluator2.setContext(members);
579                         if (calc.evaluateBoolean(evaluator2)) {
580                             result.add(members);
581                         }
582                     }
583                     return result;
584                 }
585
586                 public boolean dependsOn(Dimension dimension) {
587                     return anyDependsButFirst(getCalcs(), dimension);
588                 }
589             };
590         }
591     }
592 */

593 }
594
595 // End FilterFunDef.java
596
Popular Tags