KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > mondrian > web > taglib > DOMBuilder


1 /*
2 // $Id: //open/mondrian/src/main/mondrian/web/taglib/DOMBuilder.java#14 $
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) 2002-2002 Kana Software, Inc.
7 // Copyright (C) 2002-2007 Julian Hyde and others
8 // All Rights Reserved.
9 // You must accept the terms of that agreement to use this software.
10 //
11 // Andreas Voss, 22 March, 2002
12 */

13 package mondrian.web.taglib;
14
15 import mondrian.olap.*;
16
17 import org.apache.log4j.Logger;
18 import org.w3c.dom.CDATASection JavaDoc;
19 import org.w3c.dom.Document JavaDoc;
20 import org.w3c.dom.Element JavaDoc;
21
22 import javax.xml.parsers.DocumentBuilder JavaDoc;
23 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
24 import javax.xml.parsers.ParserConfigurationException JavaDoc;
25 import javax.xml.transform.Templates JavaDoc;
26 import javax.xml.transform.TransformerFactory JavaDoc;
27 import javax.xml.transform.dom.DOMSource JavaDoc;
28 import javax.xml.transform.stream.StreamResult JavaDoc;
29 import javax.xml.transform.stream.StreamSource JavaDoc;
30
31 import java.io.ByteArrayOutputStream JavaDoc;
32 import java.io.OutputStream JavaDoc;
33 import java.io.StringReader JavaDoc;
34 import java.util.List JavaDoc;
35
36 /**
37  * transforms a mondrian result into a DOM
38  */

39 public class DOMBuilder {
40     private static final Logger LOGGER = Logger.getLogger(DOMBuilder.class);
41
42     Document JavaDoc factory;
43     Result JavaDoc result;
44     int dimCount;
45
46     protected DOMBuilder(Document JavaDoc factory, Result JavaDoc result) {
47         this.factory = factory;
48         this.result = result;
49     }
50
51     public static Document JavaDoc build(Result JavaDoc result) throws ParserConfigurationException JavaDoc {
52         DocumentBuilderFactory JavaDoc dbf = DocumentBuilderFactory.newInstance();
53         dbf.setValidating(false);
54         dbf.setExpandEntityReferences(true);
55         DocumentBuilder JavaDoc db = dbf.newDocumentBuilder();
56         Document JavaDoc doc = db.newDocument();
57         Element JavaDoc table = build(doc, result);
58         doc.appendChild(table);
59         // debug(doc);
60
return doc;
61     }
62
63     public static Element JavaDoc build(Document JavaDoc factory, Result JavaDoc result) {
64         return new DOMBuilder(factory, result).build();
65     }
66
67     private Element JavaDoc build() {
68         dimCount = result.getAxes().length;
69         Element JavaDoc mdxtable = factory.createElement("mdxtable");
70         Element JavaDoc query = elem("query", mdxtable);
71         cdata(Util.unparse(result.getQuery()), query);
72         Element JavaDoc head = elem("head", mdxtable);
73         Element JavaDoc body = elem("body", mdxtable);
74         switch (dimCount) {
75         case 0:
76             buildRows0Dim(body);
77             break;
78         case 1:
79             buildColumns(head, result.getAxes()[0]);
80             buildRows1Dim(body);
81             break;
82         case 2:
83             buildColumns(head, result.getAxes()[0]);
84             buildRows2Dim(body, result.getAxes()[1]);
85             break;
86         default:
87             throw new IllegalArgumentException JavaDoc("DOMBuilder requires 0, 1 or 2 dimensional result");
88         }
89         Element JavaDoc slicers = elem("slicers", mdxtable);
90         buildSlicer(slicers);
91         return mdxtable;
92     }
93
94     abstract class AxisBuilder {
95         Member[] prevMembers;
96         Element JavaDoc[] prevElems;
97         int [] prevSpan;
98
99         Element JavaDoc parent;
100         List JavaDoc<Position> positions;
101         int levels;
102
103         AxisBuilder(Element JavaDoc parent, Axis axis) {
104             this.parent = parent;
105
106             positions = axis.getPositions();
107             levels = positions.get(0).size();
108             prevMembers = new Member[levels];
109             prevElems = new Element JavaDoc[levels];
110             prevSpan = new int[levels];
111         }
112
113         abstract int getRowCount();
114         abstract Element JavaDoc build(int rowIndex);
115     }
116
117     class RowBuilder extends AxisBuilder {
118         RowBuilder(Element JavaDoc parent, Axis axis) {
119             super(parent, axis);
120         }
121
122         Element JavaDoc build(int rowIndex) {
123             boolean even = (rowIndex % 2 != 0); // counting starts at row 1
124
Element JavaDoc row = elem("row", parent);
125             build(row, positions.get(rowIndex), even);
126             return row;
127         }
128
129         int getRowCount() {
130             return positions.size();
131         }
132
133         private void build(Element JavaDoc row, List JavaDoc<Member> currentMembers, boolean even) {
134             for (int i = 0; i < levels; i++) {
135                 Member currentMember = currentMembers.get(i);
136                 Member prevMember = prevMembers[i];
137                 if (prevMember == null || !prevMember.equals(currentMember)) {
138                     Element JavaDoc currentElem = createMemberElem("row-heading", row, currentMember);
139                     if (even)
140                         currentElem.setAttribute("style", "even");
141                     else
142                         currentElem.setAttribute("style", "odd");
143                     prevMembers[i] = currentMember;
144                     prevElems[i] = currentElem;
145                     prevSpan[i] = 1;
146                     for (int j = i + 1; j < levels; j++)
147                         prevMembers[j] = null;
148                 }
149                 else {
150                     Element JavaDoc prevElem = prevElems[i];
151                     prevElem.setAttribute("style", "span");
152                     prevSpan[i] += 1;
153                     prevElem.setAttribute("rowspan", Integer.toString(prevSpan[i]));
154                 }
155             }
156         }
157     }
158
159
160     class ColumnBuilder extends AxisBuilder {
161         ColumnBuilder(Element JavaDoc parent, Axis axis) {
162             super(parent, axis);
163         }
164
165         int getRowCount() {
166             return levels;
167         }
168
169         Element JavaDoc build(int rowIndex) {
170             Element JavaDoc row = elem("row", parent);
171             if (dimCount > 1 && rowIndex == 0)
172                 buildCornerElement(row);
173             build(row, rowIndex);
174             return row;
175         }
176
177         private void build(Element JavaDoc row, int rowIndex) {
178             for (int i = 0; i < levels; i++)
179                 prevMembers[i] = null;
180
181             for (int i = 0; i < positions.size(); i++) {
182                 Position position = positions.get(i);
183                 //Member[] currentMembers = positions.get(i).getMembers();
184

185                 for (int j = 0; j < rowIndex - 1; j++) {
186                     Member currentMember = position.get(j);
187                     if (prevMembers[j] == null || !prevMembers[j].equals(currentMember)) {
188                         prevMembers[j] = currentMember;
189                         for (int k = j + 1; k < levels; k++)
190                             prevMembers[j] = null;
191                     }
192                 }
193
194                 Member currentMember = position.get(rowIndex);
195                 Member prevMember = prevMembers[rowIndex];
196                 if (prevMember == null || !prevMember.equals(currentMember)) {
197                     Element JavaDoc currentElem = createMemberElem("column-heading", row, currentMember);
198                     prevMembers[rowIndex] = currentMember;
199                     prevElems[rowIndex] = currentElem;
200                     prevSpan[rowIndex] = 1;
201                     for (int j = rowIndex + 1; j < levels; j++)
202                         prevMembers[j] = null;
203                 }
204                 else {
205                     Element JavaDoc prevElem = prevElems[rowIndex];
206                     prevElem.setAttribute("style", "span");
207                     prevSpan[rowIndex] += 1;
208                     prevElem.setAttribute("colspan", Integer.toString(prevSpan[rowIndex]));
209                 }
210             }
211         }
212
213         void buildCornerElement(Element JavaDoc row) {
214             Element JavaDoc corner = elem("corner", row);
215             corner.setAttribute("rowspan", Integer.toString(result.getAxes()[0].getPositions().get(0).size()));
216             corner.setAttribute("colspan", Integer.toString(result.getAxes()[1].getPositions().get(0).size()));
217         }
218     }
219
220
221     private void buildRows2Dim(Element JavaDoc parent, Axis axis) {
222         RowBuilder rb = new RowBuilder(parent, axis);
223         final int N = rb.getRowCount();
224         int[] cellIndex = new int[2];
225         for (int i = 0; i < N; i++) {
226             Element JavaDoc row = rb.build(i);
227             boolean even = (i % 2 != 0); // counting starts at row 1
228
cellIndex[1] = i;
229             buildCells(row, cellIndex, even);
230         }
231     }
232
233     private void buildRows1Dim(Element JavaDoc parent) {
234         int[] cellIndex = new int[1];
235         Element JavaDoc row = elem("row", parent);
236         buildCells(row, cellIndex, false);
237     }
238
239     private void buildColumns(Element JavaDoc parent, Axis axis) {
240         ColumnBuilder cb = new ColumnBuilder(parent, axis);
241         final int N = cb.getRowCount();
242         for (int i = 0; i < N; i++) {
243             Element JavaDoc row = cb.build(i);
244         }
245     }
246
247
248     private void buildCells(Element JavaDoc row, int[] cellIndex, boolean even) {
249         int columns = result.getAxes()[0].getPositions().size();
250         for (int i = 0; i < columns; i++) {
251             cellIndex[0] = i;
252             Cell cell = result.getCell(cellIndex);
253             buildCell(cell, row, even);
254         }
255     }
256
257     private void buildCell(Cell cell, Element JavaDoc row, boolean even) {
258         Element JavaDoc cellElem = elem("cell", row);
259         String JavaDoc s = cell.getFormattedValue();
260         if (s == null || s.length() == 0 || s.equals("(null)"))
261             s = "\u00a0"; // &nbsp;
262
cellElem.setAttribute("value", s);
263         cellElem.setAttribute("style", even ? "even" : "odd");
264     }
265
266     private void buildRows0Dim(Element JavaDoc parent) {
267         int[] cellIndex = new int[0];
268         Element JavaDoc row = elem("row", parent);
269         Cell cell = result.getCell(cellIndex);
270         buildCell(cell, row, false);
271     }
272
273     private void buildSlicer(Element JavaDoc parent) {
274         List JavaDoc<Position> positions = result.getSlicerAxis().getPositions();
275         for (int i = 0; i < positions.size(); i++) {
276             Position position = positions.get(i);
277             if (position.size() > 0) {
278                 Element JavaDoc el = elem("position", parent);
279                 for (int j = 0; j < position.size(); j++) {
280                     createMemberElem("member", el, position.get(j));
281                 }
282             }
283         }
284     }
285
286     private Element JavaDoc createMemberElem(String JavaDoc name, Element JavaDoc parent, Member m) {
287         Element JavaDoc e = elem(name, parent);
288         e.setAttribute("caption", m.getCaption());
289         e.setAttribute("depth", Integer.toString(m.getLevel().getDepth()));
290         //e.setAttribute("name", m.getName());
291
//e.setAttribute("qname", m.getQualifiedName());
292
e.setAttribute("uname", m.getUniqueName());
293         e.setAttribute("colspan", "1");
294         e.setAttribute("rowspan", "1");
295
296         // add properties to dom tree
297
addMemberProperties(m, e);
298
299         return e;
300     }
301
302     private void addMemberProperties(Member m, Element JavaDoc e) {
303         Property[] props = m.getLevel().getProperties();
304         if (props != null) {
305           for (int i = 0; i < props.length; i++) {
306             String JavaDoc propName = props[i].getName();
307             String JavaDoc propValue = "" + m.getPropertyValue(propName);
308             Element JavaDoc propElem = elem("property", e);
309             propElem.setAttribute("name", propName);
310             propElem.setAttribute("value", propValue);
311           }
312         }
313     }
314
315     private Element JavaDoc elem(String JavaDoc name, Element JavaDoc parent) {
316         Element JavaDoc elem = factory.createElement(name);
317         parent.appendChild(elem);
318         return elem;
319     }
320
321     private Object JavaDoc cdata(String JavaDoc content, Element JavaDoc parent) {
322         CDATASection JavaDoc section = factory.createCDATASection(content);
323         parent.appendChild(section);
324         return section;
325     }
326
327     private static final String JavaDoc PRETTY_PRINTER = ""
328     + "<xsl:stylesheet version=\"1.0\" xmlns:xsl=\"http://www.w3.org/1999/XSL/Transform\">\n"
329     + "<xsl:output method=\"xml\" indent=\"yes\"/>\n"
330     + "<xsl:template match=\"*|@*\">\n"
331     + " <xsl:copy>\n"
332     + " <xsl:apply-templates select=\"*|@*\"/>\n"
333     + " </xsl:copy>\n"
334     + "</xsl:template>\n"
335     + "</xsl:stylesheet>\n";
336
337     public static void debug(Document JavaDoc doc) {
338         try {
339             TransformerFactory JavaDoc tf = TransformerFactory.newInstance();
340             StringReader JavaDoc input = new StringReader JavaDoc(PRETTY_PRINTER);
341             //File input = new File(System.getProperty("test.dir") + "/" + "pretty.xsl");
342
Templates JavaDoc templates = tf.newTemplates(new StreamSource JavaDoc(input));
343             OutputStream JavaDoc result = new ByteArrayOutputStream JavaDoc();
344             templates.newTransformer().transform(new DOMSource JavaDoc(doc), new StreamResult JavaDoc(result));
345             LOGGER.debug(result.toString());
346         }
347         catch (Exception JavaDoc e) {
348             e.printStackTrace();
349         }
350     }
351
352 }
353
354 // End DOMBuilder.java
355
Popular Tags