KickJava   Java API By Example, From Geeks To Geeks.

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


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 package com.tonbeller.jpivot.mondrian;
14
15 import java.util.ArrayList JavaDoc;
16 import java.util.List JavaDoc;
17
18 import mondrian.mdx.LevelExpr;
19 import mondrian.mdx.MemberExpr;
20 import mondrian.mdx.UnresolvedFunCall;
21 import mondrian.olap.Category;
22 import mondrian.olap.Dimension;
23 import mondrian.olap.Exp;
24 import mondrian.olap.FunCall;
25 import mondrian.olap.HierarchyBase;
26 import mondrian.olap.Member;
27 import mondrian.olap.Parameter;
28 import mondrian.olap.SchemaReader;
29 import mondrian.olap.Syntax;
30
31 import com.tonbeller.jpivot.util.TreeNode;
32 import com.tonbeller.jpivot.util.TreeNodeCallback;
33
34 /**
35  * @author hh
36  *
37  * Utils for Mondrian Interface
38  */

39 public class MondrianUtil {
40
41   /**
42    * format exp to string for debugging purposes
43    * @param exp
44    * @return
45    */

46   public static String JavaDoc expString(Exp exp) {
47     String JavaDoc s = "";
48     if (exp instanceof FunCall) {
49       FunCall f = (FunCall) exp;
50       final String JavaDoc name = f.getFunName();
51       s += "<function:" + name + ">";
52       Exp[] args = f.getArgs();
53       for (int i = 0; i < args.length; i++) {
54         s += expString(args[i]);
55       }
56       s += "</function:" + name + ">";
57     } else if (exp instanceof mondrian.olap.Member) {
58       mondrian.olap.Member m = (mondrian.olap.Member) exp;
59       s += "<member>" + m.getUniqueName() + "</member>";
60     } else if (exp instanceof Parameter) {
61       mondrian.olap.Parameter p = (mondrian.olap.Parameter) exp;
62       s += "<parameter>" + p.getName() + "</parameter>";
63     } else if (exp instanceof mondrian.olap.Hierarchy) {
64       mondrian.olap.Hierarchy h = (mondrian.olap.Hierarchy) exp;
65       s += "<hier>" + h.getUniqueName() + "</hier>";
66     } else if (exp instanceof mondrian.olap.Level) {
67       mondrian.olap.Level l = (mondrian.olap.Level) exp;
68       s += "<level>" + l.getUniqueName() + "</level>";
69     } else {
70       s += " <exp>" + exp.toString() + "</exp>";
71     }
72     return s;
73   }
74
75   /**
76    * compare arrays of members
77    * @param aMem1
78    * @param aMem2
79    * @return true, if arrays are equal
80    */

81   public static boolean compareMembers(mondrian.olap.Member[] aMem1, mondrian.olap.Member[] aMem2) {
82     if (aMem1.length != aMem2.length)
83       return false;
84     for (int i = 0; i < aMem1.length; i++) {
85       // any null does not compare
86
if (aMem1[i] == null)
87         return false;
88       if (!aMem1[i].equals(aMem2[i]))
89         return false;
90     }
91     return true;
92   }
93
94   /**
95    * display member array for debugging purposes
96    * @param mPath
97    * @return
98    */

99   public static String JavaDoc memberString(mondrian.olap.Member[] mPath) {
100     if (mPath == null || mPath.length == 0)
101       return "";
102     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
103     for (int i = 0; i < mPath.length; i++) {
104       if (i > 0)
105         sb.append(" ");
106       sb.append(mPath[i].getUniqueName());
107     }
108     return sb.toString();
109   }
110
111   /**
112    * generate Exp for top level members of hierarchy
113    * @param monHier
114    * @param expandAllMember - true if an "All" member is to be expanded
115    * @return Exp for top level members
116    */

117   static Exp topLevelMembers(mondrian.olap.Hierarchy monHier, boolean expandAllMember,
118       SchemaReader scr) {
119
120     if (monHier.hasAll()) {
121       // an "All" member is present -get it
122
String JavaDoc sAll = ((HierarchyBase) monHier).getAllMemberName();
123       mondrian.olap.Member mona = (Member) scr.lookupCompound(monHier.getDimension(),
124           new String JavaDoc[] { sAll}, false, Category.Member);
125        if (mona != null) {
126         if (!expandAllMember)
127           return new MemberExpr(mona);
128         MemberExpr[] monar = { new MemberExpr(mona)};
129         Exp monaSet = new UnresolvedFunCall("{}", Syntax.Braces, monar);
130
131         // must expand
132
// create Union({AllMember}, AllMember.children)
133
Exp mAllChildren = new UnresolvedFunCall("children", Syntax.Property, monar);
134         Exp union = new UnresolvedFunCall("union", Syntax.Function, new Exp[] { monaSet, mAllChildren});
135         return union;
136       }
137     }
138     // does this call work with parent-child
139
mondrian.olap.Member[] topMembers = scr.getHierarchyRootMembers(monHier);
140     if (topMembers.length == 1)
141       return new MemberExpr(topMembers[0]); // single member
142
else if (topMembers.length == 0)
143       return null; // possible if access control active
144
return new UnresolvedFunCall("{}", Syntax.Braces, toExprArray(topMembers));
145   }
146
147   static MemberExpr[] toExprArray(Member[] members) {
148     MemberExpr[] memberExprs = new MemberExpr[members.length];
149     for (int i = 0; i < memberExprs.length; i++) {
150       memberExprs[i] = new MemberExpr(members[i]);
151     }
152     return memberExprs;
153   }
154
155   /**
156    * determine descendants of member at specific level
157    * @param scr SchemaReader
158    * @param member
159    * @param level
160    * @return descendants
161    */

162   public static mondrian.olap.Member[] getMemberDescendants(SchemaReader scr,
163       mondrian.olap.Member member, mondrian.olap.Level level) {
164     int depth = level.getDepth();
165     mondrian.olap.Level lev = member.getLevel();
166     if (depth <= lev.getDepth())
167       return new mondrian.olap.Member[0];
168     mondrian.olap.Member[] currentMembers = new mondrian.olap.Member[] { member};
169     while (depth > lev.getDepth()) {
170       lev = lev.getChildLevel();
171       currentMembers = scr.getMemberChildren(currentMembers);
172     }
173     return currentMembers;
174   }
175
176   /**
177    * Map function names to Mondrian Syntax type
178    * must be synchronized with mondrian/olap/fun/BuiltinFunTable.java
179    * @param fuName - function name
180    * @param nArgs - number of function args
181    * @return Syntax type
182    */

183   public static Syntax funCallSyntax(String JavaDoc fuName, int nArgs) {
184
185     if (fuName.equals("()"))
186       return Syntax.Parentheses;
187
188     else if (fuName.equals("{}"))
189       return Syntax.Braces;
190
191     if (nArgs == 1) {
192
193       if (fuName.equalsIgnoreCase("members"))
194         return Syntax.Property;
195       else if (fuName.equalsIgnoreCase("children"))
196         return Syntax.Property;
197       else if (fuName.equalsIgnoreCase("dimension"))
198         return Syntax.Property;
199       else if (fuName.equalsIgnoreCase("hierarchy"))
200         return Syntax.Property;
201       else if (fuName.equalsIgnoreCase("level"))
202         return Syntax.Property;
203       else if (fuName.equalsIgnoreCase("currentmember"))
204         return Syntax.Property;
205       else if (fuName.equalsIgnoreCase("defaultmember"))
206         return Syntax.Property;
207       else if (fuName.equalsIgnoreCase("firstchild"))
208         return Syntax.Property;
209       else if (fuName.equalsIgnoreCase("firstsibling"))
210         return Syntax.Property;
211       else if (fuName.equalsIgnoreCase("lastchild"))
212         return Syntax.Property;
213       else if (fuName.equalsIgnoreCase("lastsibling"))
214         return Syntax.Property;
215       else if (fuName.equalsIgnoreCase("nextmember"))
216         return Syntax.Property;
217       else if (fuName.equalsIgnoreCase("parent"))
218         return Syntax.Property;
219       else if (fuName.equalsIgnoreCase("prevmember"))
220         return Syntax.Property;
221       else if (fuName.equalsIgnoreCase("ordinal"))
222         return Syntax.Property;
223       else if (fuName.equalsIgnoreCase("value"))
224         return Syntax.Property;
225       else if (fuName.equalsIgnoreCase("lastperiods"))
226         return Syntax.Property;
227       else if (fuName.equalsIgnoreCase("siblings"))
228         return Syntax.Property;
229       else if (fuName.equalsIgnoreCase("name"))
230         return Syntax.Property;
231       else if (fuName.equalsIgnoreCase("uniquename"))
232         return Syntax.Property;
233       else if (fuName.equalsIgnoreCase("current"))
234         return Syntax.Property;
235
236       else if (fuName.equalsIgnoreCase("not"))
237         return Syntax.Prefix;
238       else if (fuName.equals("-"))
239         return Syntax.Prefix;
240
241     } else if (nArgs == 2) {
242
243       if (fuName.indexOf('<') >= 0)
244         return Syntax.Infix; // comparison operator
245
else if (fuName.indexOf('=') >= 0)
246         return Syntax.Infix; // comparison operator
247
else if (fuName.indexOf('>') >= 0)
248         return Syntax.Infix; // comparison operator
249
else if (fuName.equals("*"))
250         return Syntax.Infix;
251       else if (fuName.equals(":"))
252         return Syntax.Infix;
253       else if (fuName.equals("+"))
254         return Syntax.Infix;
255       else if (fuName.equals("-"))
256         return Syntax.Infix;
257       else if (fuName.equals("/"))
258         return Syntax.Infix;
259       else if (fuName.equalsIgnoreCase("||"))
260         return Syntax.Infix;
261       else if (fuName.equalsIgnoreCase("and"))
262         return Syntax.Infix;
263       else if (fuName.equalsIgnoreCase("or"))
264         return Syntax.Infix;
265       else if (fuName.equalsIgnoreCase("xor"))
266         return Syntax.Infix;
267     }
268
269     if (fuName.equalsIgnoreCase("lead"))
270       return Syntax.Method;
271     else if (fuName.equalsIgnoreCase("properties"))
272       return Syntax.Method;
273     else if (fuName.equalsIgnoreCase("item"))
274       return Syntax.Method;
275
276     return Syntax.Function;
277   }
278
279   /**
280    *
281    * @param root
282    * @param iDim
283    * @return
284    */

285   static List JavaDoc collectMembers(TreeNode root, final int iDim, final SchemaReader scr) {
286     if (root == null)
287       return null;
288     final List JavaDoc memberList = new ArrayList JavaDoc();
289     int ret = root.walkChildren(new TreeNodeCallback() {
290
291       /**
292        * callback
293        * find node matching member Path exactly
294        */

295       public int handleTreeNode(TreeNode node) {
296         int iDimNode = node.getLevel() - 1;
297         if (iDimNode < iDim)
298           return TreeNodeCallback.CONTINUE; // we are below iDim, don't care
299

300         // iDimNode == iDim
301
// node Exp must contain children of member[iDim]
302
final Object JavaDoc ref = node.getReference();
303         if (ref instanceof mondrian.olap.Member) {
304           mondrian.olap.Member m = (mondrian.olap.Member) ref;
305           if (!memberList.contains(m))
306             memberList.add(m);
307         } else if (ref instanceof MemberExpr) {
308           mondrian.olap.Member m = ((MemberExpr) ref).getMember();
309           if (!memberList.contains(m))
310             memberList.add(m);
311         } else {
312           // must be FunCall
313
FunCall f = (FunCall) ref;
314           boolean b = MondrianUtil.resolveFunCallMembers(f, memberList, scr);
315           if (!b)
316             return TreeNodeCallback.BREAK; // indicate: cannot handle
317
}
318         return TreeNodeCallback.CONTINUE_SIBLING; // continue next sibling
319
}
320     });
321     if (ret == TreeNodeCallback.BREAK)
322       return null;
323     else
324       return memberList;
325   }
326
327   static boolean isCallTo(FunCall f, String JavaDoc name) {
328     return f.getFunName().compareToIgnoreCase(name) == 0;
329   }
330
331   /**
332    *
333    * @param f
334    * @param memberList
335    * @return true, if Funcalls could be handled, otherwise false
336    */

337   static boolean resolveFunCallMembers(FunCall f, List JavaDoc memberList, SchemaReader scr) {
338     boolean canHandle = true;
339     if (isCallTo(f, "Children")) {
340       mondrian.olap.Member m = ((MemberExpr) f.getArg(0)).getMember();
341       mondrian.olap.Member[] members = scr.getMemberChildren(m);
342       for (int i = 0; i < members.length; i++) {
343         if (!memberList.contains(members[i]))
344           memberList.add(members[i]);
345       }
346     } else if (isCallTo(f, "Descendants")) {
347       mondrian.olap.Member m = ((MemberExpr) f.getArg(0)).getMember();
348       mondrian.olap.Level level = ((LevelExpr) f.getArg(1)).getLevel();
349       mondrian.olap.Member[] members = MondrianUtil.getMemberDescendants(scr, m, level);
350       for (int i = 0; i < members.length; i++) {
351         if (!memberList.contains(members[i]))
352           memberList.add(members[i]);
353       }
354     } else if (isCallTo(f, "Members")) {
355       mondrian.olap.Level level = ((LevelExpr) f.getArg(0)).getLevel();
356       mondrian.olap.Member[] members = scr.getLevelMembers(level, false);
357       for (int i = 0; i < members.length; i++) {
358         if (!memberList.contains(members[i]))
359           memberList.add(members[i]);
360       }
361     } else if (isCallTo(f, "Union")) {
362       resolveFunCallMembers((FunCall) f.getArg(0), memberList, scr);
363       resolveFunCallMembers((FunCall) f.getArg(1), memberList, scr);
364     } else if (isCallTo(f, "{}")) {
365       for (int i = 0; i < f.getArgs().length; i++) {
366         final Exp arg = f.getArg(i);
367         if (arg instanceof MemberExpr) {
368           Member member = ((MemberExpr) arg).getMember();
369           if (!memberList.contains(member))
370             memberList.add(member);
371         }
372       }
373     } else {
374       canHandle = false;
375     }
376     return canHandle;
377   }
378
379   /**
380    * creates a parameter name for a member
381    */

382   public static String JavaDoc defaultParamName(Member m) {
383     Dimension d = m.getDimension();
384     String JavaDoc s = d.getName();
385     s.replace(' ', '_');
386     // s.replaceAll("[ \\.\"'!§$%&/()=?ßüäöÖÄÜ#-:;,]", "");
387
return s + "_param";
388   }
389   
390 } // End MondrianUtil.java
391
Popular Tags