001: /*
002: * Copyright (c) 2000-2001 Sosnoski Software Solutions, Inc.
003: *
004: * Permission is hereby granted, free of charge, to any person obtaining a copy
005: * of this software and associated documentation files (the "Software"), to deal
006: * in the Software without restriction, including without limitation the rights
007: * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
008: * copies of the Software, and to permit persons to whom the Software is
009: * furnished to do so, subject to the following conditions:
010: *
011: * The above copyright notice and this permission notice shall be included in
012: * all copies or substantial portions of the Software.
013: *
014: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
015: * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
016: * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
017: * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
018: * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
019: * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
020: * IN THE SOFTWARE.
021: */
022:
023: package com.sosnoski.xmlbench;
024:
025: import java.io.*;
026: import java.util.*;
027:
028: import javax.xml.parsers.*;
029:
030: import org.jdom.*;
031: import org.jdom.input.*;
032: import org.jdom.output.*;
033:
034: /**
035: * Benchmark for measuring performance of the JDOM document representation.
036: *
037: * @author Dennis M. Sosnoski
038: * @version 1.2
039: */
040:
041: public class BenchJDOM extends BenchDocBase {
042: /** SAX builder used within a test run. */
043: private SAXBuilder m_builder;
044:
045: /** XML outputter used within a test run. */
046: private XMLOutputter m_outputter;
047:
048: /**
049: * Constructor.
050: */
051:
052: public BenchJDOM() {
053: super ("JDOM");
054: }
055:
056: /**
057: * Build document representation by parsing XML. This implementation
058: * creates a SAX builder if one does not already exist, then reuses
059: * that builder for the duration of a test run..
060: *
061: * @param in XML document input stream
062: * @return document representation
063: */
064:
065: protected Object build(InputStream in) {
066: if (m_builder == null) {
067: m_builder = new SAXBuilder(false);
068: }
069: Object doc = null;
070: try {
071: doc = m_builder.build(in);
072: } catch (Exception ex) {
073: ex.printStackTrace(System.err);
074: System.exit(0);
075: }
076: return doc;
077: }
078:
079: /**
080: * Walk subtree for element. This recursively walks through the document
081: * nodes under an element, accumulating summary information.
082: *
083: * @param element element to be walked
084: * @param summary document summary information
085: */
086:
087: protected void walkElement(Element element, DocumentSummary summary) {
088:
089: // include attribute values in summary
090: List list = element.getAttributes();
091: if (list.size() > 0) {
092: Iterator iter = list.iterator();
093: while (iter.hasNext()) {
094: Attribute attr = (Attribute) iter.next();
095: summary.addAttribute(attr.getValue().length());
096: }
097: }
098:
099: // loop through children
100: list = element.getContent();
101: if (list.size() > 0) {
102: Iterator iter = list.iterator();
103: while (iter.hasNext()) {
104:
105: // handle child by type
106: Object child = iter.next();
107: if (child instanceof String) {
108: summary.addContent(((String) child).length());
109: } else if (child instanceof Element) {
110: summary.addElements(1);
111: walkElement((Element) child, summary);
112: }
113:
114: }
115: }
116: }
117:
118: /**
119: * Walk and summarize document. This method walks through the nodes
120: * of the document, accumulating summary information.
121: *
122: * @param doc document representation to be walked
123: * @param summary output document summary information
124: */
125:
126: protected void walk(Object doc, DocumentSummary summary) {
127: summary.addElements(1);
128: walkElement(((Document) doc).getRootElement(), summary);
129: }
130:
131: /**
132: * Output a document as XML text. This method uses the method defined
133: * by JDOM to output a text representation of the document.
134: *
135: * @param doc document representation to be output
136: * @param out XML document output stream
137: */
138:
139: protected void output(Object doc, OutputStream out) {
140: if (m_outputter == null) {
141: m_outputter = new XMLOutputter();
142: }
143: try {
144: m_outputter.output((Document) doc, out);
145: } catch (Exception ex) {
146: ex.printStackTrace(System.err);
147: System.exit(0);
148: }
149: }
150:
151: /**
152: * Modify subtree for element. This recursively walks through the document
153: * nodes under an element, performing the modifications.
154: *
155: * @param element element to be walked
156: */
157:
158: protected void modifyElement(Element element) {
159:
160: // check for children present
161: List children = element.getContent();
162: if (children.size() > 0) {
163:
164: // loop through child nodes
165: int ccnt = children.size();
166: Namespace namespace = null;
167: boolean content = false;
168: for (int i = 0; i < ccnt; i++) {
169:
170: // handle child by node type
171: Object child = children.get(i);
172: if (child instanceof String) {
173:
174: // trim whitespace from content text
175: String trimmed = child.toString().trim();
176: if (trimmed.length() == 0) {
177:
178: // delete child if only whitespace (adjusting index)
179: children.remove(i--);
180: --ccnt;
181:
182: } else {
183:
184: // set namespace if first content found
185: if (!content) {
186: namespace = element.getNamespace();
187: content = true;
188: }
189:
190: // wrap the trimmed content with new element
191: Element text = new Element("text", namespace);
192: text.setText(trimmed);
193: children.set(i, text);
194:
195: }
196: } else if (child instanceof Element) {
197:
198: // handle child elements with recursive call
199: modifyElement((Element) child);
200:
201: }
202: }
203:
204: // check if we've seen any non-whitespace content for element
205: if (content) {
206:
207: // add attribute flagging content found
208: if (namespace.getPrefix().length() == 0) {
209: element.setAttribute("text", "true");
210: } else {
211: element.setAttribute("text", "true", namespace);
212: }
213:
214: }
215: }
216: }
217:
218: /**
219: * Modify a document representation. This implementation of the abstract
220: * superclass method walks the document representation performing the
221: * following modifications: remove all content segments which consist only
222: * of whitespace; add an attribute "text" set to "true" to any elements
223: * which directly contain non-whitespace text content; and replace each
224: * non-whitespace text content segment with a "text" element which wraps
225: * the trimmed content.
226: *
227: * @param doc document representation to be modified
228: */
229:
230: protected void modify(Object doc) {
231: modifyElement(((Document) doc).getRootElement());
232: }
233:
234: /**
235: * Reset test class instance. This discards the SAX builder used
236: * within a test pass.
237: */
238:
239: protected void reset() {
240: m_builder = null;
241: m_outputter = null;
242: }
243: }
|