2 * Copyright (c) 2001-2007 Sun Microsystems, Inc. All rights reserved.
4 * The Sun Project JXTA(TM) Software License
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * 1. Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright notice,
13 * this list of conditions and the following disclaimer in the documentation
14 * and/or other materials provided with the distribution.
16 * 3. The end-user documentation included with the redistribution, if any, must
17 * include the following acknowledgment: "This product includes software
18 * developed by Sun Microsystems, Inc. for JXTA(TM) technology."
19 * Alternately, this acknowledgment may appear in the software itself, if
20 * and wherever such third-party acknowledgments normally appear.
22 * 4. The names "Sun", "Sun Microsystems, Inc.", "JXTA" and "Project JXTA" must
23 * not be used to endorse or promote products derived from this software
24 * without prior written permission. For written permission, please contact
25 * Project JXTA at http://www.jxta.org.
27 * 5. Products derived from this software may not be called "JXTA", nor may
28 * "JXTA" appear in their name, without prior written permission of Sun.
30 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
31 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
32 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SUN
33 * MICROSYSTEMS OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
34 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
36 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
37 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
38 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
39 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
41 * JXTA is a registered trademark of Sun Microsystems, Inc. in the United
42 * States and other countries.
44 * Please see the license information page at :
45 * <http://www.jxta.org/project/www/license.html> for instructions on use of
46 * the license in source files.
48 * ====================================================================
50 * This software consists of voluntary contributions made by many individuals
51 * on behalf of Project JXTA. For more information on Project JXTA, please see
52 * http://www.jxta.org.
54 * This license is based on the BSD license adopted by the Apache Foundation.
57 package net.jxta.impl.document;
60 import net.jxta.document.Attribute;
61 import net.jxta.document.XMLElement;
63 import org.w3c.dom.Element;
64 import org.w3c.dom.NamedNodeMap;
65 import org.w3c.dom.Node;
67 import java.util.ArrayList;
68 import java.util.Collections;
69 import java.util.Enumeration;
70 import java.util.List;
74 * This class represent an element of an XML document. XML Documents are formed
75 * as a hierarchy of elements. Each element provides a proxy for DOM elements
76 * and the text nodes containing values.
78 public class DOMXMLElement implements XMLElement<DOMXMLElement> {
80 protected DOMXMLDocument root;
83 * The DOM node for which this element is a proxy.
85 protected Node domNode;
88 * Constructor for associating a DOM node with a StructuredDocument Element.
90 * @param root the DOM not which is to be associated with this element.
91 * @param node the DOM node
93 protected DOMXMLElement(DOMXMLDocument root, Node node) {
99 * Get the name associated with an element.
101 * @return A string containing the key of this element.
103 public String getKey() {
108 * Get the value (if any) associated with an element.
110 * @return A string containing the value of this element, if any, otherwise null.
112 public String getValue() {
113 return getTextValue();
117 * Get the name associated with an element.
119 * @return A string containing the name of this element.
121 public String getName() {
122 return getAssocNode().getNodeName();
126 * Get the value (if any) associated with an element.
128 * @return A string containing the value of this element, if any, otherwise null.
130 public String getTextValue() {
131 StringBuilder itsValue = new StringBuilder();
133 for (Node eachChild = getAssocNode().getFirstChild(); eachChild != null; eachChild = eachChild.getNextSibling()) {
134 if (Node.TEXT_NODE == eachChild.getNodeType()) {
135 itsValue.append(eachChild.getNodeValue());
139 if (0 == itsValue.length()) {
142 return itsValue.toString();
147 * Get the root element of the hierarchy this element belongs to.
149 * @return StructuredDocument root of this element's hierarchy.
151 public DOMXMLDocument getRoot() {
156 * Get the parent of this element. If the element has not been inserted into
157 * the Document then null is returned. If this element is the root of the
158 * Document then it returns itself.
160 public DOMXMLElement getParent() {
161 Node node = getAssocNode();
163 if (node.getOwnerDocument().equals(node)) {
164 return new DOMXMLElement(root, node);
166 return new DOMXMLElement(root, node.getParentNode());
171 * Add a child element to this element
173 * @param element the element to be added as a child
175 public void appendChild(DOMXMLElement element) {
176 getAssocNode().appendChild(element.getAssocNode());
180 * Returns an enumeration of the immediate children of this element
182 * @return An enumeration containing all of the children of this element.
184 public Enumeration<DOMXMLElement> getChildren() {
185 List<DOMXMLElement> children = new ArrayList<DOMXMLElement>();
187 for (Node eachChild = getAssocNode().getFirstChild(); eachChild != null; eachChild = eachChild.getNextSibling()) {
188 if (Node.ELEMENT_NODE == eachChild.getNodeType()) {
189 children.add(new DOMXMLElement(root, eachChild));
193 return Collections.enumeration(children);
197 * Returns an enumeration of the immediate children of this element whose
198 * name match the specified string.
200 * @param key The key which will be matched against.
201 * @return enumeration containing all of the children of this element.
203 public Enumeration<DOMXMLElement> getChildren(Object key) {
204 if (key instanceof String)
205 return getChildren((String) key);
207 throw new ClassCastException(key.getClass().getName() + " not supported by getChildren.");
211 * Returns an enumeration of the immediate children of this element whose
212 * name match the specified string.
214 * @param name The name which will be matched against.
215 * @return An enumeration containing all of the children of this element.
217 public Enumeration<DOMXMLElement> getChildren(String name) {
218 List<DOMXMLElement> children = new ArrayList<DOMXMLElement>();
220 for (Node eachChild = getAssocNode().getFirstChild(); eachChild != null; eachChild = eachChild.getNextSibling()) {
221 if ((Node.ELEMENT_NODE == eachChild.getNodeType()) && (name.equals(eachChild.getNodeName()))) {
222 children.add(new DOMXMLElement(root, eachChild));
226 return Collections.enumeration(children);
230 * Tests two elements for equality. For the XML document the definition of
234 * <li>the item compared against must be an XML Element.</li>
236 * <li>The items must belong to the same document.</li>
238 * <li>The items must have the same name.</li>
240 * <li>The items must have the save textual value.</li>
243 * @param element the element to be compared against.
244 * @return true if the elements are equal
247 public boolean equals(Object element) {
248 if (this == element) {
252 if (!(element instanceof DOMXMLElement)) {
256 DOMXMLElement xmlElement = (DOMXMLElement) element;
258 Node me = getAssocNode();
259 Node it = xmlElement.getAssocNode();
265 if (me.getOwnerDocument() != it.getOwnerDocument()) {
269 if (!getName().equals(xmlElement.getName())) {
273 String val1 = getTextValue();
274 String val2 = xmlElement.getTextValue();
276 return (null == val1) && (null == val2) || null != val1 && null != val2 && val1.equals(val2);
281 * Returns the DOM Node associated with this StructuredDocument element.
283 * @return Node The DOM Node associated with this StructuredDocument element.
285 protected Node getAssocNode() {
289 // Attributable methods
292 * Adds an attribute with the given name and value. Some implementations
293 * may support only a single value for each distinct name. Others may
294 * support multiple values for each name. If the value being provided
295 * replaces some other value then that value is returned otherwise null
298 * @param name name of the attribute.
299 * @param value value for the attribute.
300 * @return String containing previous value for this name if the value
301 * is being replaced otherwise null.
303 public String addAttribute(String name, String value) {
304 String oldAttrValue = ((Element) getAssocNode()).getAttribute(name);
306 ((Element) getAssocNode()).setAttribute(name, value);
307 return (0 == oldAttrValue.length()) ? null : oldAttrValue;
311 * Adds an attribute with the given name and value. Some implementations
312 * may support only a single value for each distinct name. Others may
313 * support multiple values for each name. If the value being provided
314 * replaces some other value then that value is returned otherwise null
317 * @param newAttrib new attribute.
318 * @return String containing previous value for this name if the value
319 * is being replaced otherwise null.
321 public String addAttribute(Attribute newAttrib) {
322 String oldAttrValue = ((Element) getAssocNode()).getAttribute(newAttrib.getName());
324 ((Element) getAssocNode()).setAttribute(newAttrib.getName(), newAttrib.getValue());
325 return (0 == oldAttrValue.length()) ? null : oldAttrValue;
329 * Returns an enumerations of the attributes assosicated with this object.
330 * Each element is of type Attribute.
332 * @return Enumeration the attributes associated with this object.
334 public Enumeration<Attribute> getAttributes() {
335 NamedNodeMap nmap = getAssocNode().getAttributes();
338 List<Attribute> noAttrs = Collections.emptyList();
340 return Collections.enumeration(noAttrs);
343 List<Attribute> attrs = new ArrayList<Attribute>();
345 for (int i = 0; i < nmap.getLength(); i++) {
346 Node domAttr = nmap.item(i);
347 Attribute attr = new Attribute(this, domAttr.getNodeName(), domAttr.getNodeValue());
352 return Collections.enumeration(attrs);
356 * returns a single attribute which matches the name provided. If no such
357 * named attribute exists then null is returned. For impelementations of
358 * this interface which support multiple values for each name only the
359 * first value will be returned. To access all values for a name you must
362 * @return Attribute the attributes matching the given name.
364 public Attribute getAttribute(String name) {
365 NamedNodeMap nmap = (getAssocNode()).getAttributes();
371 for (int i = 0; i < nmap.getLength(); i++) {
372 Node domAttr = nmap.item(i);
374 if (name.equals(domAttr.getNodeName())) {
375 Attribute attr = new Attribute(this, domAttr.getNodeName(), domAttr.getNodeValue());