KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tonbeller > jpivot > xmla > XMLA_Member


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.xmla;
14
15 import java.util.ArrayList JavaDoc;
16 import java.util.List JavaDoc;
17
18 import org.apache.log4j.Logger;
19
20 import com.tonbeller.jpivot.olap.mdxparse.CompoundId;
21 import com.tonbeller.jpivot.olap.mdxparse.Exp;
22 import com.tonbeller.jpivot.olap.mdxparse.ExpVisitor;
23 import com.tonbeller.jpivot.olap.model.Dimension;
24 import com.tonbeller.jpivot.olap.model.Hierarchy;
25 import com.tonbeller.jpivot.olap.model.Level;
26 import com.tonbeller.jpivot.olap.model.Member;
27 import com.tonbeller.jpivot.olap.model.OlapDiscoverer;
28 import com.tonbeller.jpivot.olap.model.OlapException;
29 import com.tonbeller.jpivot.olap.model.Property;
30 import com.tonbeller.jpivot.olap.model.Visitor;
31 import com.tonbeller.jpivot.olap.query.MDXMember;
32 import com.tonbeller.jpivot.util.StringUtil;
33
34 /**
35  * Member Implementation for XMLA
36  */

37 public class XMLA_Member implements Member, MDXMember, Exp {
38
39   static Logger logger = Logger.getLogger(XMLA_Member.class);
40
41   private XMLA_Model model;
42
43   private long ordinal;
44   private String JavaDoc name;
45   private int type;
46   private String JavaDoc caption;
47   private long childrenCardinality = -1;
48   private long parentLevel;
49   private String JavaDoc uniqueName;
50   private String JavaDoc parentUniqueName = null;
51   private String JavaDoc key;
52   private boolean isPlaceHolderMember;
53   private boolean isDataMember;
54   private long displayInfo = -1;
55   private String JavaDoc dimUName = null;
56   // dimension unique name for calculated members
57

58   private XMLA_Level level;
59   private XMLA_Member parent = null;
60   private ArrayList JavaDoc aChildren = null;
61
62   //private Property[] properties = null;
63
private List JavaDoc properties = new ArrayList JavaDoc();
64
65   private boolean isCalculated; // for a formula member
66

67   private boolean complete = false; // completely initialized
68
private boolean propsOk = false;
69   private boolean childrenOk = false;
70   private boolean parentOk = false;
71
72   /**
73    * c'tor
74    * @param uName
75    * @param caption
76    * @param levUname
77    * @param levelNumber
78    * @param hierUName
79    * @param lev
80    */

81   public XMLA_Member(
82     XMLA_Model model,
83     String JavaDoc uName,
84     String JavaDoc caption,
85     XMLA_Level lev,
86     boolean isCalculated) {
87
88     if (!(model.lookupMemberByUName(uName) == null)) {
89       // error - should never occur
90
logger.fatal("cannot create member doubly " + uName);
91       throw new IllegalArgumentException JavaDoc("cannot create member doubly " + uName);
92     }
93
94     this.model = model;
95     this.uniqueName = uName;
96     this.caption = caption;
97     this.level = lev;
98     this.isCalculated = isCalculated;
99
100     logger.debug("<init>: uName - " + uName + ", level - " + lev + ", isCalculated - " + isCalculated);
101     
102     model.addMember(this);
103
104     if (model.isMicrosoft() || isCalculated) {
105       parentUniqueName = StringUtil.parentFromUName(uName);
106       if (parentUniqueName == null) {
107         parent = null;
108         parentOk = true;
109         logger.debug("parentUniqueName from uName: " + uName + " == null");
110       } else {
111         parent = (XMLA_Member) model.lookupMemberByUName(parentUniqueName);
112         logger.debug("lookupMemberByUName(" + parentUniqueName + "): " + parent);
113         if (parent != null)
114           parentOk = true;
115       }
116     }
117
118     // SAP does not return a level name for a calculated measure
119
// another bug?
120
// we need (?) a level, so try to get it
121
// a normal member (not calculated) should always have a level
122
if (level == null && isCalculated) {
123       // get the dimension from the unique name
124
String JavaDoc dimUname = StringUtil.dimFromUName(uniqueName);
125       XMLA_Dimension dim = model.lookupDimByUName(dimUname);
126       logger.debug("looked up dimension name: " + uniqueName + " = " + dim);
127       if (dim != null) {
128         if (dim.isMeasure()) {
129           // assign measures level
130
Hierarchy[] hiers = dim.getHierarchies();
131           Level[] levs = hiers[0].getLevels();
132           level = (XMLA_Level) levs[0];
133           logger.debug("isMeasure: " + level);
134         } else {
135           // normal dimension
136
// if it is NOT SAP (no parent supported) and
137
// if the unique name contains a parent - get the level from parent
138
XMLA_Member pm = null;
139           if (model.isMicrosoft() && parentUniqueName != null) {
140             pm = (XMLA_Member) model.lookupMemberByUName(parentUniqueName);
141             if (pm != null)
142               level = ((XMLA_Level) pm.getLevel()).getChildLevel();
143             logger.debug("normal dimension: " + level);
144           }
145           if (level == null) {
146             // don't know how to find level
147
// try default hierarchy - top level
148
Hierarchy hier = null;
149             if (pm != null) {
150               hier = pm.getHierarchy();
151               logger.debug("hierarchy from member: " + hier);
152             } else {
153               String JavaDoc hierUname = dim.getDefaultHier();
154               hier = model.lookupHierByUName(hierUname);
155               logger.debug("hierarchy from DefaultHier: " + hier);
156             }
157             if (hier != null) {
158               logger.debug("trying default hierarchy: " + hier);
159               // take the level with number 0
160
Level[] levs = hier.getLevels();
161               for (int i = 0; i < levs.length; i++) {
162                 if (((XMLA_Level) levs[i]).getDepth() == 0) {
163                   level = (XMLA_Level) levs[i];
164                   break;
165                 }
166               } // for levs
167
}
168           }
169         } // else
170
} // if dim != null
171
} // if level == null
172

173     // won't survive without a level
174
// better crash here than later
175
if (level == null)
176       throw new IllegalArgumentException JavaDoc("Member " + uName + " Level=null");
177
178     if (level.getChildLevel() == null || isCalculated) {
179       childrenCardinality = 0;
180       childrenOk = true;
181     }
182   }
183
184   /**
185    *
186    * @param other
187    * @return boolean
188    */

189   public boolean isEqual(Member otherM) {
190     XMLA_Member other = (XMLA_Member) otherM;
191     return this.uniqueName.equals(other.uniqueName);
192   }
193
194   /**
195    * determine, whether this member is descendant of other member
196    * @param other
197    * @return boolean
198    */

199   public boolean isChildOf(Member otherM) throws OlapException {
200     XMLA_Member other = (XMLA_Member) otherM;
201     // if not the same hierarchy, say no
202
XMLA_Hierarchy thisHier = (XMLA_Hierarchy) level.getHierarchy();
203     XMLA_Hierarchy otherHier = (XMLA_Hierarchy) other.getLevel().getHierarchy();
204     if (!thisHier.isEqual(otherHier))
205       return false;
206     // cannot be a child, if the level is not higher
207
long otherLevelNumber = ((XMLA_Level) other.getLevel()).getDepth();
208     if (!(level.getDepth() > otherLevelNumber))
209       return false;
210
211     // go up parent chain
212
XMLA_Member m = this;
213     while (m.level.getDepth() > otherLevelNumber) {
214       m = (XMLA_Member) m.getParent();
215     }
216
217     if (m.isEqual(other))
218       return true;
219
220     return false;
221   }
222
223   /**
224     * @see com.tonbeller.jpivot.olap.model.Visitable#accept(Visitor)
225     */

226   public void accept(Visitor visitor) {
227     visitor.visitMember(this);
228   }
229
230   public Object JavaDoc getRootDecoree() {
231     return this;
232   }
233
234   /**
235     * Returns the caption as Label.
236     * @return String
237     */

238   public String JavaDoc getLabel() {
239     return caption;
240   }
241
242   /**
243    * Returns the caption.
244    * @return String
245    */

246   public String JavaDoc getCaption() {
247     return caption;
248   }
249
250   /**
251    * Returns the childrenCardinality.
252    * @return int
253    */

254   public long getChildrenCardinality() {
255     return childrenCardinality;
256   }
257
258   /**
259    * Returns the isDataMember.
260    * @return boolean
261    */

262   public boolean isDataMember() {
263     return isDataMember;
264   }
265
266   /**
267    * Returns the isPlaceHolderMember.
268    * @return boolean
269    */

270   public boolean isPlaceHolderMember() {
271     return isPlaceHolderMember;
272   }
273
274   /**
275    * Returns the key.
276    * @return String
277    */

278   public String JavaDoc getKey() {
279     return key;
280   }
281
282   /**
283    * Returns the name.
284    * @return String
285    */

286   public String JavaDoc getName() {
287     return name;
288   }
289
290   /**
291    * Returns the ordinal.
292    * @return int
293    */

294   public long getOrdinal() {
295     return ordinal;
296   }
297
298   /**
299    * Returns the parentLevel.
300    * @return int
301    */

302   public long getParentLevel() {
303     return parentLevel;
304   }
305
306   /**
307    * Returns the type.
308    * @return int
309    */

310   public int getType() {
311     return type;
312   }
313
314   /**
315    * Returns the uniqueName.
316    * @return String
317    */

318   public String JavaDoc getUniqueName() {
319     return uniqueName;
320   }
321
322   /**
323    * set all attributes, which were not set in the c'tor
324    * @param name
325    * @param type
326    * @param ordinal
327    * @param parentUniqueName
328    * @param childrenCardinality
329    * @param parentLevel
330    * @param isDataMember
331    * @param isPlaceHolderMember
332    * @param key
333    */

334   public void complete(
335     String JavaDoc name,
336     int type,
337     long ordinal,
338     String JavaDoc parentUniqueName,
339     long childrenCardinality,
340     long parentLevel,
341     boolean isDataMember,
342     boolean isPlaceHolderMember,
343     String JavaDoc key) {
344     this.childrenCardinality = childrenCardinality;
345     this.isDataMember = isDataMember;
346     this.isPlaceHolderMember = isPlaceHolderMember;
347     this.key = key;
348     this.name = name;
349     this.ordinal = ordinal;
350     this.parentLevel = parentLevel;
351     this.type = type;
352     this.parentUniqueName = parentUniqueName;
353     complete = true;
354   }
355
356   /**
357    * Returns the parentUniqueName.
358    * @return String
359    */

360   public String JavaDoc getParentUniqueName() {
361     return parentUniqueName;
362   }
363
364   /**
365    * Returns the level.
366    * @return XMLA_Level
367    */

368   public Level getLevel() {
369     return level;
370   }
371
372   /**
373     * set the Level
374     */

375   public void setLevel(XMLA_Level level) {
376     this.level = level;
377   }
378
379   /**
380    * @see com.tonbeller.jpivot.olap.model.PropertyHolder#getProperties()
381    */

382   public Property[] getProperties() {
383
384     /*
385         if (!propsOk) {
386           propsOk = true;
387           // if this member's level does not have properties at all
388           if (isCalculated || level.getProps().size() == 0) {
389             properties.clear();
390           } else {
391     
392             try {
393               model.completeMember(this);
394             } catch (OlapException e) {
395               logger.error("?", e);
396             }
397           }
398         }
399     */

400     if (isCalculated || properties.size() == 0)
401       return new Property[0]; // or null ???
402

403     return (Property[]) properties.toArray(new Property[0]);
404   }
405
406   /**
407    * @see com.tonbeller.jpivot.olap.model.PropertyHolder#getProperty(String)
408    */

409   public Property getProperty(String JavaDoc name) {
410
411     /*
412         if (!propsOk) {
413           propsOk = true;
414           // if this member's level does not have properties at all
415           if (isCalculated || level.getProps().size() == 0) {
416     
417             properties.clear();
418           } else {
419     
420             try {
421               model.completeMember(this);
422             } catch (OlapException e) {
423               logger.error("?", e);
424             }
425           }
426         }
427     */

428
429     if (isCalculated || properties.size() == 0)
430       return null;
431
432     for (int i = 0; i < properties.size(); i++) {
433       Property prop = (Property) properties.get(i);
434       if (name.equals(prop.getName()))
435         return prop;
436     }
437
438     return null; // not found
439
}
440
441   /**
442    * @see com.tonbeller.jpivot.olap.model.Member#getRootDistance()
443    */

444   public int getRootDistance() {
445     if (level == null && isCalculated)
446       return 0;
447     return level.getDepth();
448   }
449
450   /**
451    * get level number = depth of member
452    * @return int
453    */

454   public int getDepth() {
455     if (level == null && isCalculated)
456       return 0;
457     return this.level.getDepth(); // level number is depth
458
}
459
460   /**
461    *
462    * @return XMLA_Member[]
463    */

464   public XMLA_Member[] getChildren() throws OlapException {
465     if (childrenOk) {
466       if (childrenCardinality == 0)
467         return new XMLA_Member[0];
468       else
469         return (XMLA_Member[]) aChildren.toArray(new XMLA_Member[0]);
470     }
471
472     // determine children
473
model.retrieveMemberChildren(this); // will retrieve children
474

475     return (XMLA_Member[]) aChildren.toArray(new XMLA_Member[0]);
476   }
477
478   /**
479     * set list of children.
480     * @param aNewChildren List of children to be added
481     */

482   public void setChildren(ArrayList JavaDoc aChildren) {
483     this.aChildren = aChildren;
484     if (aChildren == null)
485       childrenCardinality = 0;
486     else
487       childrenCardinality = aChildren.size();
488   }
489
490   /**
491    * Returns the complete.
492    * @return boolean
493    */

494   public boolean isComplete() {
495     return complete;
496   }
497
498   /**
499    * Returns the parent.
500    * @return XMLA_Member
501    */

502   public Member getParent() throws OlapException {
503
504     if (parentOk)
505       return parent;
506  
507     /*
508         if (isCalculated) {
509           //get the parent by unique name
510           String[] names = uniqueName.split("\\.");
511           if (names.length <= 2) {
512             // no parent in unique name
513             parentOk = true;
514             parent = null;
515             return null;
516           }
517           StringBuffer sb = new StringBuffer();
518           for (int i = 0; i < names.length - 1; i++) {
519             if (i > 0)
520               sb.append('.');
521             sb.append(names[i]);
522           }
523           parentUniqueName = sb.toString();
524           parent = model.lookupMemberByUName(parentUniqueName);
525           parentOk = true;
526           return parent;
527         }
528     */

529
530     if (model.isMicrosoft() || isCalculated) {
531       parentUniqueName = StringUtil.parentFromUName(uniqueName);
532       if (parentUniqueName == null) {
533         parent = null;
534         parentOk = true;
535         return parent;
536       } else {
537         parent = (XMLA_Member) model.lookupMemberByUName(parentUniqueName);
538         if (parent != null) {
539           parentOk = true;
540           return parent;
541         }
542       }
543     }
544
545     // this call should not be needed
546
model.retrieveMemberParent(this);
547     return parent;
548   }
549
550   /**
551    * get Dimension of member
552    * @return dimension
553    */

554   public Dimension getDimension() {
555     if (level != null)
556       return level.getHierarchy().getDimension();
557     Dimension dim = model.lookupDimByUName(dimUName);
558     return dim;
559   }
560
561   /**
562    * Sets the parent.
563    * @param parent The parent to set
564    */

565   public void setParent(XMLA_Member parent) {
566     this.parent = parent;
567     this.parentOk = true;
568   }
569
570   /**
571    * get hierarchy of member
572    * @return Hierarchy
573    */

574   public Hierarchy getHierarchy() {
575     if (level != null)
576       return level.getHierarchy();
577     XMLA_Dimension dim = (XMLA_Dimension) getDimension();
578     String JavaDoc defHier = dim.getDefaultHier();
579     if (defHier != null && defHier.length() > 0)
580       return model.lookupHierByUName(defHier);
581     else
582       return null;
583   }
584
585   /**
586    * Returns the isCalculated.
587    * @return boolean
588    */

589   public boolean isCalculated() {
590     return isCalculated;
591   }
592
593   /**
594    * @return the unique name
595    */

596   public String JavaDoc toMdx() {
597     return this.uniqueName;
598   }
599
600   /**
601    * @see com.tonbeller.jpivot.olap.mdxparse.Exp#clone()
602    * probably not needed
603    */

604   public Object JavaDoc clone() {
605     String JavaDoc[] nameParts = StringUtil.splitUniqueName(uniqueName);
606     CompoundId clone = new CompoundId(nameParts[0], false);
607     for (int i = 1; i < nameParts.length; i++) {
608       clone.append(nameParts[i], false);
609     }
610     return clone;
611   }
612
613   /**
614    * add a property
615    */

616   public void addProp(Property prop) {
617     properties.add(prop);
618   }
619
620   /**
621     * clear properties
622     */

623   public void clearProps() {
624     properties.clear();
625   }
626
627   /**
628    * @return
629    */

630   public boolean isPropsOk() {
631     return propsOk;
632   }
633
634   /**
635    * @param b
636    */

637   public void setPropsOk(boolean b) {
638     propsOk = b;
639   }
640
641   /**
642    * @return
643    */

644   public boolean isChildrenOk() {
645     return childrenOk;
646   }
647
648   /**
649    * @return
650    */

651   public boolean isParentOk() {
652     return parentOk;
653   }
654
655   /**
656    * @param b
657    */

658   public void setChildrenOk(boolean b) {
659     childrenOk = b;
660   }
661
662   /**
663    * @param b
664    */

665   public void setParentOk(boolean b) {
666     parentOk = b;
667   }
668
669   /**
670    * @return true , if the model is SAP
671    */

672   public boolean isSAP() {
673     return model.isSAP();
674   }
675
676   public boolean isMicrosoft() {
677     return model.isMicrosoft();
678   }
679
680   public boolean isMondrian() {
681     return model.isMondrian();
682   }
683
684   /**
685      * @see com.tonbeller.jpivot.olap.mdxparse.Exp#accept
686      */

687   public void accept(ExpVisitor visitor) {
688     visitor.visitMember(this);
689   }
690
691   /**
692    * @return displayInfo
693    */

694   public long getDisplayInfo() {
695     return displayInfo;
696   }
697
698   /**
699    * @param displayInfo string
700    */

701   public void setDisplayInfo(String JavaDoc strDisplayInfo) {
702     if (strDisplayInfo == null || displayInfo != -1)
703       return;
704     displayInfo = Long.parseLong(strDisplayInfo);
705     // the two least significant bytes is the children cardinality
706
if (childrenCardinality == -1)
707       childrenCardinality = Math.abs(displayInfo) % 65536;
708   }
709
710   /**
711    * @return true, if it is an "All" member
712    */

713   public boolean isAll() {
714     return ((XMLA_Level)this.getLevel()).isAll();
715   }
716
717 } // End XMLA_Member
718
Popular Tags