KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > rolap > RolapAxis


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/rolap/RolapAxis.java#15 $
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) 2005-2007 Julian Hyde
7 // All Rights Reserved.
8 // You must accept the terms of that agreement to use this software.
9 */

10
11 package mondrian.rolap;
12
13
14 import mondrian.olap.Axis;
15 import mondrian.olap.Member;
16 import mondrian.olap.Position;
17 import mondrian.util.UnsupportedList;
18 import org.apache.log4j.Logger;
19 import java.util.Collection JavaDoc;
20 import java.util.Collections JavaDoc;
21 import java.util.ListIterator JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.ListIterator JavaDoc;
26 import java.util.NoSuchElementException JavaDoc;
27
28 /**
29  * Derived classes of RolapAxis implements the Axis interface which are
30  * specializations based upon the number of Positions, how each Position's
31  * Members are orgainized and whether the Members/Member[]s are in a List
32  * or an Iterable.
33  *
34  * @author <a>Richard M. Emberson</a>
35  * @version $Id: //open/mondrian/src/main/mondrian/rolap/RolapAxis.java#15 $
36  */

37 public abstract class RolapAxis implements Axis {
38     private static final Logger LOGGER = Logger.getLogger(RolapAxis.class);
39
40     public static String JavaDoc toString(Axis axis) {
41         List<Position> pl = axis.getPositions();
42         return toString(pl);
43     }
44     public static String JavaDoc toString(List<Position> pl) {
45         StringBuilder JavaDoc buf = new StringBuilder JavaDoc();
46         for (Position p: pl) {
47             buf.append('{');
48             boolean firstTime = true;
49             for (Member m: p) {
50                 if (! firstTime) {
51                     buf.append(", ");
52                 }
53                 buf.append(m.getUniqueName());
54                 firstTime = false;
55             }
56             buf.append('}');
57             buf.append('\n');
58         }
59         return buf.toString();
60     }
61     /**
62      * A Wrapper has many uses. In particular, if one is using Java 5 or
63      * above, one can create a Wrapper that is also a memory usage listener.
64      * Then one can place an Axis implementation into a Wrapper where the
65      * initial implementation is in-memory, large-memory-usage and
66      * cpu fast. The on the first memory notification it can be migrated
67      * to an in-memory, small-memory-usage and cpu slower. On a subsequent
68      * memory notification it can be migrated to an on-disk, low-memory and
69      * cpu slow implementation.
70      */

71     public static class Wrapper extends RolapAxis {
72         private final Axis axis;
73         protected Wrapper(Axis axis) {
74             super();
75             this.axis = axis;
76         }
77         public List<Position> getPositions() {
78             return this.axis.getPositions();
79         }
80     }
81
82     /**
83      * The NoPosition Axis implementation is an Axis that has no Positions,
84      * the size of the list of positions is zero.
85      */

86     public static class NoPosition extends RolapAxis {
87         public NoPosition() {
88             super();
89         }
90         public List<Position> getPositions() {
91             return Collections.EMPTY_LIST;
92         }
93     }
94
95     /**
96      * The PositionList Axis implementation takes a List of positions.
97      */

98     public static class PositionList extends RolapAxis {
99         protected final List<Position> positions;
100         public PositionList(List<Position> positions) {
101             super();
102             this.positions = positions;
103         }
104         public List<Position> getPositions() {
105             return positions;
106         }
107     }
108
109     /**
110      * A SingleEmptyPosition has a single Position and the Position has
111      * no Members.
112      */

113     public static class SingleEmptyPosition extends RolapAxis {
114         public SingleEmptyPosition() {
115         }
116         public List<Position> getPositions() {
117             return Collections.singletonList((Position) new EmptyPosition());
118         }
119         static class EmptyPosition extends PositionBase {
120             EmptyPosition() {
121             }
122             public int size() {
123                 return 0;
124             }
125             public Member get(int index) {
126                 throw new IndexOutOfBoundsException JavaDoc(
127                         "Index: "+index+", Size: 0");
128             }
129         }
130     }
131
132     /**
133      * A MemberIterable takes an Iterable&lt;Member&gt; where each Position has
134      * a single Member from the corresponding location in the iterator.
135      * If the client request any of the List, non-Iterable, API, then
136      * a List is materialized from the Iterable.
137      */

138     public static class MemberIterable extends RolapAxis {
139         private Iterable JavaDoc<Member> iter;
140         private List<Member> list;
141         public MemberIterable(Iterable JavaDoc<Member> iter) {
142             this.iter = iter;
143             this.list = null;
144         }
145         public synchronized List<Position> getPositions() {
146             return (list == null)
147                 ? new MemberIterable.PositionWrapper()
148                 : new MemberIterable.PositionList();
149         }
150         protected synchronized void materialize() {
151 //System.out.println("RolapAxis.materialize: 1");
152
if (list == null) {
153                 Iterator JavaDoc<Member> it = iter.iterator();
154                 list = new ArrayList JavaDoc<Member>();
155                 while (it.hasNext()) {
156                     list.add(it.next());
157                 }
158                 // allow gc of iter
159
iter = null;
160             }
161         }
162
163
164         /**
165          * This List&lt;Position&gt; starts life with a List&lt;Position&gt;
166          * implementation
167          * that is based upon an non-List (Iterable). If all accesses
168          * are simply through iteration, then the initial implementation
169          * remains, but if the client uses either the 'size' or 'get' methods
170          * then the Iterable is materialized into a List.
171          */

172         class PositionWrapper extends PositionListUnsupported {
173             List<Position> positionList;
174             PositionWrapper() {
175                 positionList = new PositionIter();
176             }
177             protected synchronized void materialize() {
178 //System.out.println("RolapAxis.materialize: 2");
179
if (LOGGER.isDebugEnabled()) {
180                     LOGGER.debug(
181                        "PositionWrapper.materialize: Member iter.class="
182                              + iter.getClass().getName());
183                 }
184                 RolapAxis.MemberIterable.this.materialize();
185                 positionList = new MemberIterable.PositionList();
186             }
187             public int size() {
188                 try {
189                     return positionList.size();
190                 } catch (UnsupportedOperationException JavaDoc ex) {
191                     this.materialize();
192                     return positionList.size();
193                 }
194             }
195             public Position get(int index) {
196                 try {
197                     return positionList.get(index);
198                 } catch (UnsupportedOperationException JavaDoc ex) {
199                     this.materialize();
200                     return positionList.get(index);
201                 }
202             }
203             public Iterator JavaDoc<Position> iterator() {
204                 return positionList.iterator();
205             }
206         }
207
208         /**
209          * PositionIter is a List&lt;Position&gt; that only support the
210          * 'iterator' method. This assumes that one iterates over Positions
211          * and for each Postion one iterates over Members. In this case,
212          * each Position has a single Member.
213          */

214         class PositionIter extends PositionIterBase {
215             private Iterator JavaDoc<Member> it;
216             PositionIter() {
217                 it = iter.iterator();
218             }
219             public Iterator JavaDoc<Position> iterator() {
220                 return new Iterator JavaDoc<Position>() {
221                     public boolean hasNext() {
222                         return it.hasNext();
223                     }
224                     public Position next() {
225                         return new MemberIterable.MIPosition(it.next());
226                     }
227                     public void remove() {
228                         throw new UnsupportedOperationException JavaDoc("remove");
229                     }
230                 };
231             }
232         }
233
234         /**
235          * A List&lt;Member&gt; which only implements the 'iterator' method.
236          * Each Iterator&lt;Member&gt; has only one Member.
237          */

238         class MIPosition extends PositionBase {
239             Member member;
240             MIPosition(Member member) {
241                 this.member = member;
242             }
243             public int size() {
244                 return 1;
245             }
246             public Member get(int index) {
247                 if (index != 0) {
248                     throw new IndexOutOfBoundsException JavaDoc(
249                         "Index: "+index+", Size: 1");
250                 }
251                 return member;
252             }
253
254             public Iterator JavaDoc<Member> iterator() {
255                 return new Iterator JavaDoc<Member>() {
256                     public boolean hasNext() {
257                         return (member != null);
258                     }
259                     public Member next() {
260                         try {
261                             return member;
262                         } finally {
263                             member = null;
264                         }
265                     }
266                     public void remove() {
267                         throw new UnsupportedOperationException JavaDoc("remove");
268                     }
269                 };
270             }
271         }
272
273         /**
274          * Each Position has a single Member.
275          */

276         class PositionList extends PositionListBase {
277             PositionList() {
278             }
279             public int size() {
280                 return list.size();
281             }
282             public Position get(int index) {
283                 return new MemberIterable.MLPosition(index);
284             }
285         }
286
287         /**
288          * Allows access only the the Member at the given offset.
289          */

290         class MLPosition extends PositionBase {
291             protected final int offset;
292             MLPosition(int offset) {
293                 this.offset = offset;
294             }
295             public int size() {
296                 return 1;
297             }
298             public Member get(int index) {
299                 if (index != 0) {
300                     throw new IndexOutOfBoundsException JavaDoc(
301                         "Index: "+index+", Size: 1");
302                 }
303                 return list.get(offset);
304             }
305         }
306     }
307
308
309
310     /**
311      * A MemberList takes a List&lt;Member&gt; where each Position has
312      * a single Member from the corresponding location in the list.
313      */

314     public static class MemberList extends RolapAxis {
315         private final List<Member> list;
316         public MemberList(List<Member> list) {
317             this.list = list;
318         }
319         public List<Position> getPositions() {
320             return new MemberList.PositionList();
321         }
322         /**
323          * Each Position has a single Member.
324          */

325         class PositionList extends PositionListBase {
326             PositionList() {
327             }
328             public int size() {
329                 return list.size();
330             }
331             public Position get(int index) {
332                 return new MemberList.MLPosition(index);
333             }
334         }
335
336         /**
337          * Allows access only the the Member at the given offset.
338          */

339         class MLPosition extends PositionBase {
340             protected final int offset;
341             MLPosition(int offset) {
342                 this.offset = offset;
343             }
344             public int size() {
345                 return 1;
346             }
347             public Member get(int index) {
348                 if (index != 0) {
349                     throw new IndexOutOfBoundsException JavaDoc(
350                         "Index: "+index+", Size: 1");
351                 }
352                 return list.get(offset);
353             }
354         }
355     }
356
357     /**
358      * A MemberArrayIterable takes an Iterable&lt;Member[]&gt; where
359      * each Position has
360      * an array of Members from the corresponding location in the iterator.
361      * If the client request any of the List, non-Iterable, API, then
362      * a List is materialized from the Iterable.
363      */

364     public static class MemberArrayIterable extends RolapAxis {
365         private Iterable JavaDoc<Member[]> iter;
366         private List<Member[]> list;
367         private int len;
368         public MemberArrayIterable(Iterable JavaDoc<Member[]> iter) {
369             this.iter = iter;
370             this.list = null;
371             this.len = 0;
372         }
373         public synchronized List<Position> getPositions() {
374             return (list == null)
375                 ? new MemberArrayIterable.PositionWrapper()
376                 : new MemberArrayIterable.PositionList();
377         }
378         protected synchronized void materialize() {
379 //System.out.println("RolapAxis.materialize: 3");
380
if (list == null) {
381                 Iterator JavaDoc<Member[]> it = iter.iterator();
382                 list = new ArrayList JavaDoc<Member[]>();
383                 while (it.hasNext()) {
384                     list.add(it.next());
385                 }
386                 // allow gc of iter
387
iter = null;
388
389                 len = (list.size() == 0) ? 0 : list.get(0).length;
390             }
391         }
392
393         /**
394          * This List&lt;Position&gt; starts life with a List&lt;Position&gt;
395          * implementation
396          * that is based upon an non-List (Iterable). If all accesses
397          * are simply through iteration, then the initial implementation
398          * remains, but if the client uses either the 'size' or 'get' methods
399          * then the Iterable is materialized into a List.
400          */

401         class PositionWrapper extends PositionListUnsupported {
402             List<Position> positionList;
403             PositionWrapper() {
404                 positionList = new PositionIter();
405             }
406             protected synchronized void materialize() {
407 //System.out.println("RolapAxis.materialize: 4");
408
if (LOGGER.isDebugEnabled()) {
409                     LOGGER.debug(
410                        "PositionWrapper.materialize: Member[] iter.class="
411                              + iter.getClass().getName());
412                 }
413                 RolapAxis.MemberArrayIterable.this.materialize();
414                 positionList = new MemberArrayIterable.PositionList();
415             }
416             public int size() {
417                 try {
418                     return positionList.size();
419                 } catch (UnsupportedOperationException JavaDoc ex) {
420                     this.materialize();
421                     return positionList.size();
422                 }
423             }
424             public Position get(int index) {
425                 try {
426                     return positionList.get(index);
427                 } catch (UnsupportedOperationException JavaDoc ex) {
428                     this.materialize();
429                     return positionList.get(index);
430                 }
431             }
432             public Iterator JavaDoc<Position> iterator() {
433                 return positionList.iterator();
434             }
435         }
436
437         /**
438          * PositionIter is a List&lt;Position&gt; that only support the
439          * 'iterator' method. This assumes that one iterates over Positions
440          * and for each Postion one iterates over Members. Each Position
441          * has two or more Members.
442          */

443         class PositionIter extends PositionIterBase {
444             private Iterator JavaDoc<Member[]> it;
445             PositionIter() {
446                 it = iter.iterator();
447             }
448             public Iterator JavaDoc<Position> iterator() {
449                 return new Iterator JavaDoc<Position>() {
450                     int nextCnt = 0;
451                     public boolean hasNext() {
452                         return it.hasNext();
453                     }
454                     public Position next() {
455                         nextCnt++;
456                         return new MemberArrayIterable.MIPosition(it.next());
457                     }
458                     public void remove() {
459                         throw new UnsupportedOperationException JavaDoc("remove");
460                     }
461                 };
462             }
463         }
464         /**
465          * A List&lt;Member&gt; which only implements the 'iterator' method.
466          * Each Iterator&lt;Member&gt; two or more Members.
467          */

468         class MIPosition extends PositionBase {
469             Member[] members;
470             MIPosition(Member[] members) {
471                 this.members = members;
472             }
473             public int size() {
474                 return members.length;
475             }
476             public Member get(int index) {
477                 return members[index];
478             }
479             public Iterator JavaDoc<Member> iterator() {
480                 return new Iterator JavaDoc<Member>() {
481                     int index = 0;
482                     public boolean hasNext() {
483                         return (index < members.length);
484                     }
485                     public Member next() {
486                         return members[index++];
487                     }
488                     public void remove() {
489                         throw new UnsupportedOperationException JavaDoc("remove");
490                     }
491                 };
492             }
493         }
494
495         /**
496          * Each Position has two or more Members.
497          */

498         class PositionList extends PositionListBase {
499             PositionList() {
500             }
501             public int size() {
502                 return list.size();
503             }
504             public Position get(int index) {
505                 return new MemberArrayIterable.MALPosition(index);
506             }
507         }
508
509         /**
510          * Allows access only the the Member at the given offset.
511          */

512         class MALPosition extends PositionBase {
513             protected final int offset;
514             MALPosition(int offset) {
515                 this.offset = offset;
516             }
517             public int size() {
518                 return RolapAxis.MemberArrayIterable.this.len;
519             }
520             public Member get(int index) {
521                 if (index > RolapAxis.MemberArrayIterable.this.len) {
522                     throw new IndexOutOfBoundsException JavaDoc(
523                         "Index: " +
524                         index +
525                         ", Size: " +
526                         RolapAxis.MemberArrayIterable.this.len);
527                 }
528                 return list.get(offset)[index];
529             }
530         }
531     }
532
533
534
535     /**
536      * A MemberArrayList takes a List&lt;Member[]&gt; where each Position has
537      * the Member's from the corresponding location in the list.
538      * It is assumed that each element of the list has an array of Members of
539      * the same size.
540      */

541     public static class MemberArrayList extends RolapAxis {
542         private final List<Member[]> list;
543         private final int len;
544         public MemberArrayList(List<Member[]> list) {
545             this.list = list;
546             this.len = (list.size() == 0) ? 0 : list.get(0).length;
547         }
548         public List<Position> getPositions() {
549             return new MemberArrayList.PositionList();
550         }
551         /**
552          * Each Position has an array of Member.
553          */

554         class PositionList extends PositionListBase {
555             PositionList() {
556             }
557             public int size() {
558                 return list.size();
559             }
560             public Position get(int index) {
561                 return new MemberArrayList.MALPosition(index);
562             }
563         }
564         /**
565          * Allows access only the the Member at the given offset plus index.
566          */

567         class MALPosition extends PositionBase {
568             protected final int offset;
569             MALPosition(int offset) {
570                 this.offset = offset;
571             }
572             public int size() {
573                 return RolapAxis.MemberArrayList.this.len;
574             }
575             public Member get(int index) {
576                 if (index > RolapAxis.MemberArrayList.this.len) {
577                     throw new IndexOutOfBoundsException JavaDoc(
578                         "Index: " +
579                         index +
580                         ", Size: " +
581                         RolapAxis.MemberArrayList.this.len);
582                 }
583                 return list.get(offset)[index];
584             }
585         }
586     }
587
588     /**
589      * A List&lt;Member&gt; for which all methods throw the
590      * UnsupportedOperationException exception when invoked. Derived classes
591      * can implement those methods that they require.
592      */

593     protected static abstract class PositionUnsupported
594                         extends UnsupportedList<Member>
595                         implements Position {
596         protected PositionUnsupported() {
597         }
598     }
599     /**
600      * The PositionBase is an abstract implementation of the Position
601      * interface and provides both Iterator&lt;Member&gt; and
602      * ListIterator&lt;Member&gt; implementations.
603      */

604     protected static abstract class PositionBase extends PositionUnsupported {
605         protected PositionBase() {
606         }
607         public ListIterator JavaDoc<Member> listIterator() {
608             return new ListItr(0);
609         }
610         public ListIterator JavaDoc<Member> listIterator(int index) {
611             return new ListItr(index);
612         }
613         public Iterator JavaDoc<Member> iterator() {
614             return new Itr();
615         }
616     }
617
618     protected static abstract class PositionListUnsupported
619                         extends UnsupportedList<Position> {
620         protected PositionListUnsupported() {
621         }
622     }
623
624     protected static abstract class PositionIterBase
625                                 extends PositionListUnsupported {
626         protected PositionIterBase() {
627             super();
628         }
629         public abstract Iterator JavaDoc<Position> iterator();
630     }
631
632     /**
633      * The PositionListBase is an abstract implementation of the
634      * List&lt;Position&gt
635      * interface and provides both Iterator&lt;Position&gt; and
636      * ListIterator&lt;Position&gt; implementations.
637      */

638     protected static abstract class PositionListBase
639                                 extends PositionListUnsupported {
640         protected PositionListBase() {
641             super();
642         }
643         public abstract int size();
644         public abstract Position get(int index);
645
646         // Collection
647
public boolean isEmpty() {
648             return (size() == 0);
649         }
650         public ListIterator JavaDoc<Position> listIterator() {
651             return new ListItr(0);
652         }
653         public ListIterator JavaDoc<Position> listIterator(int index) {
654             return new ListItr(index);
655         }
656         public Iterator JavaDoc<Position> iterator() {
657             return new Itr();
658         }
659     }
660
661     protected RolapAxis() {
662     }
663     public abstract List<Position> getPositions();
664 }
665 // End RolapAxis.java
666
Popular Tags