001: package com.calipso.reportgenerator.reportmanager;
002:
003: //import com.calipso.reportgenerator.reportcalculator.CubeFloat;
004: import com.calipso.reportgenerator.reportcalculator.CubeQuery;
005: import com.calipso.reportgenerator.reportcalculator.SharedDate;
006: import com.calipso.reportgenerator.reportcalculator.SharedFloat;
007: import com.calipso.reportgenerator.common.*;
008: import org.apache.xerces.dom.*;
009: import org.apache.xml.serialize.OutputFormat;
010: import org.apache.xml.serialize.XMLSerializer;
011: import org.w3c.dom.*;
012:
013: import java.io.StringWriter;
014: import java.io.IOException;
015: import java.util.Map;
016: import java.text.DateFormat;
017: import java.text.SimpleDateFormat;
018: import java.text.DecimalFormat;
019:
020: import com.calipso.reportgenerator.common.InfoException;
021:
022: /**
023: * Esta clase se encarga de generar el XML de salida
024: * para un reporte de tipo Cube. Result.xml
025: */
026: public class CubeReportXmlWriter implements ReportXmlWriter {
027: private ReportData reportData;
028: private ReportDataIterator reportDataIterator;
029: private ReportSpec reportSpec;
030: private Document document;
031: private Map paramValues;
032: private CubeQuery cubeQuery;
033: private Element root;
034:
035: public CubeReportXmlWriter(ReportData reportData,
036: ReportSpec reportSpec, Map paramValues, ReportQuery query)
037: throws InfoException {
038: this .reportData = reportData;
039: this .reportDataIterator = reportData.iterator();
040: this .reportSpec = reportSpec;
041: this .paramValues = paramValues;
042: cubeQuery = query.getCubeQuery();
043: }
044:
045: /**
046: * Retorna el xml generado
047: * @return
048: */
049: public StringWriter getXml() throws InfoException {
050: try {
051: /*Element node;
052: startDocument();
053: if (reportDataIterator.hasNext()) {
054: reportDataIterator.advance();
055: node = createDocument();
056: root = createElement("Report");
057: node.appendChild(root);
058: iterateCube(0, root, false);
059: addParameters();
060: }*/
061: startDocument();
062: Element node = createDocument();
063: root = createElement("Report");
064: node.appendChild(root);
065: iterateRows(root);
066: return getStream();
067: } catch (Exception e) {
068: throw new InfoException(LanguageTraslator.traslate("76"), e);
069: }
070: }
071:
072: public ReportSpec getReportSpec() {
073: return reportSpec;
074: }
075:
076: public Map getParamValues() {
077: return paramValues;
078: }
079:
080: /**
081: * Agrega los parámetros(Parameters values) al xml
082: */
083: private void addParameters() {
084: // COMPLETAR
085: }
086:
087: /**
088: * Devuelve un StringWriter con el xml
089: * @return
090: * @throws IOException
091: */
092: private StringWriter getStream() throws IOException {
093: OutputFormat format = new OutputFormat(document, "ISO-8859-1",
094: true);
095: StringWriter stringOut = new StringWriter();
096: XMLSerializer serial = new XMLSerializer(stringOut, format);
097: serial.asDOMSerializer();
098: Element elem = document.getDocumentElement();
099: if (elem != null) {
100: serial.serialize(elem);
101: }
102: return stringOut;
103: }
104:
105: private void iterateRows(Element node) {
106: int i;
107: int[] rows = cubeQuery.getRows();
108: if (rows.length > 0) {
109: while (reportDataIterator.hasNext()) {
110: reportDataIterator.advance();
111: Object[] values = reportDataIterator.current();
112: for (i = 0; i < rows.length; i++) {
113: ReportDimensionSpec dimensionSpec = reportSpec
114: .getDimensionFromIndex(rows[i]);
115: node = getNodeFrom(dimensionSpec.getName(),
116: getNodeValue(dimensionSpec, values[i]),
117: node, values);
118: }
119:
120: iterateColumns(node, values, i);
121: node = root;
122: }
123: }
124: }
125:
126: private void iterateColumns(Element node, Object[] values, int i) {
127: int[] cols = cubeQuery.getColumns();
128: if (cols.length > 0) {
129: for (int j = 0; j < cols.length; j++, i++) {
130: ReportDimensionSpec dimensionSpec = reportSpec
131: .getDimensionFromIndex(cols[j]);
132: node = getNodeFrom(dimensionSpec.getName(),
133: getNodeValue(dimensionSpec, values[i]), node,
134: values);
135: }
136: }
137: }
138:
139: /**
140: * Retorna el valor para el nodo
141: * @param dimensionSpec
142: * @param value
143: * @return
144: */
145: private String getNodeValue(ReportDimensionSpec dimensionSpec,
146: Object value) {
147: if (value instanceof SharedDate) {
148: DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
149: return dateFormat.format(((SharedDate) value).getDateEx()
150: .getDate());
151: } else if (value instanceof SharedFloat) {
152: DecimalFormat df = new DecimalFormat();
153: return df.format(((SharedFloat) value).floatValue());
154: } else {
155: return value.toString();
156: }
157: }
158:
159: private Element getNodeFrom(String name, String value,
160: Element node, Object[] values) {
161: Element returnVal = null;
162:
163: NodeList childs = node.getChildNodes();
164: for (int i = 0; i < childs.getLength(); i++) {
165: Element child = (Element) childs.item(i);
166: Attr attr = child.getAttributeNode("Value");
167: if (attr.getValue().equalsIgnoreCase(value)) {
168: returnVal = child;
169: break;
170: }
171: }
172:
173: if (returnVal == null) {
174: returnVal = document.createElement(name);
175: returnVal.setAttribute("Value", value);
176: node.appendChild(returnVal);
177: }
178:
179: addMetrics(returnVal, values, cubeQuery.getRows().length
180: + cubeQuery.getColumns().length);
181: return returnVal;
182: }
183:
184: private void addMetrics(Element returnVal, Object[] values, int j) {
185: int[] metrics = cubeQuery.getMetrics();
186: for (int i = 0; i < metrics.length; i++, j++) {
187: ReportMetricSpec metric = reportSpec.getMetricFromIndex(i);
188: if (returnVal.hasAttribute(metric.getName())) {
189: Attr attr = returnVal
190: .getAttributeNode(metric.getName());
191: float metricValue = Float.valueOf(attr.getValue())
192: .floatValue();
193: float result = ((SharedFloat) values[j]).floatValue()
194: + metricValue;
195: attr.setValue(String.valueOf(result));
196: } else {
197: returnVal.setAttribute(metric.getName(), values[j]
198: .toString());
199: }
200: }
201: }
202:
203: /**
204: * Recorre el iterador del cube
205: * @param dimension nivel del iterador
206: * @param ownerNode nodeo padre
207: * @param eoc fin del cube
208: */
209:
210: private void iterateCube(int dimension, Element ownerNode,
211: boolean eoc) {
212: Element elemTo;
213: Element child;
214: Object[] totalObj = null;
215: int dimTo;
216: int dimSize;
217: boolean lEoc = false;
218: //dimSize = reportData.getQuery().getDimensions().size();
219: //Todo: no optimo
220: dimSize = getCubeQuery().getDimensions().length;
221:
222: if (!eoc) {
223: child = createNodeElement(
224: getDimensionNameFromIndex(dimension),
225: reportDataIterator.current()[dimension].toString());
226: ownerNode.appendChild(child);
227: if (dimension < (dimSize - 1)) {
228: iterateCube((dimension + 1), child, eoc);
229: } else {
230: FillValue(child);
231: if (reportDataIterator.hasNext()) {
232: reportDataIterator.advance();
233: } else {
234: lEoc = true;
235: reportDataIterator.advance();
236: }
237: elemTo = child;
238: dimTo = dimension;
239: for (int i = 0; i < (reportDataIterator.currentTotals()
240: .size()); i++) {
241: dimTo = dimTo - 1;
242: elemTo = (Element) elemTo.getParentNode();
243: if (i < (reportDataIterator.currentTotals().size())) {
244: totalObj = (Object[]) reportDataIterator
245: .currentTotals().toArray()[i];
246: fillTotals(elemTo, totalObj);
247: }
248: }
249: iterateCube(dimTo, (Element) elemTo.getParentNode(),
250: lEoc);
251: }
252: }
253: }
254:
255: private CubeQuery getCubeQuery() {
256: if (cubeQuery == null) {
257: try {
258: cubeQuery = reportData.getQuery().getCubeQuery();
259: } catch (InfoException e) {
260: return null;
261: }
262: }
263: return cubeQuery;
264: }
265:
266: /**
267: * Obtiene el nombre de una dimensión
268: * @param dimension indice
269: * @return
270: */
271: private String getDimensionNameFromIndex(int dimension) {
272: return ((QueryDimension) reportData.getQuery().getDimensions()
273: .get(dimension)).getName();
274: /*int index = reportData.getQuery().getDimensions().get[dimension];
275: return ((DataDefinition) cube.getDefinition().getDimensions()[index]).getName();*/
276: }
277:
278: /**
279: * Obtienen el nombre de la métrica
280: * @param metric indice
281: * @return
282: */
283: private String getMetricNameFromIndex(int metric) {
284: return ((QueryMetric) reportData.getQuery().getMetrics().get(
285: metric)).getName();
286: //return ((DataDefinition) cube.getDefinition().getMetrics()[metric]).getName();
287: }
288:
289: /**
290: * Completa los totales para el grupo
291: * @param elem
292: * @param total lista de totales
293: */
294:
295: private void fillTotals(Element elem, Object[] total) {
296: int index = 0;
297: int currentMetric = 0;
298: int metricsFound = 0;
299: int metricsCount = reportData.getQuery().getMetrics().size();
300:
301: while (metricsFound < metricsCount) {
302: if (total[index] instanceof SharedFloat) {
303: String metricName = getMetricNameFromIndex(currentMetric);
304: elem.setAttribute(metricName, total[index].toString());
305: currentMetric++;
306: metricsFound++;
307: }
308: index++;
309: }
310: }
311:
312: /**
313: * Completa el valor de las dimensiones
314: * @param elem nodo
315: * @param metricValues valores de las métricas
316: */
317: private void fillMetricValues(Element elem, Object[] metricValues) {
318: int index = 0;
319: int currentMetric = 0;
320: int metricsFound = 0;
321: int metricsCount = reportData.getQuery().getMetrics().size();
322:
323: while (metricsFound < metricsCount) {
324: if (metricValues[index] instanceof SharedFloat) {
325: String metricName = getMetricNameFromIndex(currentMetric);
326: elem.setAttribute(metricName, metricValues[index]
327: .toString());
328: currentMetric++;
329: metricsFound++;
330: }
331: index++;
332: }
333: }
334:
335: /**
336: * Completa el valor de la métrica
337: * @param elem
338: */
339: private void FillValue(Element elem) {
340: Object[] row;
341: row = reportDataIterator.current();
342: fillMetricValues(elem, row);
343: }
344:
345: /**
346: * Crea el documento xml y el root
347: * @return
348: */
349: private Element createDocument() {
350: Element root;
351: root = createElement("Result");
352: document.appendChild(root);
353: String reportDefName = getReportSpec().getDescription();
354: root.setAttribute("ReportRefinition", reportDefName);
355: return root;
356: }
357:
358: /**
359: * Crea un document
360: */
361: private void startDocument() {
362: document = new DocumentImpl();
363: }
364:
365: /**
366: * Crea un nodo dentro del documento
367: * @param tagName Nombre del tag
368: * @param value valor del tag
369: * @return el elemento creado
370: */
371: private Element createNodeElement(String tagName, String value) {
372: Element newElem;
373: newElem = document.createElement(tagName);
374: newElem.setAttribute("Value", value);
375: return newElem;
376: }
377:
378: /**
379: * Crea un element
380: * @param tagName
381: * @return
382: */
383: private Element createElement(String tagName) {
384: return document.createElement(tagName);
385: }
386: }
|