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 org.w3c.dom.*;
029:
030: /**
031: * Abstract base class for measuring performance of any of the DOM document
032: * representations. Subclasses need to implement the actual document building
033: * and text output methods, but can use the common tree walking code provided
034: * here.
035: *
036: * @author Dennis M. Sosnoski
037: * @version 1.2
038: */
039:
040: public abstract class BenchDOM extends BenchDocBase {
041: /**
042: * Constructor.
043: *
044: * @param config test configuration name
045: */
046:
047: protected BenchDOM(String config) {
048: super (config);
049: }
050:
051: /**
052: * Walk subtree for element. This recursively walks through the document
053: * nodes under an element, accumulating summary information.
054: *
055: * @param element element to be walked
056: * @param summary document summary information
057: */
058:
059: protected void walkElement(Element element, DocumentSummary summary) {
060:
061: // include attribute values in summary
062: if (element.hasAttributes()) {
063: NamedNodeMap attrs = element.getAttributes();
064: for (int i = 0; i < attrs.getLength(); i++) {
065: summary.addAttribute(attrs.item(i).getNodeValue()
066: .length());
067: }
068: }
069:
070: // loop through children
071: if (element.hasChildNodes()) {
072: Node child = (Node) element.getFirstChild();
073: while (child != null) {
074:
075: // handle child by type
076: int type = child.getNodeType();
077: if (type == Node.TEXT_NODE) {
078: summary.addContent(child.getNodeValue().length());
079: } else if (type == Node.ELEMENT_NODE) {
080: summary.addElements(1);
081: walkElement((Element) child, summary);
082: }
083: child = child.getNextSibling();
084: }
085: }
086: }
087:
088: /**
089: * Walk and summarize document. This method walks through the nodes
090: * of the document, accumulating summary information.
091: *
092: * @param doc document representation to be walked
093: * @param summary output document summary information
094: */
095:
096: protected void walk(Object doc, DocumentSummary summary) {
097: summary.addElements(1);
098: walkElement(((Document) doc).getDocumentElement(), summary);
099: }
100:
101: /**
102: * Modify subtree for element. This recursively walks through the document
103: * nodes under an element, performing the modifications.
104: *
105: * @param element element to be walked
106: */
107:
108: protected void modifyElement(Element element) {
109:
110: // check for children present
111: if (element.hasChildNodes()) {
112:
113: // loop through child nodes
114: Node child;
115: Node next = (Node) element.getFirstChild();
116: Document doc = null;
117: String prefix = null;
118: String uri = null;
119: boolean content = false;
120: while ((child = next) != null) {
121:
122: // set next before we change anything
123: next = child.getNextSibling();
124:
125: // handle child by node type
126: if (child.getNodeType() == Node.TEXT_NODE) {
127:
128: // trim whitespace from content text
129: String trimmed = child.getNodeValue().trim();
130: if (trimmed.length() == 0) {
131:
132: // delete child if nothing but whitespace
133: element.removeChild(child);
134:
135: } else {
136:
137: // make sure we have the parent element information
138: if (!content) {
139: doc = element.getOwnerDocument();
140: prefix = element.getPrefix();
141: uri = element.getNamespaceURI();
142: content = true;
143: }
144:
145: // create a "text" element matching parent namespace
146: Element text;
147: if (uri == null) {
148: text = doc.createElement("text");
149: } else {
150: text = doc.createElementNS(uri, prefix
151: + ":text");
152: }
153:
154: // wrap the trimmed content with new element
155: text.appendChild(doc.createTextNode(trimmed));
156: element.replaceChild(text, child);
157:
158: }
159: } else if (child.getNodeType() == Node.ELEMENT_NODE) {
160:
161: // handle child elements with recursive call
162: modifyElement((Element) child);
163:
164: }
165: }
166:
167: // check if we've seen any non-whitespace content for element
168: if (content) {
169:
170: // add attribute flagging content found
171: if (prefix == null || prefix.length() == 0) {
172: element.setAttribute("text", "true");
173: } else {
174: element.setAttributeNS(uri, prefix + ":text",
175: "true");
176: }
177:
178: }
179: }
180: }
181:
182: /**
183: * Modify a document representation. This implementation of the abstract
184: * superclass method walks the document representation performing the
185: * following modifications: remove all content segments which consist only
186: * of whitespace; add an attribute "text" set to "true" to any elements
187: * which directly contain non-whitespace text content; and replace each
188: * non-whitespace text content segment with a "text" element which wraps
189: * the trimmed content.
190: *
191: * @param doc document representation to be modified
192: */
193:
194: protected void modify(Object doc) {
195: modifyElement(((Document) doc).getDocumentElement());
196: }
197: }
|