001: package com.calipso.reportgenerator.reportcalculator;
002:
003: import com.calipso.reportgenerator.reportcalculator.*;
004:
005: import java.util.Iterator;
006: import java.io.Serializable;
007:
008: /**
009: * Representa los datos de un reporte de tipo estatico
010: * en una estructura de arbol.
011: */
012:
013: public class DataTree implements Serializable, PivotClient {
014: private DataTreeDefinition defintion;
015: private StaticQuery query;
016: private DataTreeNode root;
017:
018: /**
019: * Obtiene la definicion asignada al <code>DataTree</code>
020: * @return
021: */
022: public DataTreeDefinition getDefintion() {
023: return defintion;
024: }
025:
026: /**
027: * Asigna una definicion al <code>DataTree</code>
028: * @param definition
029: */
030: public void setDefinition(DataTreeDefinition definition) {
031: this .defintion = definition;
032: }
033:
034: public Iterator valuesFor(int dimension, int[] previousDimensions,
035: Object[] values) {
036: return null;
037: }
038:
039: /**
040: * Devuelve el iterador del <code>DataTree</code>
041: * @return
042: */
043: public DataTreeIterator iterator() {
044: return DataTreeIterator.on(this );
045: }
046:
047: public Object[] measuresAtDimensionsValues(int[] dimensions,
048: Object[] values) {
049: return new Object[0];
050: }
051:
052: /**
053: * Asigna la <code>StaticQuery</code> al <code>DataTree</code>
054: * @param staticQuery
055: */
056: public void setQuery(StaticQuery staticQuery) {
057: this .query = staticQuery;
058: }
059:
060: /**
061: * * Reinicializa el <code>DataTree</code>. Como efecto se pierden todos los datos actuales.
062: */
063: public void reset() {
064: root = null;
065: }
066:
067: /**
068: * Devuelve la raiz del <code>DataTree</code>.
069: * @return
070: */
071: public DataTreeNode getRoot() {
072: if (root == null) {
073: root = new DataTreeNode(null, "Root",
074: query.getMetrics().length, -1);
075: }
076: return root;
077: }
078:
079: /**
080: * Crea una rama del arbol a partir del array que recibe por parametro.
081: * Por cada dimension que agrupa se crea u obtiene un ya creado
082: * <code>DataTreeNode</code>, excepto para la ultima dimension.
083: * A cada instancia de <code>DataTreeNode</code> de cada dimension que agrupa,
084: * se le actualizan las metricas, es decir, se recalcula el total de estas
085: * sumando las actuales mas las acumuladas, excepto para la ultima dimension,
086: * en tal caso se crea una instancia de <code>DataTreeSubItem</code>, que representan
087: * las hojas del arbol.
088: * @param row
089: */
090: public void fillWith(Object[] row) {
091: int[] groupDims = query.getGroupDimensions();
092: int[] noGroupDims = query.getNoGroupDimensions();
093:
094: if (query.matches(row)) {
095: DataTreeNode currentNode = getRoot();
096: SharedFloat[] metricValues = new SharedFloat[query
097: .getMetrics().length];
098: fillMetricValues(metricValues, row);
099: updateMetricValues(currentNode, metricValues);
100:
101: for (int i = 0; i < groupDims.length; i++) {
102: int index = groupDims[i];
103: currentNode = currentNode
104: .getNodeFrom(row[index], index);
105: updateMetricValues(currentNode, metricValues);
106: }
107:
108: String[] noGroupDimValues = new String[noGroupDims.length];
109: for (int i = 0; i < noGroupDims.length; i++) {
110: int index = noGroupDims[i];
111: noGroupDimValues[i] = row[index].toString();
112: }
113: DataTreeSubItem subItem = currentNode
114: .getSubItem(noGroupDimValues);
115: subItem.updateMetricValues(metricValues);
116: }
117: }
118:
119: /**
120: * Llena un array con los valores de las metricas correspondientes
121: * en el objeto Object[] row que recibe por parametro.
122: * @param metricValues
123: * @param row
124: */
125: private void fillMetricValues(SharedFloat[] metricValues,
126: Object[] row) {
127: int[] metrics = query.getMetrics();
128: for (int i = 0; i < metrics.length; i++) {
129: int index = metrics[i];
130: metricValues[i] = ((SharedFloat) row[index]);
131: }
132: }
133:
134: /**
135: * Asigna para el nodo correspondiente los valores de las metricas
136: * del array recibido por parametro.
137: * @param node
138: * @param metricValues
139: */
140: private void updateMetricValues(DataTreeNode node,
141: SharedFloat[] metricValues) {
142: for (int i = 0; i < metricValues.length; i++) {
143: node.updateMetricValue(i, metricValues[i]);
144: }
145: }
146:
147: /**
148: * Devuelve la <code>StaticQuery</code> asignada al <code>DataTree</code>
149: * @return
150: */
151: public StaticQuery getQuery() {
152: return query;
153: }
154:
155: /**
156: * Sirve para pasar el indice de la metrica en el DataSource al
157: * indice de la metrica en el array de metricValues del
158: * subItem.
159: */
160: public void afterFill() {
161: int[] metrics = query.getMetrics();
162: int[] accMetrics = query.getAccumulableMetrics();
163: int[] adjAccMetrics = new int[accMetrics.length];
164: for (int i = 0; i < accMetrics.length; i++) {
165: int metricIndex = -1;
166: for (int j = 0; j < metrics.length; j++) {
167: if (accMetrics[i] == metrics[j]) {
168: metricIndex = j;
169: break;
170: }
171: }
172: adjAccMetrics[i] = metricIndex;
173: }
174: if (getDefintion().getAccumulable()) {
175: root.calculateAccumulable(adjAccMetrics);
176: }
177: }
178: }
|