KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > openi > xmla > navigator > hierarchy > HierarchyNavigator


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 org.openi.xmla.navigator.hierarchy;
14
15 import java.util.ArrayList JavaDoc;
16 import java.util.HashSet JavaDoc;
17 import java.util.Iterator JavaDoc;
18 import java.util.List JavaDoc;
19 import java.util.Set JavaDoc;
20
21 import org.apache.log4j.Logger;
22 import org.w3c.dom.Document JavaDoc;
23 import org.w3c.dom.Element JavaDoc;
24
25 import com.tonbeller.jpivot.core.ModelChangeEvent;
26 import com.tonbeller.jpivot.core.ModelChangeListener;
27 import com.tonbeller.jpivot.olap.model.Axis;
28 import com.tonbeller.jpivot.olap.model.Hierarchy;
29 import com.tonbeller.jpivot.olap.model.OlapException;
30 import com.tonbeller.jpivot.olap.model.OlapModel;
31 import com.tonbeller.jpivot.olap.model.Result;
32 import com.tonbeller.jpivot.olap.navi.ChangeSlicer;
33 import com.tonbeller.jpivot.olap.navi.MemberDeleter;
34 import com.tonbeller.jpivot.olap.navi.PlaceHierarchiesOnAxes;
35 import com.tonbeller.jpivot.olap.navi.PlaceMembersOnAxes;
36 import com.tonbeller.jpivot.ui.Available;
37 import com.tonbeller.tbutils.res.Resources;
38 import com.tonbeller.wcf.catedit.CategoryEditor;
39 import com.tonbeller.wcf.catedit.CategoryModelSupport;
40 import com.tonbeller.wcf.component.Component;
41 import com.tonbeller.wcf.controller.Dispatcher;
42 import com.tonbeller.wcf.controller.DispatcherSupport;
43 import com.tonbeller.wcf.controller.RequestContext;
44 import com.tonbeller.wcf.controller.RequestListener;
45 import com.tonbeller.wcf.selection.SelectionModel;
46
47 import com.tonbeller.jpivot.olap.mdxparse.CompoundId;
48 import com.tonbeller.jpivot.olap.mdxparse.Exp;
49 import com.tonbeller.jpivot.olap.mdxparse.FunCall;
50 import com.tonbeller.jpivot.olap.mdxparse.MemberProperty;
51 import com.tonbeller.jpivot.olap.mdxparse.ParsedQuery;
52 import com.tonbeller.jpivot.xmla.XMLA_Member;
53 import com.tonbeller.jpivot.xmla.XMLA_Model;
54 import com.tonbeller.jpivot.tags.OlapModelProxy;
55 import com.tonbeller.jpivot.olap.model.CachingOlapModel;
56
57 /**
58  * Navigation dialog
59  *
60  * @author av
61  */

62 public class HierarchyNavigator extends CategoryEditor implements ModelChangeListener, Available {
63
64   public class CancelHandler implements RequestListener {
65     private boolean hide;
66
67     public CancelHandler(boolean hide) {
68       this.hide = hide;
69     }
70
71     public void request(RequestContext context) throws Exception JavaDoc {
72       editing = false;
73       // we will recreate everything on the next render()
74
revert(context);
75       if (hide)
76         setVisible(false);
77     }
78   }
79
80   public class OkHandler implements RequestListener {
81     private boolean hide;
82
83     public OkHandler(boolean hide) {
84       this.hide = hide;
85     }
86
87     /*public void request(RequestContext context) throws Exception {
88       editing = false;
89       boolean valid = validate(context);
90
91       // the following will fire multiple ModelChangeEvents
92       for (Iterator it = categories.iterator(); it.hasNext();)
93         ((AbstractCategory) it.next()).deleteDeleted();
94       for (Iterator it = categories.iterator(); it.hasNext();)
95         ((AbstractCategory) it.next()).prepareApplyChanges();
96       for (Iterator it = categories.iterator(); it.hasNext();)
97         ((AbstractCategory) it.next()).applyChanges();
98
99       if (valid && hide)
100         setVisible(false);
101     }*/

102
103     public void request(RequestContext context) throws Exception JavaDoc {
104       editing = false;
105       boolean valid = validate(context);
106       // the following will fire multiple ModelChangeEvents
107
for (Iterator JavaDoc it = categories.iterator(); it.hasNext();)
108         ((AbstractCategory) it.next()).deleteDeleted();
109       for (Iterator JavaDoc it = categories.iterator(); it.hasNext();)
110         ((AbstractCategory) it.next()).prepareApplyChanges();
111
112       List JavaDoc slicerMembersMdx = null;
113
114       for (Iterator JavaDoc it = categories.iterator(); it.hasNext();) {
115         AbstractCategory cat = (AbstractCategory)it.next();
116         if(cat instanceof SlicerCategory) {
117           SlicerCategory scat = (SlicerCategory)cat;
118           List JavaDoc items = scat.getItems();
119           Iterator JavaDoc iter = items.iterator();
120           while(iter.hasNext()) {
121             HierarchyItem item = (HierarchyItem)iter.next();
122             List JavaDoc selection = item.getSlicerSelection();
123             if(selection.size()>1) {
124              slicerMembersMdx = new ArrayList JavaDoc();
125              Iterator JavaDoc selIter = selection.iterator();
126              List JavaDoc deleted = new ArrayList JavaDoc();
127              while(selIter.hasNext()) {
128                XMLA_Member member = (XMLA_Member)selIter.next();
129                deleted.add(member);
130                slicerMembersMdx.add(member.toMdx());
131              }
132              for(Iterator JavaDoc delIter = deleted.iterator(); delIter.hasNext();)
133                selection.remove(delIter.next());
134             }
135           }
136         }
137
138         cat.applyChanges();
139       }
140
141       if (valid && hide)
142         setVisible(false);
143
144       if(slicerMembersMdx == null ) {
145         return;
146       }
147
148       XMLA_Model model = ((XMLA_Model)((CachingOlapModel)((OlapModelProxy)olapModel).getDelegate()).getDelegate());
149       ParsedQuery pquery = model.getPQuery();
150
151       String JavaDoc newMember = slicerMembersMdx.get(0).toString();
152       newMember = newMember.substring(0, newMember.lastIndexOf("."));
153
154       String JavaDoc names[] = new String JavaDoc[2];
155       StringBuffer JavaDoc newSlicerName = new StringBuffer JavaDoc("");
156       names[0] = newMember;
157
158
159       Exp cids[] = new Exp[slicerMembersMdx.size()];
160
161       Iterator JavaDoc iter = slicerMembersMdx.iterator();
162       for(int i=0 ; iter.hasNext(); i++){
163         String JavaDoc name = (String JavaDoc)iter.next();
164         name = name.substring(name.lastIndexOf(".") + 1);
165         cids[i] = new CompoundId(name, false);
166         //build new slicer name by concatinating calculated members
167
name = name.replace('[',' ');
168         name = name.replace(']','_');
169         newSlicerName.append(name.trim());
170       }
171
172       newSlicerName.insert(0,'[');
173       newSlicerName.setCharAt(newSlicerName.length() -1,']');
174
175       names[1] = newSlicerName.toString();
176
177       FunCall fun = new FunCall("+",cids, FunCall.TypeInfix);
178       pquery.addFormula(names, fun, new MemberProperty[0]);
179
180       String JavaDoc fullname = slicerMembersMdx.get(0).toString();
181       fullname = newMember.substring(0, newMember.lastIndexOf(".")<0 ? newMember.length(): newMember.lastIndexOf(".") ) + "." + names[1];
182
183       FunCall slicer = (FunCall)pquery.getSlicer();
184
185       Exp[] args = null;
186
187       int index = 0;
188
189       if(slicer != null ) {
190         index = slicer.getArgs().length;
191         args = new Exp[index +1 ];
192         System.arraycopy(slicer.getArgs(),0,args,0,index);
193       } else {
194         args = new Exp[1];
195       }
196
197       String JavaDoc []nameparts = fullname.split("\\.");
198
199       CompoundId cid = new CompoundId(nameparts[0], false);
200       for(int i=1 ; i < nameparts.length; i++) {
201         cid.append(nameparts[i], false);
202       }
203
204       args[index] = cid;
205       pquery.setSlicer(new FunCall("()", args, 6));
206     }
207
208   }
209
210   private String JavaDoc acceptButtonId;
211   private String JavaDoc cancelButtonId;
212   private RequestListener acceptHandler;
213   private RequestListener revertHandler;
214   private String JavaDoc okButtonId;
215   private String JavaDoc revertButtonId;
216   private List JavaDoc categories = new ArrayList JavaDoc();
217   private Resources resources;
218
219   /**
220    * after the user has started editing, the CategoryModel is no longer synchronized with the
221    * OlapModel. This means, the user may do one or more changes, and then apply these changes
222    * at once to the OlapModel.
223    */

224   private boolean editing = false;
225
226   private HierarchyItemClickHandler hierarchyItemClickHandler;
227   private OlapModel olapModel;
228   private CategoryModelSupport categoryModel;
229   private Dispatcher tempDispatcher = new DispatcherSupport();
230   private SlicerCategory slicerCategory;
231
232   private static Logger logger = Logger.getLogger(HierarchyNavigator.class);
233
234   /**
235    * Constructor for HierNavigator.
236    */

237   public HierarchyNavigator(String JavaDoc id, Component parent, OlapModel olapModel) {
238     super(id, parent);
239
240     logger.info("creating instance: " + this);
241
242     acceptButtonId = id + ".accept";
243     cancelButtonId = id + ".cancel";
244     okButtonId = id + ".ok";
245     revertButtonId = id + ".revert";
246
247     this.olapModel = olapModel;
248     olapModel.addModelChangeListener(this);
249
250     acceptHandler = new OkHandler(false);
251     revertHandler = new CancelHandler(false);
252     super.getDispatcher().addRequestListener(acceptButtonId, null, acceptHandler);
253     super.getDispatcher().addRequestListener(revertButtonId, null, revertHandler);
254     super.getDispatcher().addRequestListener(okButtonId, null, new OkHandler(true));
255     super.getDispatcher().addRequestListener(cancelButtonId, null, new CancelHandler(true));
256     super.getDispatcher().addRequestListener(null, null, tempDispatcher);
257     categoryModel = new CategoryModelSupport() {
258       public List JavaDoc getCategories() {
259         return categories;
260       }
261     };
262     super.setModel(categoryModel);
263     super.setItemRenderer(new HierarchyItemRenderer());
264   }
265
266   public void initialize(RequestContext context) throws Exception JavaDoc {
267     super.initialize(context);
268     resources = context.getResources(HierarchyNavigator.class);
269   }
270
271   /**
272    * Returns the hierExtension.
273    * @return PlaceHierarchiesOnAxes
274    */

275   public PlaceHierarchiesOnAxes getHierarchyExtension() {
276     return (PlaceHierarchiesOnAxes) olapModel.getExtension(PlaceHierarchiesOnAxes.ID);
277   }
278
279   /**
280    * Returns the hierarchyItemClickHandler.
281    * @return HierarchyItemClickHandler
282    */

283   public HierarchyItemClickHandler getHierarchyItemClickHandler() {
284     return hierarchyItemClickHandler;
285   }
286
287   /**
288    * Returns the memberExtension.
289    * @return PlaceMembersOnAxes
290    */

291   public PlaceMembersOnAxes getMemberExtension() {
292     return (PlaceMembersOnAxes) olapModel.getExtension(PlaceMembersOnAxes.ID);
293   }
294
295   public MemberDeleter getDeleterExtension() {
296     return (MemberDeleter) olapModel.getExtension(MemberDeleter.ID);
297   }
298
299   /**
300    * Returns the olapModel.
301    * @return OlapModel
302    */

303   public OlapModel getOlapModel() {
304     return olapModel;
305   }
306
307   /**
308    * Returns the slicerExtension.
309    * @return ChangeSlicer
310    */

311   public ChangeSlicer getSlicerExtension() {
312     return (ChangeSlicer) olapModel.getExtension(ChangeSlicer.ID);
313   }
314
315   /**
316    * Returns the tempDispatcher.
317    * @return Dispatcher
318    */

319   Dispatcher getTempDispatcher() {
320     return tempDispatcher;
321   }
322
323   /**
324    * initializes the CategoryModel to reflect the OlapModel
325    */

326   void initializeCategories() throws OlapException {
327     categories.clear();
328
329     Result result = olapModel.getResult();
330     Axis[] axes = result.getAxes();
331     for (int index = 0; index < axes.length; index++) {
332       Axis axis = axes[index];
333       String JavaDoc name = resources.getString("axis." + index + ".name");
334       String JavaDoc icon = resources.getString("axis." + index + ".icon");
335       AxisCategory axisCat = new AxisCategory(this, axis, name, icon);
336       categories.add(axisCat);
337     }
338
339     // the rest is added to the slicer
340
String JavaDoc name = resources.getString("slicer.name");
341     String JavaDoc icon = resources.getString("slicer.icon");
342     slicerCategory = new SlicerCategory(this, name, icon);
343     categories.add(slicerCategory);
344   }
345
346   /**
347    * true if the user has changed the axis/hierarchy mapping.
348    * @return boolean
349    */

350   public boolean isEditing() {
351     return editing;
352   }
353
354   void itemClicked(RequestContext context, HierarchyItem item, SelectionModel selection,
355       boolean allowChangeOrder) {
356     if (hierarchyItemClickHandler != null)
357       hierarchyItemClickHandler.itemClicked(context, item, selection, allowChangeOrder);
358   }
359
360   public Element JavaDoc render(RequestContext context, Document JavaDoc factory) throws Exception JavaDoc {
361     if (!editing) {
362       tempDispatcher.clear();
363       initializeCategories();
364     }
365
366     Element JavaDoc elem = super.render(context, factory);
367
368     elem.setAttribute("accept-id", acceptButtonId);
369     elem.setAttribute("accept-title", resources.getString("accept.title"));
370     elem.setAttribute("revert-id", revertButtonId);
371     elem.setAttribute("revert-title", resources.getString("revert.title"));
372     elem.setAttribute("ok-id", okButtonId);
373     elem.setAttribute("ok-title", resources.getString("ok.title"));
374     elem.setAttribute("cancel-id", cancelButtonId);
375     elem.setAttribute("cancel-title", resources.getString("cancel.title"));
376
377     return elem;
378   }
379
380   public void setEditing(boolean editing) {
381     this.editing = editing;
382   }
383
384   /**
385    * Sets the hierarchyItemClickHandler.
386    * @param hierarchyItemClickHandler The hierarchyItemClickHandler to set
387    */

388   public void setHierarchyItemClickHandler(HierarchyItemClickHandler hierarchyItemClickHandler) {
389     this.hierarchyItemClickHandler = hierarchyItemClickHandler;
390   }
391
392   public void modelChanged(ModelChangeEvent e) {
393     // recreate everything on next render()
394
editing = false;
395   }
396
397   public void structureChanged(ModelChangeEvent e) {
398     logger.info("cleaning up");
399     // force reload of members, hierarchies etc
400
setEditing(false);
401     tempDispatcher.clear();
402     categories.clear();
403     // invalidate hyperlinks
404
categoryModel.fireModelChanged();
405   }
406
407
408   /**
409    * finds the HierarchyItem for <code>hier</code>
410    * @param hier the Hierarchy
411    * @return null or the HierarchyItem
412    */

413   public HierarchyItem findHierarchyItem(Hierarchy hier) {
414     for (Iterator JavaDoc ci = categoryModel.getCategories().iterator(); ci.hasNext();) {
415       AbstractCategory ac = (AbstractCategory) ci.next();
416       for (Iterator JavaDoc ii = ac.getItems().iterator(); ii.hasNext();) {
417         HierarchyItem hi = (HierarchyItem) ii.next();
418         if (hi.getHierarchy().equals(hier))
419           return hi;
420       }
421     }
422     return null;
423   }
424
425   public RequestListener getAcceptHandler() {
426     return acceptHandler;
427   }
428
429   public RequestListener getRevertHandler() {
430     return revertHandler;
431   }
432
433   /**
434    * returns the set of dimensions that are currently on the
435    * slicer axis. This includes those dimensions that the
436    * user has moved to the slicer in the navigator but not yet
437    * committed by pressing the OK button.
438    *
439    * @return empty set if this component has not been rendered yet
440    */

441   public Set JavaDoc getSlicerDimensions() {
442     Set JavaDoc set = new HashSet JavaDoc();
443     for (Iterator JavaDoc it = slicerCategory.getItems().iterator(); it.hasNext();) {
444       HierarchyItem hi = (HierarchyItem) it.next();
445       set.add(hi.getHierarchy().getDimension());
446     }
447     return set;
448   }
449
450   public Resources getRes() {
451     return resources;
452   }
453
454   public boolean isAvailable() {
455     return getHierarchyExtension() != null;
456   }
457
458 }
Popular Tags