View Javadoc

1   /*
2    * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
3    *
4    * This software is open source.
5    * See the bottom of this file for the licence.
6    */
7   
8   package org.dom4j.dom;
9   
10  import java.util.ArrayList;
11  import java.util.List;
12  
13  import org.dom4j.Attribute;
14  import org.dom4j.DocumentFactory;
15  import org.dom4j.Namespace;
16  import org.dom4j.QName;
17  import org.dom4j.tree.DefaultElement;
18  
19  import org.w3c.dom.DOMException;
20  import org.w3c.dom.Document;
21  import org.w3c.dom.NamedNodeMap;
22  import org.w3c.dom.Node;
23  import org.w3c.dom.NodeList;
24  
25  /***
26   * <p>
27   * <code>DOMElement</code> implements an XML element which supports the W3C
28   * DOM API.
29   * </p>
30   * 
31   * @author <a href="mailto:jstrachan@apache.org">James Strachan </a>
32   * @version $Revision: 1.23 $
33   */
34  public class DOMElement extends DefaultElement implements org.w3c.dom.Element {
35      /*** The <code>DocumentFactory</code> instance used by default */
36      private static final DocumentFactory DOCUMENT_FACTORY = DOMDocumentFactory
37              .getInstance();
38  
39      public DOMElement(String name) {
40          super(name);
41      }
42  
43      public DOMElement(QName qname) {
44          super(qname);
45      }
46  
47      public DOMElement(QName qname, int attributeCount) {
48          super(qname, attributeCount);
49      }
50  
51      public DOMElement(String name, Namespace namespace) {
52          super(name, namespace);
53      }
54  
55      // org.w3c.dom.Node interface
56      // -------------------------------------------------------------------------
57      public boolean supports(String feature, String version) {
58          return DOMNodeHelper.supports(this, feature, version);
59      }
60  
61      public String getNamespaceURI() {
62          return getQName().getNamespaceURI();
63      }
64  
65      public String getPrefix() {
66          return getQName().getNamespacePrefix();
67      }
68  
69      public void setPrefix(String prefix) throws DOMException {
70          DOMNodeHelper.setPrefix(this, prefix);
71      }
72  
73      public String getLocalName() {
74          return getQName().getName();
75      }
76  
77      public String getNodeName() {
78          return getName();
79      }
80  
81      // already part of API
82      //
83      // public short getNodeType();
84      public String getNodeValue() throws DOMException {
85          return null;
86      }
87  
88      public void setNodeValue(String nodeValue) throws DOMException {
89      }
90  
91      public org.w3c.dom.Node getParentNode() {
92          return DOMNodeHelper.getParentNode(this);
93      }
94  
95      public NodeList getChildNodes() {
96          return DOMNodeHelper.createNodeList(content());
97      }
98  
99      public org.w3c.dom.Node getFirstChild() {
100         return DOMNodeHelper.asDOMNode(node(0));
101     }
102 
103     public org.w3c.dom.Node getLastChild() {
104         return DOMNodeHelper.asDOMNode(node(nodeCount() - 1));
105     }
106 
107     public org.w3c.dom.Node getPreviousSibling() {
108         return DOMNodeHelper.getPreviousSibling(this);
109     }
110 
111     public org.w3c.dom.Node getNextSibling() {
112         return DOMNodeHelper.getNextSibling(this);
113     }
114 
115     public NamedNodeMap getAttributes() {
116         return new DOMAttributeNodeMap(this);
117     }
118 
119     public Document getOwnerDocument() {
120         return DOMNodeHelper.getOwnerDocument(this);
121     }
122 
123     public org.w3c.dom.Node insertBefore(org.w3c.dom.Node newChild,
124             org.w3c.dom.Node refChild) throws DOMException {
125         checkNewChildNode(newChild);
126 
127         return DOMNodeHelper.insertBefore(this, newChild, refChild);
128     }
129 
130     public org.w3c.dom.Node replaceChild(org.w3c.dom.Node newChild,
131             org.w3c.dom.Node oldChild) throws DOMException {
132         checkNewChildNode(newChild);
133 
134         return DOMNodeHelper.replaceChild(this, newChild, oldChild);
135     }
136 
137     public org.w3c.dom.Node removeChild(org.w3c.dom.Node oldChild)
138             throws DOMException {
139         return DOMNodeHelper.removeChild(this, oldChild);
140     }
141 
142     public org.w3c.dom.Node appendChild(org.w3c.dom.Node newChild)
143             throws DOMException {
144         checkNewChildNode(newChild);
145 
146         return DOMNodeHelper.appendChild(this, newChild);
147     }
148 
149     private void checkNewChildNode(org.w3c.dom.Node newChild)
150             throws DOMException {
151         final int nodeType = newChild.getNodeType();
152 
153         if (!((nodeType == Node.ELEMENT_NODE) || (nodeType == Node.TEXT_NODE)
154                 || (nodeType == Node.COMMENT_NODE)
155                 || (nodeType == Node.PROCESSING_INSTRUCTION_NODE)
156                 || (nodeType == Node.CDATA_SECTION_NODE) 
157                 || (nodeType == Node.ENTITY_REFERENCE_NODE))) {
158             throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
159                     "Given node cannot be a child of element");
160         }
161     }
162 
163     public boolean hasChildNodes() {
164         return nodeCount() > 0;
165     }
166 
167     public org.w3c.dom.Node cloneNode(boolean deep) {
168         return DOMNodeHelper.cloneNode(this, deep);
169     }
170 
171     public boolean isSupported(String feature, String version) {
172         return DOMNodeHelper.isSupported(this, feature, version);
173     }
174 
175     public boolean hasAttributes() {
176         return DOMNodeHelper.hasAttributes(this);
177     }
178 
179     // org.w3c.dom.Element interface
180     // -------------------------------------------------------------------------
181     public String getTagName() {
182         return getName();
183     }
184 
185     public String getAttribute(String name) {
186         String answer = attributeValue(name);
187 
188         return (answer != null) ? answer : "";
189     }
190 
191     public void setAttribute(String name, String value) throws DOMException {
192         addAttribute(name, value);
193     }
194 
195     public void removeAttribute(String name) throws DOMException {
196         Attribute attribute = attribute(name);
197 
198         if (attribute != null) {
199             remove(attribute);
200         }
201     }
202 
203     public org.w3c.dom.Attr getAttributeNode(String name) {
204         return DOMNodeHelper.asDOMAttr(attribute(name));
205     }
206 
207     public org.w3c.dom.Attr setAttributeNode(org.w3c.dom.Attr newAttr)
208             throws DOMException {
209         if (this.isReadOnly()) {
210             throw new DOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
211                     "No modification allowed");
212         }
213 
214         Attribute attribute = attribute(newAttr);
215 
216         if (attribute != newAttr) {
217             if (newAttr.getOwnerElement() != null) {
218                 throw new DOMException(DOMException.INUSE_ATTRIBUTE_ERR,
219                         "Attribute is already in use");
220             }
221 
222             Attribute newAttribute = createAttribute(newAttr);
223 
224             if (attribute != null) {
225                 attribute.detach();
226             }
227 
228             add(newAttribute);
229         }
230 
231         return DOMNodeHelper.asDOMAttr(attribute);
232     }
233 
234     public org.w3c.dom.Attr removeAttributeNode(org.w3c.dom.Attr oldAttr)
235             throws DOMException {
236         Attribute attribute = attribute(oldAttr);
237 
238         if (attribute != null) {
239             attribute.detach();
240 
241             return DOMNodeHelper.asDOMAttr(attribute);
242         } else {
243             throw new DOMException(DOMException.NOT_FOUND_ERR,
244                     "No such attribute");
245         }
246     }
247 
248     public String getAttributeNS(String namespaceURI, String localName) {
249         Attribute attribute = attribute(namespaceURI, localName);
250 
251         if (attribute != null) {
252             String answer = attribute.getValue();
253 
254             if (answer != null) {
255                 return answer;
256             }
257         }
258 
259         return "";
260     }
261 
262     public void setAttributeNS(String namespaceURI, String qualifiedName,
263             String value) throws DOMException {
264         Attribute attribute = attribute(namespaceURI, qualifiedName);
265 
266         if (attribute != null) {
267             attribute.setValue(value);
268         } else {
269             QName qname = getQName(namespaceURI, qualifiedName);
270             addAttribute(qname, value);
271         }
272     }
273 
274     public void removeAttributeNS(String namespaceURI, String localName)
275             throws DOMException {
276         Attribute attribute = attribute(namespaceURI, localName);
277 
278         if (attribute != null) {
279             remove(attribute);
280         }
281     }
282 
283     public org.w3c.dom.Attr getAttributeNodeNS(String namespaceURI,
284             String localName) {
285         Attribute attribute = attribute(namespaceURI, localName);
286 
287         if (attribute != null) {
288             DOMNodeHelper.asDOMAttr(attribute);
289         }
290 
291         return null;
292     }
293 
294     public org.w3c.dom.Attr setAttributeNodeNS(org.w3c.dom.Attr newAttr)
295             throws DOMException {
296         Attribute attribute = attribute(newAttr.getNamespaceURI(), newAttr
297                 .getLocalName());
298 
299         if (attribute != null) {
300             attribute.setValue(newAttr.getValue());
301         } else {
302             attribute = createAttribute(newAttr);
303             add(attribute);
304         }
305 
306         return DOMNodeHelper.asDOMAttr(attribute);
307     }
308 
309     public NodeList getElementsByTagName(String name) {
310         ArrayList list = new ArrayList();
311         DOMNodeHelper.appendElementsByTagName(list, this, name);
312 
313         return DOMNodeHelper.createNodeList(list);
314     }
315 
316     public NodeList getElementsByTagNameNS(String namespace, String lName) {
317         ArrayList list = new ArrayList();
318         DOMNodeHelper.appendElementsByTagNameNS(list, this, namespace, lName);
319 
320         return DOMNodeHelper.createNodeList(list);
321     }
322 
323     public boolean hasAttribute(String name) {
324         return attribute(name) != null;
325     }
326 
327     public boolean hasAttributeNS(String namespaceURI, String localName) {
328         return attribute(namespaceURI, localName) != null;
329     }
330 
331     // Implementation methods
332     // -------------------------------------------------------------------------
333     protected DocumentFactory getDocumentFactory() {
334         DocumentFactory factory = getQName().getDocumentFactory();
335 
336         return (factory != null) ? factory : DOCUMENT_FACTORY;
337     }
338 
339     protected Attribute attribute(org.w3c.dom.Attr attr) {
340         return attribute(DOCUMENT_FACTORY.createQName(attr.getLocalName(), attr
341                 .getPrefix(), attr.getNamespaceURI()));
342     }
343 
344     protected Attribute attribute(String namespaceURI, String localName) {
345         List attributes = attributeList();
346         int size = attributes.size();
347 
348         for (int i = 0; i < size; i++) {
349             Attribute attribute = (Attribute) attributes.get(i);
350 
351             if (localName.equals(attribute.getName())
352                     && (((namespaceURI == null || namespaceURI.length() == 0)
353                           && ((attribute.getNamespaceURI() == null) 
354                               || (attribute.getNamespaceURI().length() == 0)))
355                               || ((namespaceURI != null) && namespaceURI
356                                       .equals(attribute.getNamespaceURI())))) {
357                 return attribute;
358             }
359         }
360 
361         return null;
362     }
363 
364     protected Attribute createAttribute(org.w3c.dom.Attr newAttr) {
365         QName qname = null;
366         String name = newAttr.getLocalName();
367 
368         if (name != null) {
369             String prefix = newAttr.getPrefix();
370             String uri = newAttr.getNamespaceURI();
371             qname = getDocumentFactory().createQName(name, prefix, uri);
372         } else {
373             name = newAttr.getName();
374             qname = getDocumentFactory().createQName(name);
375         }
376 
377         return new DOMAttribute(qname, newAttr.getValue());
378     }
379 
380     protected QName getQName(String namespace, String qualifiedName) {
381         int index = qualifiedName.indexOf(':');
382         String prefix = "";
383         String localName = qualifiedName;
384 
385         if (index >= 0) {
386             prefix = qualifiedName.substring(0, index);
387             localName = qualifiedName.substring(index + 1);
388         }
389 
390         return getDocumentFactory().createQName(localName, prefix, namespace);
391     }
392 }
393 
394 /*
395  * Redistribution and use of this software and associated documentation
396  * ("Software"), with or without modification, are permitted provided that the
397  * following conditions are met:
398  * 
399  * 1. Redistributions of source code must retain copyright statements and
400  * notices. Redistributions must also contain a copy of this document.
401  * 
402  * 2. Redistributions in binary form must reproduce the above copyright notice,
403  * this list of conditions and the following disclaimer in the documentation
404  * and/or other materials provided with the distribution.
405  * 
406  * 3. The name "DOM4J" must not be used to endorse or promote products derived
407  * from this Software without prior written permission of MetaStuff, Ltd. For
408  * written permission, please contact dom4j-info@metastuff.com.
409  * 
410  * 4. Products derived from this Software may not be called "DOM4J" nor may
411  * "DOM4J" appear in their names without prior written permission of MetaStuff,
412  * Ltd. DOM4J is a registered trademark of MetaStuff, Ltd.
413  * 
414  * 5. Due credit should be given to the DOM4J Project - http://www.dom4j.org
415  * 
416  * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS ``AS IS'' AND
417  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
418  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
419  * ARE DISCLAIMED. IN NO EVENT SHALL METASTUFF, LTD. OR ITS CONTRIBUTORS BE
420  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
421  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
422  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
423  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
424  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
425  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
426  * POSSIBILITY OF SUCH DAMAGE.
427  * 
428  * Copyright 2001-2005 (C) MetaStuff, Ltd. All Rights Reserved.
429  */