KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tonbeller > jpivot > mondrian > MondrianQuaxUti


1 /*
2  * ====================================================================
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) 2003-2004 TONBELLER AG.
7  * All Rights Reserved.
8  * You must accept the terms of that agreement to use this software.
9  * ====================================================================
10  *
11  *
12  */

13
14 package com.tonbeller.jpivot.mondrian;
15
16 import java.util.ArrayList JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.List JavaDoc;
19
20 import mondrian.olap.Exp;
21 import mondrian.olap.FunCall;
22 import mondrian.olap.OlapElement;
23 import mondrian.olap.SchemaReader;
24 import mondrian.olap.Syntax;
25 import mondrian.mdx.DimensionExpr;
26 import mondrian.mdx.HierarchyExpr;
27 import mondrian.mdx.LevelExpr;
28 import mondrian.mdx.MemberExpr;
29 import mondrian.mdx.UnresolvedFunCall;
30
31 import org.apache.log4j.Logger;
32
33 import com.tonbeller.jpivot.olap.model.Dimension;
34 import com.tonbeller.jpivot.olap.model.Hierarchy;
35 import com.tonbeller.jpivot.olap.model.Level;
36 import com.tonbeller.jpivot.olap.model.Member;
37 import com.tonbeller.jpivot.olap.query.Quax;
38 import com.tonbeller.jpivot.olap.query.QuaxUti;
39 import com.tonbeller.jpivot.olap.query.SetExp;
40 import com.tonbeller.jpivot.olap.query.Quax.CannotHandleException;
41
42 /**
43  * Utility Functions for Quax
44  */

45 public class MondrianQuaxUti implements QuaxUti {
46
47   static Logger logger = Logger.getLogger(MondrianQuaxUti.class);
48
49   private MondrianModel model = null;
50
51   private SchemaReader scr;
52
53   /**
54    * c'tor
55    *
56    * @param model
57    */

58   MondrianQuaxUti(MondrianModel model) {
59     this.model = model;
60     scr = model.getConnection().getSchemaReader();
61   }
62
63   private static boolean isCallTo(FunCall f, String JavaDoc name) {
64     return f.getFunName().compareToIgnoreCase(name) == 0;
65   }
66
67   /**
68    * check whether a Funcall does NOT resolve to top level of hierarchy
69    *
70    * @param oFun
71    * @return
72    */

73   public boolean isFunCallNotTopLevel(Object JavaDoc oFun) throws CannotHandleException {
74     FunCall f = (FunCall) oFun;
75     if (isCallTo(f, "Children")) {
76       return true; // children *not* top level
77
} else if (isCallTo(f, "Descendants")) {
78       return true; // descendants*not* top level
79
} else if (isCallTo(f, "Members")) {
80       mondrian.olap.Level lev = getLevelArg(f, 0);
81       return (lev.getDepth() > 0);
82     } else if (isCallTo(f, "Union")) {
83       if (isFunCallNotTopLevel(f.getArg(0)))
84         return true;
85       return isFunCallNotTopLevel(f.getArg(1));
86     } else if (isCallTo(f, "{}")) {
87       for (int i = 0; i < f.getArgs().length; i++) {
88         if (!isMemberOnToplevel(getMemberArg(f, i)))
89           return true;
90       }
91       return false;
92     }
93     throw new Quax.CannotHandleException(f.getFunName());
94   }
95
96   /**
97    * @return true if member is on top level (has no parent)
98    * @see com.tonbeller.jpivot.olap.query.QuaxUti#isMemberOnToplevel
99    */

100   public boolean isMemberOnToplevel(Object JavaDoc oMem) {
101     mondrian.olap.Member m = ((MondrianMember) oMem).getMonMember();
102     return isMemberOnToplevel(m);
103   }
104
105   /**
106    */

107   private boolean isMemberOnToplevel(mondrian.olap.Member m) {
108     if (m.getLevel().getDepth() > 0)
109       return false;
110     else
111       return true;
112   }
113
114   /**
115    *
116    * @param oFun
117    * @param member
118    * @return true if FunCall matches member
119    */

120   public boolean isMemberInFunCall(Object JavaDoc oFun, Member member) throws CannotHandleException {
121     FunCall f = (FunCall) oFun;
122     mondrian.olap.Member m = ((MondrianMember) member).getMonMember();
123     return isMemberInFunCall(f, m);
124   }
125
126   /**
127    *
128    * @param f
129    * @param m
130    * @return true if FunCall matches member
131    */

132   private boolean isMemberInFunCall(FunCall f, mondrian.olap.Member m) throws CannotHandleException {
133     if (isCallTo(f, "Children")) {
134       return isMemberInChildren(f, m);
135     } else if (isCallTo(f, "Descendants")) {
136       return isMemberInDescendants(f, m);
137     } else if (isCallTo(f, "Members")) {
138       return isMemberInLevel(f, m);
139     } else if (isCallTo(f, "Union")) {
140       return isMemberInUnion(f, m);
141     } else if (isCallTo(f, "{}")) {
142       return isMemberInSet(f, m);
143     }
144     throw new Quax.CannotHandleException(f.getFunName());
145   }
146
147   /**
148    * @param f
149    * Children FunCall
150    * @param mSearch
151    * member to search for
152    * @return true if member mSearch is in set of children function
153    */

154   private boolean isMemberInChildren(FunCall f, mondrian.olap.Member mSearch) {
155     if (mSearch.isCalculatedInQuery())
156       return false;
157     mondrian.olap.Member parent = getMemberArg(f, 0);
158     if (parent.equals(mSearch.getParentMember()))
159       return true;
160     return false;
161   }
162
163   /**
164    * @param f
165    * Descendants FunCall
166    * @param mSearch
167    * member to search for
168    * @return true if member mSearch is in set of Descendants function
169    */

170   private boolean isMemberInDescendants(FunCall f, mondrian.olap.Member mSearch) {
171     if (mSearch.isCalculatedInQuery())
172       return false;
173     mondrian.olap.Member ancestor = getMemberArg(f, 0);
174     mondrian.olap.Level level = getLevelArg(f, 1);
175     if (mSearch.equals(ancestor))
176       return false;
177     if (!mSearch.isChildOrEqualTo(ancestor))
178       return false;
179     if (level.equals(mSearch.getLevel()))
180       return true;
181     return false;
182   }
183
184   /**
185    * @param f
186    * Members FunCall
187    * @param mSearch
188    * member to search for
189    * @return true if member mSearch is in set of Members function
190    */

191   private boolean isMemberInLevel(FunCall f, mondrian.olap.Member mSearch) {
192     if (mSearch.isCalculatedInQuery())
193       return false;
194     mondrian.olap.Level level = getLevelArg(f, 0);
195     if (level.equals(mSearch.getLevel()))
196       return true;
197     return false;
198   }
199
200   /**
201    * @param f
202    * Set FunCall
203    * @param mSearch
204    * member to search for
205    * @return true if member mSearch is in set function
206    */

207   private boolean isMemberInSet(FunCall f, mondrian.olap.Member mSearch) {
208     // set of members expected
209
for (int i = 0; i < f.getArgs().length; i++) {
210       mondrian.olap.Member m = getMemberArg(f, i);
211       if (m.equals(mSearch))
212         return true;
213     }
214     return false;
215   }
216
217   /**
218    * @param f
219    * Union FunCall
220    * @param mSearch
221    * member to search for
222    * @return true if member mSearch is in set function
223    */

224   private boolean isMemberInUnion(FunCall f, mondrian.olap.Member mSearch)
225       throws CannotHandleException {
226     // Unions may be nested
227
for (int i = 0; i < 2; i++) {
228       FunCall fChild = (FunCall) f.getArg(i);
229       if (isMemberInFunCall(fChild, mSearch))
230         return true;
231     }
232     return false;
233   }
234
235   /**
236    *
237    * @param oFun
238    * @param member
239    * @return true if FunCall contains child of member
240    */

241   public boolean isChildOfMemberInFunCall(Object JavaDoc oFun, Member member) throws CannotHandleException {
242     FunCall f = (FunCall) oFun;
243     mondrian.olap.Member m = ((MondrianMember) member).getMonMember();
244     if (isCallTo(f, "Children")) {
245       return (getMemberArg(f, 0).equals(m));
246     } else if (isCallTo(f, "Descendants")) {
247       mondrian.olap.Member ancestor = getMemberArg(f, 0);
248       mondrian.olap.Level lev = getLevelArg(f, 1);
249       mondrian.olap.Level parentLevel = lev.getParentLevel();
250       if (parentLevel != null && m.getLevel().equals(parentLevel)) {
251         if (m.isChildOrEqualTo(ancestor))
252           return true;
253         else
254           return false;
255       } else
256         return false;
257     } else if (isCallTo(f, "Members")) {
258       mondrian.olap.Level lev = getLevelArg(f, 0);
259       mondrian.olap.Level parentLevel = lev.getParentLevel();
260       if (parentLevel != null && m.getLevel().equals(parentLevel))
261         return true;
262       else
263         return false;
264     } else if (isCallTo(f, "Union")) {
265       if (isChildOfMemberInFunCall(f.getArg(0), member))
266         return true;
267       else
268         return isChildOfMemberInFunCall(f.getArg(1), member);
269     } else if (isCallTo(f, "{}")) {
270       for (int i = 0; i < f.getArgs().length; i++) {
271         mondrian.olap.Member mm = getMemberArg(f, i);
272         if (mm.isCalculatedInQuery())
273           continue;
274         mondrian.olap.Member mmp = mm.getParentMember();
275         if (mmp != null && mmp.equals(m))
276           return true;
277       }
278       return false;
279     }
280     throw new Quax.CannotHandleException(f.getFunName());
281   }
282
283   private static mondrian.olap.Level getLevelArg(FunCall f, final int index) {
284     return ((LevelExpr) f.getArg(index)).getLevel();
285   }
286
287   private static mondrian.olap.Member getMemberArg(FunCall f, int index) {
288     return ((MemberExpr) f.getArg(index)).getMember();
289   }
290
291   /**
292    * @param oFun
293    * @param member
294    * @return true if FunCall contains descendants of member
295    */

296   public boolean isDescendantOfMemberInFunCall(Object JavaDoc oFun, Member member)
297       throws CannotHandleException {
298     FunCall f = (FunCall) oFun;
299     mondrian.olap.Member m = ((MondrianMember) member).getMonMember();
300     if (isCallTo(f, "Children")) {
301       mondrian.olap.Member mExp = getMemberArg(f, 0);
302       return (mExp.isChildOrEqualTo(m));
303     } else if (isCallTo(f, "Descendants")) {
304       mondrian.olap.Member mExp = getMemberArg(f, 0);
305       return (mExp.isChildOrEqualTo(m));
306     } else if (isCallTo(f, "Members")) {
307       mondrian.olap.Level levExp = getLevelArg(f, 0);
308       return (levExp.getDepth() > m.getLevel().getDepth());
309     } else if (isCallTo(f, "Union")) {
310       if (isDescendantOfMemberInFunCall(f.getArg(0), member))
311         return true;
312       else
313         return isDescendantOfMemberInFunCall(f.getArg(1), member);
314     } else if (isCallTo(f, "{}")) {
315       for (int i = 0; i < f.getArgs().length; i++) {
316         mondrian.olap.Member mExp = getMemberArg(f, i);
317         if (mExp.isCalculatedInQuery())
318           continue;
319         if (!m.equals(mExp) && mExp.isChildOrEqualTo(m))
320           return true;
321       }
322       return false;
323     }
324     throw new Quax.CannotHandleException(f.getFunName());
325   }
326
327   /**
328    * remove descendants of member from set Funcall this function is only called if there *are*
329    * descendants of member in funcall
330    *
331    * @param oFun
332    * @param member
333    * @return the remainder after descendants were removed
334    */

335   public Object JavaDoc removeDescendantsFromFunCall(Object JavaDoc oFun, Member member)
336       throws CannotHandleException {
337     FunCall f = (FunCall) oFun;
338     mondrian.olap.Member m = ((MondrianMember) member).getMonMember();
339     if (isCallTo(f, "Children")) {
340       // as we know, that there is a descendent of m in x.children,
341
// we know that *all* x.children are descendants of m
342
return null;
343     } else if (isCallTo(f, "Descendants")) {
344       // as we know, that there is a descendent of m in x.descendants
345
// we know that *all* x.descendants are descendants of m
346
return null;
347     } else if (isCallTo(f, "Members")) {
348       mondrian.olap.Level levExp = getLevelArg(f, 0);
349       mondrian.olap.Member[] members = scr.getLevelMembers(levExp, false);
350       List JavaDoc remainder = new ArrayList JavaDoc();
351       for (int i = 0; i < members.length; i++) {
352         if (!members[i].isChildOrEqualTo(m))
353           remainder.add(members[i]);
354       }
355       return createMemberSet(remainder);
356     } else if (isCallTo(f, "{}")) {
357       List JavaDoc remainder = new ArrayList JavaDoc();
358       for (int i = 0; i < f.getArgs().length; i++) {
359         mondrian.olap.Member mExp = getMemberArg(f, i);
360         if (mExp.isCalculatedInQuery())
361           continue;
362         if (mExp.equals(m) || !mExp.isChildOrEqualTo(m))
363           remainder.add(mExp);
364       }
365       return createMemberSet(remainder);
366     } else if (isCallTo(f, "Union")) {
367       // TODO XMLA
368
Exp[] uargs = new Exp[2];
369       uargs[0] = (Exp) removeDescendantsFromFunCall(f.getArg(0), member);
370       uargs[1] = (Exp) removeDescendantsFromFunCall(f.getArg(1), member);
371       if (uargs[0] == null && uargs[1] == null)
372         return null;
373       if (uargs[1] == null)
374         return uargs[0];
375       if (uargs[0] == null)
376         return uargs[1];
377       if (uargs[0] instanceof mondrian.olap.Member) {
378         Exp e = uargs[0];
379         uargs[0] = new UnresolvedFunCall("{}", Syntax.Braces, new Exp[] { e});
380       }
381       if (uargs[1] instanceof mondrian.olap.Member) {
382         Exp e = uargs[1];
383         uargs[1] = new UnresolvedFunCall("{}", Syntax.Braces, new Exp[] { e});
384       }
385       return new UnresolvedFunCall("Union", uargs);
386     }
387     throw new Quax.CannotHandleException(f.getFunName());
388   }
389
390   /**
391    * generate an object for a list of members
392    *
393    * @param mList
394    * list of members
395    * @return null for empty list, single member or set function otherwise
396    * @see com.tonbeller.jpivot.olap.query.QuaxUti#createMemberSet(java.util.List)
397    */

398   public Object JavaDoc createMemberSet(List JavaDoc mList) {
399     if (mList.size() == 0)
400       return null;
401     else if (mList.size() == 1)
402       return mList.get(0);
403     else {
404       Exp[] remExps = (Exp[]) mList.toArray(new Exp[0]);
405       return new UnresolvedFunCall("{}", Syntax.Braces, remExps);
406     }
407
408   }
409
410   /**
411    * remove children FunCall from Union should never be called
412    *
413    * @param f
414    * @param monMember
415    */

416   static FunCall removeChildrenFromUnion(FunCall f, mondrian.olap.Member monMember) {
417
418     FunCall f1 = (FunCall) f.getArg(0);
419     FunCall f2 = (FunCall) f.getArg(1);
420     if (isCallTo(f1, "Children") && getMemberArg(f1, 0).equals(monMember)) { return f2; }
421     if (isCallTo(f2, "Children") && getMemberArg(f1, 0).equals(monMember)) { return f1; }
422     FunCall f1New = f1;
423     if (isCallTo(f1, "Union"))
424       f1New = removeChildrenFromUnion(f1, monMember);
425     FunCall f2New = f2;
426     if (isCallTo(f2, "Union"))
427       f2New = removeChildrenFromUnion(f2, monMember);
428
429     if (f1 == f1New && f2 == f2New)
430       return f;
431
432     return new UnresolvedFunCall("Union", new Exp[] { f1New, f2New});
433   }
434
435   /**
436    * return member for exp object
437    *
438    * @see QuaxUti#memberForObj(java.lang.Object)
439    */

440   public Member memberForObj(Object JavaDoc oExp) {
441     mondrian.olap.Member monMember = toMember(oExp);
442     Member member = model.lookupMemberByUName(monMember.getUniqueName());
443     return member;
444   }
445
446   /**
447    * @return exp object for member
448    * @see QuaxUti#objForMember(com.tonbeller.jpivot.olap.model.Member)
449    */

450   public Object JavaDoc objForMember(Member member) {
451     return ((MondrianMember) member).getMonMember();
452   }
453
454   /**
455    * @return exp object for dimension
456    * @see com.tonbeller.jpivot.olap.query.QuaxUti#objForDim
457    */

458   public Object JavaDoc objForDim(Dimension dim) {
459     return ((MondrianDimension) dim).getMonDimension();
460   }
461
462   /**
463    * return a members dimension
464    *
465    * @see QuaxUti#dimForMember(com.tonbeller.jpivot.olap.model.Member)
466    */

467   public Dimension dimForMember(Member member) {
468     mondrian.olap.Member m = ((MondrianMember) member).getMonMember();
469     mondrian.olap.Dimension monDim = m.getDimension();
470     return model.lookupDimension(monDim.getUniqueName());
471   }
472
473   /**
474    * @return a members hierarchy
475    * @see QuaxUti#hierForMember(com.tonbeller.jpivot.olap.model.Member)
476    */

477   public Hierarchy hierForMember(Member member) {
478     mondrian.olap.Member m = ((MondrianMember) member).getMonMember();
479     mondrian.olap.Hierarchy monHier = m.getHierarchy();
480     return model.lookupHierarchy(monHier.getUniqueName());
481   }
482
483   /**
484    * @param oLevel
485    * expression object representing level
486    * @return Level for given Expression Object
487    * @see QuaxUti#LevelForObj(java.lang.Object)
488    */

489   public Level LevelForObj(Object JavaDoc oLevel) {
490     if (oLevel instanceof LevelExpr)
491       oLevel = ((LevelExpr) oLevel).getLevel();
492     mondrian.olap.Level monLevel = (mondrian.olap.Level)oLevel;
493     return model.lookupLevel(monLevel.getUniqueName());
494   }
495
496   /**
497    * @return count of a FunCall's arguments
498    * @see QuaxUti#funCallArgCount(java.lang.Object)
499    */

500   public int funCallArgCount(Object JavaDoc oFun) {
501     FunCall f = (FunCall) oFun;
502     return f.getArgs().length;
503   }
504
505   /**
506    * return a FunCalls argument of given index
507    *
508    * @see QuaxUti#funCallArg(java.lang.Object, int)
509    */

510   public Object JavaDoc funCallArg(Object JavaDoc oFun, int index) {
511     FunCall f = (FunCall) oFun;
512     final Exp arg = f.getArg(index);
513     final OlapElement element = fromExp(arg);
514     return element == null ? (Object JavaDoc) arg : element;
515   }
516
517   /**
518    * @return function name
519    * @see com.tonbeller.jpivot.olap.query.QuaxUti#funCallName
520    */

521   public String JavaDoc funCallName(Object JavaDoc oFun) {
522     return ((FunCall) oFun).getFunName();
523   }
524
525   /**
526    * check level and add a members descendatns to list
527    */

528   public void addMemberDescendants(List JavaDoc list, Member member, Level level, int[] maxLevel) {
529     mondrian.olap.Member m = ((MondrianMember) member).getMonMember();
530     mondrian.olap.Level lev = ((MondrianLevel) level).getMonLevel();
531     int parentLevel = lev.getDepth() + 1;
532     if (parentLevel < maxLevel[0])
533       return;
534     if (parentLevel > maxLevel[0]) {
535       maxLevel[0] = parentLevel;
536       list.clear();
537     }
538     AddDescendants: if (parentLevel > 0) {
539       // do nothing if already on List
540
for (Iterator JavaDoc iter = list.iterator(); iter.hasNext();) {
541         Exp exp = (Exp) iter.next();
542         if (exp instanceof FunCall) {
543           FunCall f = (FunCall) exp;
544           if (isCallTo(f, "Descendants") && getMemberArg(f, 0).equals(m)) {
545             break AddDescendants;
546           }
547         }
548       }
549       UnresolvedFunCall fChildren = new UnresolvedFunCall("Descendants", Syntax.Function, new Exp[] { new MemberExpr(m), new LevelExpr(lev)});
550       /*
551        * // remove all existing Descendants of m from worklist for (Iterator iter =
552        * workList.iterator(); iter.hasNext();) { Exp exp = (Exp) iter.next(); if (exp instanceof
553        * mondrian.olap.Member && ((MemberExpr) exp).isChildOrEqualTo(m)) iter.remove(); }
554        */

555       list.add(fChildren);
556     } // AddDescendants
557
}
558
559   /**
560    * @see QuaxUti#getParentMember(java.lang.Object)
561    */

562   public Member getParentMember(Object JavaDoc oExp) {
563     mondrian.olap.Member m = toMember(oExp);
564     mondrian.olap.Member monParent = m.getParentMember();
565     if (monParent == null)
566       return null;
567     Member parent = model.lookupMemberByUName(monParent.getUniqueName());
568     return parent;
569   }
570
571   /**
572    * create FunCall
573    *
574    * @see QuaxUti#createFunCall(java.lang.String, java.lang.Object[], int)
575    */

576   public Object JavaDoc createFunCall(String JavaDoc function, Object JavaDoc[] args, int funType) {
577     Exp[] expArgs = new Exp[args.length];
578     for (int i = 0; i < expArgs.length; i++) {
579       expArgs[i] = toExp(args[i]);
580     }
581     Syntax syntax;
582     switch (funType) {
583     case QuaxUti.FUNTYPE_BRACES:
584       syntax = Syntax.Braces;
585       break;
586     case QuaxUti.FUNTYPE_PROPERTY:
587       syntax = Syntax.Property;
588       break;
589     case QuaxUti.FUNTYPE_TUPLE:
590       syntax = Syntax.Parentheses;
591       break;
592     case QuaxUti.FUNTYPE_INFIX:
593       syntax = Syntax.Infix;
594       break;
595     default:
596       syntax = Syntax.Function;
597     }
598     return new UnresolvedFunCall(function, syntax, expArgs);
599   }
600
601   /**
602    * @return true, if an expression is a FunCall to e specific function
603    * @see QuaxUti#isFunCallTo(Object, String)
604    */

605   public boolean isFunCallTo(Object JavaDoc oExp, String JavaDoc function) {
606     return isCallTo((FunCall) oExp, function);
607   }
608
609   /**
610    * @return true if member (2.arg) is child of Member (1.arg)
611    * @see com.tonbeller.jpivot.olap.query.QuaxUti#checkParent
612    */

613   public boolean checkParent(Member pMember, Object JavaDoc cMemObj) {
614     mondrian.olap.Member mc = toMember(cMemObj);
615     if (mc.isCalculatedInQuery())
616       return false;
617     mondrian.olap.Member mp = mc.getParentMember();
618     if (mp == null)
619       return false;
620     else
621       return mp.equals(((MondrianMember) pMember).getMonMember());
622   }
623
624     /**
625    * @return true if member (1.arg) is child of Member (2.arg)
626    * @see com.tonbeller.jpivot.olap.query.QuaxUti#checkParent
627    */

628   public boolean checkChild(Member cMember, Object JavaDoc pMemObj) {
629     mondrian.olap.Member mc = ((MondrianMember) cMember).getMonMember();
630     if (mc.isCalculatedInQuery())
631       return false;
632     mondrian.olap.Member mp = mc.getParentMember();
633     if (mp == null)
634       return false;
635     else
636       return mp.equals(pMemObj);
637   }
638
639   /**
640    * return true if Member (2.arg) is descendant of Member (1.arg)
641    *
642    * @see QuaxUti#isDescendantOfMemberInFunCall(Object, com.tonbeller.jpivot.olap.model.Member)
643    */

644   public boolean checkDescendantM(Member aMember, Member dMember) {
645     mondrian.olap.Member monMember = ((MondrianMember) aMember).getMonMember();
646     mondrian.olap.Member monDesc = ((MondrianMember) dMember).getMonMember();
647     if (monDesc.isCalculatedInQuery() || monDesc.equals(monMember))
648       return false;
649     return monDesc.isChildOrEqualTo(monMember);
650   }
651
652   /**
653    * return true if Expression (2.arg) is descendant of Member (1.arg)
654    *
655    * @see QuaxUti#isDescendantOfMemberInFunCall(Object, com.tonbeller.jpivot.olap.model.Member)
656    */

657   public boolean checkDescendantO(Member aMember, Object JavaDoc oMember) {
658     mondrian.olap.Member monMember = ((MondrianMember) aMember).getMonMember();
659     mondrian.olap.Member monDesc = toMember(oMember);
660     if (monDesc.isCalculatedInQuery() || monDesc.equals(monMember))
661       return false;
662     return monDesc.isChildOrEqualTo(monMember);
663   }
664
665   /**
666    * check level and add a levels members to list
667    */

668   public void addLevelMembers(List JavaDoc list, Level level, int[] maxLevel) {
669     mondrian.olap.Level lev = ((MondrianLevel) level).getMonLevel();
670     int iLevel = lev.getDepth();
671     if (iLevel < maxLevel[0])
672       return;
673     if (iLevel > maxLevel[0]) {
674       maxLevel[0] = iLevel;
675       list.clear();
676     }
677     AddMembers: if (iLevel > 0) {
678       // do nothing if already on List
679
for (Iterator JavaDoc iter = list.iterator(); iter.hasNext();) {
680         Exp exp = (Exp) iter.next();
681         if (exp instanceof FunCall) {
682           FunCall f = (FunCall) exp;
683           if (isCallTo(f, "Members")) {
684             break AddMembers;
685           }
686         }
687       }
688       UnresolvedFunCall fMembers = new UnresolvedFunCall("Members", Syntax.Property, new Exp[] { new LevelExpr(lev)});
689       /*
690        * // remove all existing level members from worklist for (Iterator iter =
691        * workList.iterator(); iter.hasNext();) { Exp exp = (Exp) iter.next(); if (exp instanceof
692        * mondrian.olap.Member && ((MemberExpr) exp).getLevel().equals(lev)) iter.remove(); }
693        */

694       list.add(fMembers);
695     } // AddDescendants
696
}
697
698   /**
699    * determine hierarchy for Exp
700    *
701    * @param oExp
702    * @return hierarchy
703    */

704   public Hierarchy hierForExp(Object JavaDoc exp) throws CannotHandleException {
705     if (exp instanceof MemberExpr)
706       exp = ((MemberExpr)exp).getMember();
707     else if (exp instanceof LevelExpr)
708       exp = ((LevelExpr)exp).getLevel();
709     else if (exp instanceof HierarchyExpr)
710       exp = ((HierarchyExpr)exp).getHierarchy();
711     else if (exp instanceof DimensionExpr)
712       exp = ((DimensionExpr)exp).getDimension();
713     if (exp instanceof mondrian.olap.OlapElement)
714       return model.lookupHierarchy(((mondrian.olap.OlapElement) exp).getHierarchy().getUniqueName());
715     
716     if (exp instanceof SetExp) {
717       // set expression generated by CalcSet extension
718
SetExp set = (SetExp) exp;
719       return set.getHier();
720     }
721
722     // must be FunCall
723
FunCall f = (FunCall) exp;
724     if (isCallTo(f, "Children")) {
725       mondrian.olap.Member m = getMemberArg(f, 0);
726       return model.lookupHierarchy(m.getHierarchy().getUniqueName());
727     } else if (isCallTo(f, "Descendants")) {
728       mondrian.olap.Member m = getMemberArg(f, 0);
729       return model.lookupHierarchy(m.getHierarchy().getUniqueName());
730     } else if (isCallTo(f, "Members")) {
731       mondrian.olap.Level lev = getLevelArg(f, 0);
732       return model.lookupHierarchy(lev.getHierarchy().getUniqueName());
733     } else if (isCallTo(f, "Union")) {
734       // continue with first set
735
return hierForExp(f.getArg(0));
736     } else if (isCallTo(f, "{}")) {
737       mondrian.olap.Member m = getMemberArg(f, 0);
738       return model.lookupHierarchy(m.getHierarchy().getUniqueName());
739     } else if (isCallTo(f, "TopCount") || isCallTo(f, "BottomCount") || isCallTo(f, "TopPercent")
740         || isCallTo(f, "BottomPercent") || isCallTo(f, "Filter")) {
741       // continue with base set of top bottom function
742
return hierForExp(f.getArg(0));
743     }
744     throw new Quax.CannotHandleException(f.getFunName());
745   }
746
747   /**
748    * @return the depth of a member's level
749    * @see QuaxUti#levelDepthForMember(java.lang.Object)
750    */

751   public int levelDepthForMember(Object JavaDoc oExp) {
752     mondrian.olap.Member m = toMember(oExp);
753     mondrian.olap.Level level = m.getLevel();
754     return level.getDepth();
755   }
756
757   /**
758    * @return an Expression Object for the top level members of an hierarchy
759    * @see QuaxUti#topLevelMembers(com.tonbeller.jpivot.olap.model.Hierarchy, boolean)
760    */

761   public Object JavaDoc topLevelMembers(Hierarchy hier, boolean expandAllMember) {
762     return MondrianUtil.topLevelMembers(((MondrianHierarchy) hier).getMonHierarchy(),
763         expandAllMember, scr);
764   }
765
766   /**
767    * @return the parent level of a given level
768    * @see QuaxUti#getParentLevel(com.tonbeller.jpivot.olap.model.Level)
769    */

770   public Level getParentLevel(Level level) {
771     mondrian.olap.Level monLevel = ((MondrianLevel) level).getMonLevel();
772     mondrian.olap.Level monParentLevel = monLevel.getParentLevel();
773     return model.lookupLevel(monParentLevel.getUniqueName());
774   }
775
776   public Exp toExp(Object JavaDoc o) {
777     if (o instanceof OlapElement) {
778       if (o instanceof mondrian.olap.Member) {
779         return new MemberExpr((mondrian.olap.Member) o);
780       } else if (o instanceof mondrian.olap.Level) {
781         return new LevelExpr((mondrian.olap.Level) o);
782       } else if (o instanceof mondrian.olap.Hierarchy) {
783         return new HierarchyExpr((mondrian.olap.Hierarchy) o);
784       } else {
785         return new DimensionExpr((mondrian.olap.Dimension) o);
786       }
787     } else {
788       return (Exp) o;
789     }
790   }
791
792   private OlapElement fromExp(Exp e) {
793     if (e instanceof MemberExpr) {
794       MemberExpr memberExpr = (MemberExpr) e;
795       return memberExpr.getMember();
796     } else if (e instanceof LevelExpr) {
797       LevelExpr levelExpr = (LevelExpr) e;
798       return levelExpr.getLevel();
799     } else if (e instanceof HierarchyExpr) {
800       HierarchyExpr hierarchyExpr = (HierarchyExpr) e;
801       return hierarchyExpr.getHierarchy();
802     } else if (e instanceof DimensionExpr) {
803       DimensionExpr dimensionExpr = (DimensionExpr) e;
804       return dimensionExpr.getDimension();
805     } else {
806       return null;
807     }
808   }
809
810     /**
811    * @param oExp
812    * expression
813    * @return true, if exp is member
814    * @see QuaxUti#isMember(java.lang.Object)
815    */

816   public boolean isMember(Object JavaDoc oExp) {
817     return (oExp instanceof mondrian.olap.Member ||
818             oExp instanceof MemberExpr);
819   }
820
821   private mondrian.olap.Member toMember(Object JavaDoc cMemObj) {
822     if (cMemObj instanceof mondrian.olap.Member) {
823       return (mondrian.olap.Member) cMemObj;
824     } else {
825       MemberExpr memberExpr = (MemberExpr) cMemObj;
826       return memberExpr.getMember();
827     }
828   }
829
830   /**
831    * @see com.tonbeller.jpivot.olap.query.QuaxUti#isFunCall
832    */

833   public boolean isFunCall(Object JavaDoc oExp) {
834     return oExp instanceof mondrian.olap.FunCall;
835   }
836
837   /**
838    * check level and add a member's parents children to list
839    */

840   public void addMemberSiblings(List JavaDoc list, Member member, int[] maxLevel) {
841     mondrian.olap.Member m = ((MondrianMember) member).getMonMember();
842     int level = m.getLevel().getDepth();
843     if (level < maxLevel[0])
844       return;
845     if (level > maxLevel[0]) {
846       maxLevel[0] = level;
847       list.clear();
848     }
849     AddSiblings: if (level > 0) {
850       mondrian.olap.Member parent = m.getParentMember();
851       // do nothing if already on List
852
for (Iterator JavaDoc iter = list.iterator(); iter.hasNext();) {
853         Exp exp = (Exp) iter.next();
854         if (isFunCall(exp)) {
855           FunCall f = (FunCall) exp;
856           if (isCallTo(f, "Children") && getMemberArg(f, 0).equals(parent)) {
857             break AddSiblings;
858           }
859         }
860       }
861       UnresolvedFunCall fSiblings = new UnresolvedFunCall("Children", Syntax.Property, new Exp[] { new MemberExpr(parent)});
862       /*
863        * // remove all existing children of parent from worklist; for (Iterator iter =
864        * workList.iterator(); iter.hasNext();) { Exp exp = (Exp) iter.next(); if (exp instanceof
865        * mondrian.olap.Member && ((MemberExpr) exp).getParentMember().equals(parent))
866        * iter.remove(); }
867        */

868       list.add(fSiblings);
869     } // AddSiblings
870
}
871
872   /**
873    * check level and add a member to list
874    */

875   public void addMemberChildren(List JavaDoc list, Member member, int[] maxLevel) {
876     mondrian.olap.Member m = ((MondrianMember) member).getMonMember();
877     int childLevel = m.getLevel().getDepth() + 1;
878     if (childLevel < maxLevel[0])
879       return;
880     if (childLevel > maxLevel[0]) {
881       maxLevel[0] = childLevel;
882       list.clear();
883     }
884     AddChildren: if (childLevel > 0) {
885       // do nothing if already on List
886
for (Iterator JavaDoc iter = list.iterator(); iter.hasNext();) {
887         Exp exp = (Exp) iter.next();
888         if (isFunCall(exp)) {
889           FunCall f = (FunCall) exp;
890           if (isCallTo(f, "Children") && getMemberArg(f, 0).equals(m)) {
891             break AddChildren;
892           }
893         }
894       }
895       UnresolvedFunCall fChildren = new UnresolvedFunCall("Children", Syntax.Property, new Exp[] { new MemberExpr(m)});
896       /*
897        * // remove all existing children of m from worklist; for (Iterator iter =
898        * workList.iterator(); iter.hasNext();) { Exp exp = (Exp) iter.next(); if (exp instanceof
899        * mondrian.olap.Member && ((MemberExpr) exp).getParentMember().equals(m))
900        * iter.remove(); }
901        */

902       list.add(fChildren);
903     } // AddChildren
904
}
905
906   /**
907    * check level and add a member's uncles to list
908    */

909   public void addMemberUncles(List JavaDoc list, Member member, int[] maxLevel) {
910     mondrian.olap.Member m = ((MondrianMember) member).getMonMember();
911     int parentLevel = m.getLevel().getDepth() - 1;
912     if (parentLevel < maxLevel[0])
913       return;
914     if (parentLevel > maxLevel[0]) {
915       maxLevel[0] = parentLevel;
916       list.clear();
917     }
918     AddUncels: if (parentLevel > 0) {
919       mondrian.olap.Member parent = m.getParentMember();
920       mondrian.olap.Member grandPa = parent.getParentMember();
921
922       // do nothing if already on List
923
for (Iterator JavaDoc iter = list.iterator(); iter.hasNext();) {
924         Exp exp = (Exp) iter.next();
925         if (isFunCall(exp)) {
926           FunCall f = (FunCall) exp;
927           if (isCallTo(f, "Children") && getMemberArg(f, 0).equals(grandPa)) {
928             break AddUncels; // already there
929
}
930         }
931       }
932       UnresolvedFunCall fUncles = new UnresolvedFunCall("Children", Syntax.Property, new Exp[] { new MemberExpr(grandPa)});
933       /*
934        * // remove all existing children of grandPa from worklist; for (Iterator iter =
935        * workList.iterator(); iter.hasNext();) { Exp exp = (Exp) iter.next(); if (exp instanceof
936        * mondrian.olap.Member && ((MemberExpr) exp).getParentMember().equals(grandPa))
937        * iter.remove(); }
938        */

939       list.add(fUncles);
940     } // AddUncels
941
}
942
943   /**
944    * @return a members unique name
945    * @see QuaxUti#getMemberUniqueName(java.lang.Object)
946    */

947   public String JavaDoc getMemberUniqueName(Object JavaDoc oExp) {
948     mondrian.olap.Member m = toMember(oExp);
949     return m.getUniqueName();
950   }
951
952   /**
953    * create String representation for FunCall
954    *
955    * @param oFun
956    * @return
957    */

958   public StringBuffer JavaDoc funString(Object JavaDoc oFun) {
959     FunCall f = (FunCall) oFun;
960     StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
961     if (isCallTo(f, "Children")) {
962       mondrian.olap.Member m = getMemberArg(f, 0);
963       buf.append(m.getUniqueName());
964       buf.append(".children");
965     } else if (isCallTo(f, "Descendants")) {
966       mondrian.olap.Member m = getMemberArg(f, 0);
967       mondrian.olap.Level lev = getLevelArg(f, 1);
968       buf.append("Descendants(");
969       buf.append(m.getUniqueName());
970       buf.append(",");
971       buf.append(lev.getUniqueName());
972       buf.append(")");
973     } else if (isCallTo(f, "members")) {
974       mondrian.olap.Level lev = getLevelArg(f, 0);
975       buf.append(lev.getUniqueName());
976       buf.append(".Members");
977     } else if (isCallTo(f, "Union")) {
978       buf.append("Union(");
979       FunCall f1 = (FunCall) f.getArg(0);
980       buf.append(funString(f1));
981       buf.append(",");
982       FunCall f2 = (FunCall) f.getArg(1);
983       buf.append(funString(f2));
984       buf.append(")");
985     } else if (isCallTo(f, "{}")) {
986       buf.append("{");
987       for (int i = 0; i < f.getArgs().length; i++) {
988         if (i > 0)
989           buf.append(",");
990         mondrian.olap.Member m = getMemberArg(f, i);
991         buf.append(m.getUniqueName());
992       }
993       buf.append("}");
994     } else if (isCallTo(f, "TopCount") || isCallTo(f, "BottomCount") || isCallTo(f, "TopPercent")
995         || isCallTo(f, "BottomPercent")) {
996       // just generate Topcount(set)
997
buf.append(f.getFunName());
998       buf.append("(");
999       FunCall f1 = (FunCall) f.getArg(0);
1000      buf.append(funString(f1));
1001      buf.append(")");
1002    }
1003    return buf;
1004  }
1005
1006  /**
1007   * display member array for debugging purposes
1008   *
1009   * @param mPath
1010   * @return
1011   */

1012  public String JavaDoc memberString(Member[] mPath) {
1013    if (mPath == null || mPath.length == 0)
1014      return "";
1015    StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
1016    for (int i = 0; i < mPath.length; i++) {
1017      if (i > 0)
1018        sb.append(" ");
1019      mondrian.olap.Member m = ((MondrianMember) mPath[i]).getMonMember();
1020      sb.append(m.getUniqueName());
1021    }
1022    return sb.toString();
1023  }
1024
1025  /**
1026   * @param oExp
1027   * expression
1028   * @return true if expression equals member
1029   * @see QuaxUti#equalMember(java.lang.Object, com.tonbeller.jpivot.olap.model.Member)
1030   */

1031  public boolean equalMember(Object JavaDoc oExp, Member member) {
1032    mondrian.olap.Member m = ((MondrianMember) member).getMonMember();
1033    mondrian.olap.Member oMon = toMember(oExp);
1034    return (m.equals(oMon));
1035  }
1036
1037  /**
1038   * check an expression whether we can handle it (expand, collapse) currently we can basically
1039   * handle following FunCalls member.children, member.descendants, level.members
1040   *
1041   * @see com.tonbeller.jpivot.olap.query.QuaxUti#canHandle(java.lang.Object)
1042   */

1043  public boolean canHandle(Object JavaDoc oExp) {
1044
1045    if (isMember(oExp))
1046      return true;
1047    FunCall f = (FunCall) oExp;
1048    if (isCallTo(f, "children"))
1049      return true;
1050    if (isCallTo(f, "descendants"))
1051      return true;
1052    if (isCallTo(f, "members"))
1053      return true;
1054    if (isCallTo(f, "{}"))
1055      return true;
1056    if (isCallTo(f, "union")) {
1057      for (int i = 0; i < f.getArgs().length; i++) {
1058        if (!canHandle(f.getArg(i)))
1059          return false;
1060      }
1061      return true;
1062    }
1063
1064    return false;
1065  }
1066
1067  /**
1068   * @return member children
1069   * @see com.tonbeller.jpivot.olap.query.QuaxUti#getChildren(java.lang.Object)
1070   */

1071  public Object JavaDoc[] getChildren(Object JavaDoc oMember) {
1072    mondrian.olap.Member[] members = scr.getMemberChildren(toMember(oMember));
1073    return members;
1074  }
1075
1076  /**
1077   * @return members of level
1078   */

1079  public Object JavaDoc[] getLevelMembers(Level level) {
1080    mondrian.olap.Level monLevel = ((MondrianLevel) level).getMonLevel();
1081    mondrian.olap.Member[] members = scr.getLevelMembers(monLevel, false);
1082    return members;
1083  }
1084
1085} //MondrianQuaxUti
1086
Popular Tags