KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > calipso > reportgenerator > reportcalculator > CubeIterator


1 package com.calipso.reportgenerator.reportcalculator;
2
3 import java.util.*;
4
5 /**
6  * Itera un Cube.
7  * A diferencia de un iterador tradicional de Java, la interface separa la
8  * obtención del valor actual (current) del avance (advance).
9  * Además, luego de cada advance, se recalculan los totales por los que pueda
10  * haberse atravesado. Es decir, se genera una lista de totales para cada corte
11  * de control realizado por los últimos valores con respecto a los anteriores.
12  * La forma de operar es obtener el iterador del Cube.
13  * Hacer recursivamente advance y consultar por current y por currentTotals
14  * Luego de obtener el último current hasNext va a devolver false.
15  * En ese momento debe hacerse un nuevo advance para obtener los últimos totales.
16  */

17 public class CubeIterator {
18   LinkedList totals;
19   Iterator[] iterators;
20   Map.Entry[] entries;
21   int[] dimensions;
22   int[] metrics;
23   Cube cube;
24   int metricsSize;
25   int dimensionsSize;
26
27
28   /**
29    * Crea un iterador para recorrer el Cube que se recibe como parámetro
30    * @param cube
31    * @return
32    */

33   public static CubeIterator on(Cube cube) {
34     return new CubeIterator(cube);
35   }
36
37   /**
38    * Crea un iterador para recorrer el Cube que se recibe como parámetro
39    * @param cube
40    */

41   public CubeIterator(Cube cube) {
42     this.cube = cube;
43     initialize();
44   }
45
46   /**
47    * Inicializa los valores que describen al cubo, cantidad de métricas, cantidad de dimensiones y prepara las
48    * estructuras internas
49    */

50   private void initialize() {
51     dimensionsSize = cube.getDimensionsSize();
52     metricsSize = cube.getMetricsSize();
53     dimensions = cube.getIntegerArray(0, dimensionsSize);
54     metrics = cube.getIntegerArray(dimensionsSize, metricsSize);
55     entries = new Map.Entry[dimensionsSize + 1];
56     iterators = new Iterator[dimensionsSize];
57     // Carga el primer nodo
58
entryAtPut(-1, new Entry("root", cube.getRoot()));
59   }
60
61   /**
62    * Devuelve una asociación que representa a un nodo del cube
63    * @param index
64    * @return
65    */

66   public Map.Entry entryAt(int index) {
67     return entries[index + 1];
68   }
69
70   /**
71    * Agrega una asociación que representa a un nodo del cube, reemplazando el valor de la dimensión por el valor real
72    * @param index
73    * @param value
74    */

75   public void entryAtPut(int index, Map.Entry value) {
76     entries[index + 1] = value;
77     fillEntryWithParentsValues(index);
78   }
79
80   /**
81    * Asigna a un nodo tipo array indicado por index los
82    * valores de las métricas bajo las cuales está, es decir,
83    * de los nodos encontrados ascendentemente. Esto se usa
84    * para cuando se devuelven estos nodos a modo de totales
85    * @param index
86    */

87   private void fillEntryWithParentsValues(int index) {
88     int i;
89     Map.Entry entry;
90     for (i = 0; i <= index; i++) {
91       entry = entries[i + 1];
92       if (entry != null) {
93         ((Object JavaDoc[]) entries[index + 1].getValue())[dimensions[i]] = entry.getKey();
94       }
95     }
96   }
97
98   /**
99    * Inicializa un nuevo iterador para una dimensión
100    * @param dimensionIndex
101    */

102   public void initializeIterator(int dimensionIndex) {
103     iterators[dimensionIndex] = iteratorFor(dimensionIndex);
104     if (iterators[dimensionIndex].hasNext()) {
105       updateEntry(iterators[dimensionIndex], dimensionIndex);
106     }
107   }
108
109   /**
110    * Crea un iterador para una dimensión
111    * @param dimensionIndex
112    * @return
113    */

114   private Iterator iteratorFor(int dimensionIndex) {
115     HashMap table;
116     Object JavaDoc[] node;
117
118     node = (Object JavaDoc[]) entryAt(dimensionIndex - 1).getValue();
119     int cubeDimIndex = dimensions[dimensionIndex];
120     table = (HashMap) node[cubeDimIndex];
121     if (table != null) {
122       return cube.sortedIteratorFor(table, cubeDimIndex);
123     }
124     else {
125       return null;
126     }
127   }
128
129   /**
130    * Agrega una asociación que representa a un nodo para el valor de una dimensión
131    * @param iterator
132    * @param dimensionIndex
133    */

134   private void updateEntry(Iterator iterator, int dimensionIndex) {
135     entryAtPut(dimensionIndex, (Map.Entry) iterator.next());
136   }
137
138   /**
139    * El iterador avanza una posicion.
140    */

141   public void advance() {
142     totals = new LinkedList();
143     advanceAt(dimensionsSize - 1);
144   }
145
146   /**
147    * Avance el iterador para la dimensión dimensionIndex, si es
148    * que está asignado, si no, o si se terminó, hace avanzar el
149    * iterador anterior y luego crea uno nuevo
150    * @param dimensionIndex
151    */

152   private void advanceAt(int dimensionIndex) {
153
154     if (dimensionIndex >= 0) {
155       if (iterators[dimensionIndex] != null) {
156         if (iterators[dimensionIndex].hasNext()) {
157           updateEntry(iterators[dimensionIndex], dimensionIndex);
158           return;
159         }
160         else {
161           iterators[dimensionIndex] = null;
162           totals.add(totalFrom(dimensionIndex - 1));
163         }
164       }
165       advanceAt(dimensionIndex - 1);
166       initializeIterator(dimensionIndex);
167     }
168   }
169
170   /**
171    * Crea un array con los totales para la dimensión dimensionIndex
172    * Si el total a devolver es el raíz, puede tener hashmaps que hay
173    * que sacar. Si no fuese por esto devolveríamos directamente:
174    * entryAt(dimensionIndex).getValue();
175    * @param dimensionIndex
176    * @return Object
177    */

178   private Object JavaDoc totalFrom(int dimensionIndex) {
179     Object JavaDoc[] result;
180     int i;
181     Object JavaDoc[] node;
182
183     node = (Object JavaDoc[]) entryAt(dimensionIndex).getValue();
184     result = new Object JavaDoc[node.length];
185     for (i = 0; i < dimensionsSize; i++) {
186       if (node[i] instanceof HashMap) {
187         result[i] = null;
188       }
189       else {
190         result[i] = node[i];
191       }
192     }
193     for (i = 0; i < metricsSize; i++) {
194       result[dimensionsSize + i] = node[metrics[i]];
195     }
196     return result;
197   }
198
199   /**
200    * A partir de la posición adonde apunta el CubeIterator
201    * devuelve verdadero/falso dependiendo si hay o no mas datos en el cubo
202    */

203   public boolean hasNext() {
204     Iterator iterator;
205     if (iterators.length == 0){
206       return false;
207     }
208     if (iterators[0] == null) {
209       iterator = iteratorFor(0);
210       if (iterator != null) {
211         return iterator.hasNext();
212       }
213       else {
214         return false;
215       }
216     }
217     for (int i = 0; i < dimensionsSize; i++) {
218       iterator = iterators[i];
219       if (iterator.hasNext()) {
220         return true;
221       }
222     }
223     return false;
224   }
225
226   /**
227    * Crea un array con los valores actuales
228    * @return [] Object
229    */

230   public Object JavaDoc[] current() {
231     Object JavaDoc[] result;
232     int i;
233     Object JavaDoc[] node;
234
235     result = new Object JavaDoc[dimensionsSize + metricsSize];
236     for (i = 0; i < dimensionsSize; i++) {
237       result[i] = entryAt(i).getKey();
238     }
239     node = (Object JavaDoc[]) entryAt(dimensionsSize - 1).getValue();
240     for (i = 0; i < metricsSize; i++) {
241       result[dimensionsSize + i] = node[metrics[i]];
242     }
243     return result;
244   }
245
246   /**
247    * Retorna una lista enlazada con los totales actuales
248    * @return LinkedList
249    */

250   public Collection currentTotals() {
251     return totals;
252   }
253 }
Popular Tags