001: /*
002: * This file is part of the Echo Web Application Framework (hereinafter "Echo").
003: * Copyright (C) 2002-2005 NextApp, Inc.
004: *
005: * Version: MPL 1.1/GPL 2.0/LGPL 2.1
006: *
007: * The contents of this file are subject to the Mozilla Public License Version
008: * 1.1 (the "License"); you may not use this file except in compliance with
009: * the License. You may obtain a copy of the License at
010: * http://www.mozilla.org/MPL/
011: *
012: * Software distributed under the License is distributed on an "AS IS" basis,
013: * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
014: * for the specific language governing rights and limitations under the
015: * License.
016: *
017: * Alternatively, the contents of this file may be used under the terms of
018: * either the GNU General Public License Version 2 or later (the "GPL"), or
019: * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
020: * in which case the provisions of the GPL or the LGPL are applicable instead
021: * of those above. If you wish to allow use of your version of this file only
022: * under the terms of either the GPL or the LGPL, and not to allow others to
023: * use your version of this file under the terms of the MPL, indicate your
024: * decision by deleting the provisions above and replace them with the notice
025: * and other provisions required by the GPL or the LGPL. If you do not delete
026: * the provisions above, a recipient may use your version of this file under
027: * the terms of any one of the MPL, the GPL or the LGPL.
028: */
029:
030: package nextapp.echo2.webrender.util;
031:
032: import java.util.ArrayList;
033: import java.util.List;
034:
035: import javax.xml.parsers.DocumentBuilder;
036: import javax.xml.parsers.DocumentBuilderFactory;
037: import javax.xml.parsers.ParserConfigurationException;
038: import javax.xml.transform.TransformerFactory;
039:
040: import org.w3c.dom.Element;
041: import org.w3c.dom.Node;
042: import org.w3c.dom.NodeList;
043: import org.w3c.dom.Text;
044:
045: /**
046: * A utility class which provides methods for working with a W3C DOM.
047: */
048: public class DomUtil {
049:
050: /**
051: * ThreadLocal cache of <code>DocumentBuilder</code> instances.
052: */
053: private static final ThreadLocal documentBuilders = new ThreadLocal() {
054:
055: /**
056: * @see java.lang.ThreadLocal#initialValue()
057: */
058: protected Object initialValue() {
059: try {
060: DocumentBuilderFactory factory = DocumentBuilderFactory
061: .newInstance();
062: factory.setNamespaceAware(true);
063: DocumentBuilder builder = factory.newDocumentBuilder();
064: return builder;
065: } catch (ParserConfigurationException ex) {
066: throw new RuntimeException(ex);
067: }
068: }
069: };
070:
071: /**
072: * ThreadLocal cache of <code>TransformerFactory</code> instances.
073: */
074: private static final ThreadLocal transformerFactories = new ThreadLocal() {
075:
076: /**
077: * @see java.lang.ThreadLocal#initialValue()
078: */
079: protected Object initialValue() {
080: TransformerFactory factory = TransformerFactory
081: .newInstance();
082: return factory;
083: }
084: };
085:
086: /**
087: * Retrieves a thread-specific <code>DocumentBuilder</code>.
088: *
089: * @return the <code>DocumentBuilder</code> serving the current thread.
090: */
091: public static DocumentBuilder getDocumentBuilder() {
092: return (DocumentBuilder) documentBuilders.get();
093: }
094:
095: /**
096: * Retrieves a thread-specific <code>TransformerFactory</code>.
097: *
098: * @return the <code>TransformerFactory</code> serving the current thread.
099: */
100: public static TransformerFactory getTransformerFactory() {
101: return (TransformerFactory) transformerFactories.get();
102: }
103:
104: /**
105: * Determines whether a specific boolean flag is set on an element.
106: *
107: * @param element The element to analyze.
108: * @param attributeName The name of the boolean 'flag' attribute.
109: * @return True if the value of the attribute is 'true', false if it is
110: * not or if the attribute does not exist.
111: */
112: public static boolean getBooleanAttribute(Element element,
113: String attributeName) {
114: String value = element.getAttribute(attributeName);
115: if (value == null) {
116: return false;
117: } else if (value.equals("true")) {
118: return true;
119: } else {
120: return false;
121: }
122: }
123:
124: /**
125: * Retrieves the first immediate child element of the specified element
126: * whose name matches the provided <code>name</code> parameter.
127: *
128: * @param parentElement The element to search.
129: * @param name The name of the child element.
130: * @return The child element, or null if none was found.
131: */
132: public static Element getChildElementByTagName(
133: Element parentElement, String name) {
134: NodeList nodes = parentElement.getChildNodes();
135: int length = nodes.getLength();
136: for (int index = 0; index < length; ++index) {
137: if (nodes.item(index).getNodeType() == Node.ELEMENT_NODE
138: && name.equals(nodes.item(index).getNodeName())) {
139: return (Element) nodes.item(index);
140: }
141: }
142: return null;
143: }
144:
145: /**
146: * Retrieves the first immediate child element of the specified element
147: * whose name matches the provided <code>name</code> parameter.
148: *
149: * @param parentElement The element to search.
150: * @param namespaceURI The namespace URI of the child element.
151: * @param localName The name of the child element.
152: * @return The child element, or null if none was found.
153: */
154: public static Element getChildElementByTagNameNS(
155: Element parentElement, String namespaceURI, String localName) {
156: NodeList nodes = parentElement.getChildNodes();
157: int length = nodes.getLength();
158: for (int index = 0; index < length; ++index) {
159: if (nodes.item(index).getNodeType() == Node.ELEMENT_NODE
160: && namespaceURI.equals(nodes.item(index)
161: .getNamespaceURI())
162: && localName
163: .equals(nodes.item(index).getNodeName())) {
164: return (Element) nodes.item(index);
165: }
166: }
167: return null;
168: }
169:
170: /**
171: * Retrieves all immediate child elements of the specified element whose
172: * names match the provided <code>name</code> parameter.
173: *
174: * @param parentElement The element to search.
175: * @param name The name of the child element.
176: * @return An array of matching child elements.
177: */
178: public static Element[] getChildElementsByTagName(
179: Element parentElement, String name) {
180: List children = new ArrayList();
181: NodeList nodes = parentElement.getChildNodes();
182: int length = nodes.getLength();
183: for (int index = 0; index < length; ++index) {
184: if (nodes.item(index).getNodeType() == Node.ELEMENT_NODE
185: && name.equals(nodes.item(index).getNodeName())) {
186: children.add(nodes.item(index));
187: }
188: }
189: Element[] childElements = new Element[children.size()];
190: return (Element[]) children.toArray(childElements);
191: }
192:
193: /**
194: * Retrieves all immediate child elements of the specified element whose
195: * names match the provided <code>name</code> parameter.
196: *
197: * @param parentElement The element to search.
198: * @param namespaceURI The namespace URI of the child element.
199: * @param localName The name of the child element.
200: * @return An array of matching child elements.
201: */
202: public static Element[] getChildElementsByTagNameNS(
203: Element parentElement, String namespaceURI, String localName) {
204: List children = new ArrayList();
205: NodeList nodes = parentElement.getChildNodes();
206: int length = nodes.getLength();
207: for (int index = 0; index < length; ++index) {
208: if (nodes.item(index).getNodeType() == Node.ELEMENT_NODE
209: && namespaceURI.equals(nodes.item(index)
210: .getNamespaceURI())
211: && localName
212: .equals(nodes.item(index).getNodeName())) {
213: children.add(nodes.item(index));
214: }
215: }
216: Element[] childElements = new Element[children.size()];
217: return (Element[]) children.toArray(childElements);
218: }
219:
220: /**
221: * Counts the number of immediate child elements of the specified element
222: * whose names match the provided <code>name</code> parameter.
223: *
224: * @param parentElement The element to analyze.
225: * @param name The name of the child element.
226: * @return The number of matching child elements.
227: */
228: public static int getChildElementCountByTagName(
229: Element parentElement, String name) {
230: NodeList nodes = parentElement.getChildNodes();
231: int length = nodes.getLength();
232: int count = 0;
233: for (int index = 0; index < length; ++index) {
234: if (nodes.item(index).getNodeType() == Node.ELEMENT_NODE
235: && name.equals(nodes.item(index).getNodeName())) {
236: ++count;
237: }
238: }
239: return count;
240: }
241:
242: /**
243: * Counts the number of immediate child elements of the specified element
244: * whose names match the provided <code>name</code> parameter.
245: *
246: * @param parentElement The element to analyze.
247: * @param namespaceURI The namespace URI of the child element.
248: * @param localName The name of the child element.
249: * @return The number of matching child elements.
250: */
251: public static int getChildElementCountByTagNameNS(
252: Element parentElement, String namespaceURI, String localName) {
253: NodeList nodes = parentElement.getChildNodes();
254: int length = nodes.getLength();
255: int count = 0;
256: for (int index = 0; index < length; ++index) {
257: if (nodes.item(index).getNodeType() == Node.ELEMENT_NODE
258: && namespaceURI.equals(nodes.item(index)
259: .getNamespaceURI())
260: && localName
261: .equals(nodes.item(index).getNodeName())) {
262: ++count;
263: }
264: }
265: return count;
266: }
267:
268: /**
269: * Returns the text content of a DOM <code>Element</code>.
270: *
271: * @param element The <code>Element</code> to analyze.
272: */
273: public static String getElementText(Element element) {
274: NodeList children = element.getChildNodes();
275: int childCount = children.getLength();
276: for (int index = 0; index < childCount; ++index) {
277: if (children.item(index) instanceof Text) {
278: Text text = (Text) children.item(index);
279: return text.getData();
280: }
281: }
282: return null;
283: }
284:
285: /**
286: * Sets the text content of a DOM <code>Element</code>.
287: *
288: * @param element The <code>Element</code> to modify.
289: * @param value The new text value.
290: */
291: public static void setElementText(Element element, String value) {
292: NodeList children = element.getChildNodes();
293: int childCount = children.getLength();
294: for (int index = 0; index < childCount; ++index) {
295: if (children.item(index) instanceof Text) {
296: Text text = (Text) children.item(index);
297: text.setData(value);
298: return;
299: }
300: }
301: Text text = element.getOwnerDocument().createTextNode(value);
302: element.appendChild(text);
303: }
304:
305: /** Non-instantiable class. */
306: private DomUtil() {
307: }
308: }
|