KickJava   Java API By Example, From Geeks To Geeks.

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


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.Iterator JavaDoc;
16 import java.util.List JavaDoc;
17
18 import mondrian.olap.*;
19 import mondrian.mdx.MemberExpr;
20 import mondrian.mdx.UnresolvedFunCall;
21
22 import org.apache.log4j.Logger;
23
24 import com.tonbeller.jpivot.olap.model.Dimension;
25 import com.tonbeller.jpivot.olap.model.Hierarchy;
26 import com.tonbeller.jpivot.olap.model.Member;
27 import com.tonbeller.jpivot.olap.query.Quax;
28 import com.tonbeller.jpivot.olap.query.QuaxChangeListener;
29 import com.tonbeller.jpivot.olap.query.QueryAdapter;
30
31 /**
32  * Adapt the Mondrian Query Object to the JPivot System.
33  */

34 public class MondrianQueryAdapter extends QueryAdapter implements QuaxChangeListener {
35
36   static Logger logger = Logger.getLogger(MondrianQueryAdapter.class);
37
38   private String JavaDoc originalMDX;
39   private Query monQuery = null; // query object representing the current MDX
40
private Query cloneQuery = null; // query object representing the original MDX
41
private int nAxes; // number of axes
42

43   private final SchemaReader scr;
44
45   /**
46    * Constructor
47    */

48   MondrianQueryAdapter(MondrianModel model, mondrian.olap.Query monQuery) {
49     super(model);
50     this.monQuery = monQuery;
51     scr = model.getMonConnection().getSchemaReader();
52
53     genMDXHierarchize = true; // Result hierarchize cannot be used
54

55     // initialize the query axis state objects
56
nAxes = monQuery.getAxes().length;
57     quaxes = new MondrianQuax[nAxes];
58     for (int i = 0; i < monQuery.getAxes().length; i++) {
59       mondrian.olap.Hierarchy[] monHiers = monQuery.getMdxHierarchiesOnAxis(
60         AxisOrdinal.forLogicalOrdinal(i));
61       quaxes[i] = new MondrianQuax(i, monQuery.getAxes()[i], model);
62       Hierarchy[] hiers = new Hierarchy[monHiers.length];
63       for (int j = 0; j < hiers.length; j++) {
64         hiers[j] = model.lookupHierarchy(monHiers[j].getUniqueName());
65       }
66       quaxes[i].setHiers(hiers);
67       quaxes[i].addChangeListener(this);
68     }
69   }
70
71   /**
72    * implement MondrianQuaxChangeListener
73    */

74   public void quaxChanged(Quax quax, Object JavaDoc source, boolean changedByNavi) {
75     useQuax = true;
76   }
77
78   /**
79    * Returns the monQuery.
80    * @return Query
81    */

82   public Query getMonQuery() {
83
84     if (monQuery != null)
85       return monQuery;
86
87     try {
88       logger.warn("NOT EXPECTED getMonQuery calling parseQuery");
89       MondrianModel mmodel = (MondrianModel) model;
90       monQuery = mmodel.getConnection().parseQuery(mmodel.getMdxQuery());
91     } catch (Exception JavaDoc ex) {
92       // we should never get here
93
logger.fatal("getMonQuery parse error", ex);
94     }
95     return monQuery;
96   }
97
98   /**
99    * set the monQuery, used for restore
100    */

101   public void setMonQuery(Query q) {
102     this.monQuery = q;
103   }
104
105   /**
106    * Update the Mondrian Query before Execute.
107    * The current query is build from
108    * - the original query
109    * - adding the drilldown groups
110    * - apply pending swap axes
111    * - apply pending sorts.
112    *
113    * Called from MondrianModel.getResult before the query is executed.
114    */

115   protected void onExecute() {
116
117     // if quax is to be used, generate axes from quax
118
if (useQuax) {
119       int iQuaxToSort = -1;
120       if (sortMan != null)
121         iQuaxToSort = sortMan.activeQuaxToSort();
122
123       for (int i = 0; i < quaxes.length; i++) {
124         if (quaxes[i].getPosTreeRoot() == null)
125           continue;
126         boolean doHierarchize = false;
127         if (genMDXHierarchize && quaxes[i].isHierarchizeNeeded() && i != iQuaxToSort) {
128           doHierarchize = true;
129           if (logger.isDebugEnabled())
130             logger.debug("MDX Generation added Hierarchize()");
131         }
132
133         monQuery.getAxes()[iASwap(i)].setSet((Exp) quaxes[i].genExp(doHierarchize));
134       } // for quaxes
135
}
136
137     // generate order function if neccessary
138
if (sortMan != null) {
139       if (!useQuax) {
140         // if Quax is used, the axis exp's are re-generated every time.
141
// if not -
142
// adding a sort to the query must not be permanent.
143
// Therefore, we clone the orig state of the query object and use
144
// the clone furthermore in order to avoid duplicate "Order" functions.
145
if (cloneQuery == null) {
146           if (sortMan.isSortOnQuery())
147             cloneQuery = monQuery.safeClone();
148         } else {
149           // reset to original state
150
if (sortMan.isSortOnQuery())
151             monQuery = cloneQuery.safeClone();
152           else
153             monQuery = cloneQuery;
154         }
155       }
156       sortMan.addSortToQuery();
157     }
158
159     long t1 = System.currentTimeMillis();
160     String JavaDoc mdx = monQuery.toString();
161     long t2 = System.currentTimeMillis();
162     logger.info("monQuery.toString took " + (t2 - t1) + " millisec");
163     ((MondrianModel) model).setCurrentMdx(mdx);
164
165     if (logger.isDebugEnabled())
166       logger.debug(mdx);
167
168   }
169
170   /**
171    * return the corresponding mdx
172    */

173   protected String JavaDoc getCurrentMdx() {
174
175     String JavaDoc mdx = monQuery.toString();
176     return mdx;
177   }
178
179   /**
180    * create set expression for list of members
181    * @param memList
182    * @return set expression
183    */

184   protected Object JavaDoc createMemberSet(List JavaDoc memList) {
185     Exp[] exps = new Exp[memList.size()];
186     int i = 0;
187     for (Iterator JavaDoc iter = memList.iterator(); iter.hasNext();) {
188       MondrianMember m = (MondrianMember) iter.next();
189       exps[i++] = new MemberExpr(m.getMonMember());
190     }
191     UnresolvedFunCall f = new UnresolvedFunCall("{}", Syntax.Braces, exps);
192     return f;
193   }
194
195   // ***************
196
// Expand Collapse
197
// ***************
198

199   /**
200    * find out, whether a member can be expanded.
201    * this is true, if
202    * - the member is on an axis and
203    * - the member is not yet expanded and
204    * - the member has children
205    * @see com.tonbeller.jpivot.olap.navi.DrillExpandMember#canExpand(Member)
206    * @param member to be expanded
207    * @return true if the member can be expanded
208    */

209   public boolean canExpand(Member member) {
210     mondrian.olap.Member monMember = ((MondrianMember) member).getMonMember();
211     // a calculated member cannot be expanded
212
if (monMember.isCalculatedInQuery())
213       return false;
214
215     if (!scr.isDrillable(monMember))
216       return false;
217
218     Dimension dim = member.getLevel().getHierarchy().getDimension();
219     Quax quax = findQuax(dim);
220     return (quax == null) ? false : quax.canExpand(member);
221   }
222
223   /**
224    * @see com.tonbeller.jpivot.olap.navi.DrillExpandMember#canExpand(Member)
225    * @param position position to be expanded
226    * @param Member to be expanded
227    * @return true if the member can be expanded
228    */

229   public boolean canExpand(Member[] pathMembers) {
230
231     MondrianMember m = (MondrianMember) pathMembers[pathMembers.length - 1];
232     mondrian.olap.Member monMember = m.getMonMember();
233     // a calculated member cannot be expanded
234
if (monMember.isCalculatedInQuery())
235       return false;
236
237     if (!scr.isDrillable(monMember))
238       return false;
239
240     Dimension dim = m.getLevel().getHierarchy().getDimension();
241     Quax quax = findQuax(dim);
242     return (quax == null) ? false : quax.canExpand(pathMembers);
243   }
244
245   /**
246    * @see com.tonbeller.jpivot.olap.navi.DrillExpandMember#canCollapse(Member)
247    * @param member Member to be collapsed
248    * @return true if the member can be collapsed
249    */

250   public boolean canCollapse(Member member) {
251
252     // a calculated member cannot be collapsed
253
if (((MondrianMember) member).getMonMember().isCalculatedInQuery())
254       return false;
255     Dimension dim = member.getLevel().getHierarchy().getDimension();
256     Quax quax = findQuax(dim);
257     return (quax == null) ? false : quax.canCollapse(member);
258   }
259
260   /**
261    * @see com.tonbeller.jpivot.olap.navi.DrillExpandMember#canCollapse(Member)
262    * @param position position to be expanded
263    * @return true if the position can be collapsed
264    */

265   public boolean canCollapse(Member[] pathMembers) {
266
267     Member member = pathMembers[pathMembers.length - 1];
268     // a calculated member cannot be collapsed
269
if (((MondrianMember) member).getMonMember().isCalculatedInQuery())
270       return false;
271     Dimension dim = member.getLevel().getHierarchy().getDimension();
272     Quax quax = findQuax(dim);
273     return (quax == null) ? false : quax.canCollapse(pathMembers);
274   }
275
276   /**
277    * expand a member in all positions
278    * this is done by applying ToggleDrillState to the Query
279    *
280    * @see com.tonbeller.jpivot.olap.navi.DrillExpand#expand(Member)
281    * @param Member member to be expanded
282    */

283   public void expand(Member member) {
284     Dimension dim = member.getLevel().getHierarchy().getDimension();
285     Quax quax = findQuax(dim);
286
287     if (logger.isInfoEnabled())
288       logger.info("expand Member" + poString(null, member));
289     if ((quax == null) || !quax.canExpand(member)) {
290       logger.fatal("Expand Member failed for " + ((MondrianMember) member).getUniqueName());
291       //throw new java.lang.IllegalArgumentException("cannot expand");
292
return;
293     }
294     quax.expand(member);
295     model.fireModelChanged();
296   }
297
298   /**
299    * expand a member in a specific position
300    *
301    * @see com.tonbeller.jpivot.olap.navi.DrillExpand#expand(Member)
302    * @param position position to be expanded
303    * @param Member member to be expanded
304    */

305   public void expand(Member[] pathMembers) {
306
307     MondrianMember m = (MondrianMember) pathMembers[pathMembers.length - 1];
308     Dimension dim = m.getLevel().getHierarchy().getDimension();
309     Quax quax = findQuax(dim);
310
311     if (logger.isDebugEnabled())
312       logger.info("expand Path" + poString(pathMembers, null));
313     if ((quax == null) || !quax.canExpand(pathMembers)) {
314       logger.fatal("Expand failed for" + poString(pathMembers, null));
315       throw new java.lang.IllegalArgumentException JavaDoc("cannot expand");
316     }
317
318     quax.expand(pathMembers);
319     model.fireModelChanged();
320   }
321
322   // ************
323
// DrillReplace
324
// ************
325

326   /**
327    * drill down is possible if <code>member</code> has children
328    */

329   public boolean canDrillDown(Member member) {
330     mondrian.olap.Member monMember = ((MondrianMember) member).getMonMember();
331     if (!scr.isDrillable(monMember))
332       return false;
333     Dimension dim = member.getLevel().getHierarchy().getDimension();
334     Quax quax = findQuax(dim);
335     return (quax == null) ? false : quax.canDrillDown(member);
336   }
337
338   // *********
339
// Swap Axes
340
// *********
341

342   /**
343    * swap axes
344    * toggle swap state if neccessary
345    */

346   public void setSwapAxes(boolean swap) {
347     if (monQuery.getAxes().length != 2)
348       return;
349     // swap axes if neccessary
350
if (swap != axesSwapped) {
351       monQuery.swapAxes();
352       axesSwapped = swap;
353       if (logger.isInfoEnabled()) {
354         logger.info("swapAxes " + axesSwapped);
355       }
356       model.fireModelChanged();
357     }
358   }
359
360 } // End MondrianQueryAdapter
361
Popular Tags