001/*
002 * Copyright 2001 (C) MetaStuff, Ltd. All Rights Reserved.
003 * 
004 * This software is open source. 
005 * See the bottom of this file for the licence.
006 * 
007 * $Id: DOMElement.java,v 1.14 2002/02/01 10:13:39 jstrachan Exp $
008 */
009
010package org.dom4j.dom;
011
012import java.util.ArrayList;
013import java.util.List;
014
015import org.dom4j.Attribute;
016import org.dom4j.DocumentFactory;
017import org.dom4j.Element;
018import org.dom4j.Namespace;
019import org.dom4j.Node;
020import org.dom4j.QName;
021import org.dom4j.tree.DefaultElement;
022
023import org.w3c.dom.Document;
024import org.w3c.dom.DOMException;
025import org.w3c.dom.NamedNodeMap;
026import org.w3c.dom.NodeList;
027
028/** <p><code>DOMAttribute</code> implements an XML element which 
029  * supports the W3C DOM API.</p>
030  *
031  * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>
032  * @version $Revision: 1.14 $
033  */
034public class DOMElement extends DefaultElement implements org.w3c.dom.Element {
035
036    /** The <code>DocumentFactory</code> instance used by default */
037    private static final DocumentFactory DOCUMENT_FACTORY = DOMDocumentFactory.getInstance();
038    
039
040    public DOMElement(String name) { 
041        super(name);
042    }
043
044    public DOMElement(QName qname) { 
045        super(qname);
046    }
047
048    public DOMElement(QName qname, int attributeCount) { 
049        super(qname, attributeCount);
050    }
051    
052    public DOMElement(String name, Namespace namespace) { 
053        super(name, namespace);
054    }
055
056    
057    
058    // org.w3c.dom.Node interface
059    //-------------------------------------------------------------------------        
060    public String getNamespaceURI() {
061        return getQName().getNamespaceURI();
062    }
063
064    public String getPrefix() {
065        return getQName().getNamespacePrefix();
066    }
067    
068    public void setPrefix(String prefix) throws DOMException {
069        DOMNodeHelper.setPrefix(this, prefix);
070    }
071
072    public String getLocalName() {
073        return getQName().getName();
074    }
075
076    public String getNodeName() {
077        return getName();
078    }
079    
080    //already part of API  
081    //
082    //public short getNodeType();
083    
084
085    
086    public String getNodeValue() throws DOMException {
087        return DOMNodeHelper.getNodeValue(this);
088    }
089    
090    public void setNodeValue(String nodeValue) throws DOMException {
091        DOMNodeHelper.setNodeValue(this, nodeValue);
092    }
093        
094
095    public org.w3c.dom.Node getParentNode() {
096        return DOMNodeHelper.getParentNode(this);
097    }
098    
099    public NodeList getChildNodes() {
100        return DOMNodeHelper.createNodeList( content() );
101    }
102
103    public org.w3c.dom.Node getFirstChild() {
104        return DOMNodeHelper.asDOMNode( node(0) );
105    }
106
107    public org.w3c.dom.Node getLastChild() {
108        return DOMNodeHelper.asDOMNode( node( nodeCount() - 1 ) );
109    }
110
111    public org.w3c.dom.Node getPreviousSibling() {
112        return DOMNodeHelper.getPreviousSibling(this);
113    }
114
115    public org.w3c.dom.Node getNextSibling() {
116        return DOMNodeHelper.getNextSibling(this);
117    }
118
119    public NamedNodeMap getAttributes() {
120        return new DOMAttributeNodeMap( this );
121    }
122    
123    public Document getOwnerDocument() {
124        return DOMNodeHelper.getOwnerDocument(this);
125    }
126
127    public org.w3c.dom.Node insertBefore(
128        org.w3c.dom.Node newChild, 
129        org.w3c.dom.Node refChild
130    ) throws DOMException {
131        return DOMNodeHelper.insertBefore(this, newChild, refChild);
132    }
133
134    public org.w3c.dom.Node replaceChild(
135        org.w3c.dom.Node newChild, 
136        org.w3c.dom.Node oldChild
137    ) throws DOMException {
138        return DOMNodeHelper.replaceChild(this, newChild, oldChild);
139    }
140
141    public org.w3c.dom.Node removeChild(org.w3c.dom.Node oldChild) throws DOMException {
142        return DOMNodeHelper.removeChild(this, oldChild);
143    }
144
145    public org.w3c.dom.Node appendChild(org.w3c.dom.Node newChild) throws DOMException {
146        return DOMNodeHelper.appendChild(this, newChild);
147    }
148
149    public boolean hasChildNodes() {
150        return nodeCount() > 0;
151    }
152
153    public org.w3c.dom.Node cloneNode(boolean deep) {
154        return DOMNodeHelper.cloneNode(this, deep);
155    }
156
157    public boolean isSupported(String feature, String version) {
158        return DOMNodeHelper.isSupported(this, feature, version);
159    }
160
161    public boolean hasAttributes() {
162        return DOMNodeHelper.hasAttributes(this);
163    }
164    
165    
166    // org.w3c.dom.Element interface
167    //-------------------------------------------------------------------------            
168    public String getTagName() {
169        return getName();
170    }
171
172    public String getAttribute(String name) {
173        String answer = attributeValue(name);
174        return (answer != null) ? answer : "";
175    }
176
177    public void setAttribute(String name, String value) throws DOMException {
178        addAttribute(name, value);
179    }
180
181    public void removeAttribute(String name) throws DOMException {
182        Attribute attribute = attribute(name);
183        if ( attribute != null ) {
184            remove(attribute);
185        }
186    }
187
188    public org.w3c.dom.Attr getAttributeNode(String name) {
189        return DOMNodeHelper.asDOMAttr( attribute( name ) );
190    }
191
192    public org.w3c.dom.Attr setAttributeNode(org.w3c.dom.Attr newAttr) throws DOMException {
193        Attribute attribute = attribute(newAttr);
194        if ( attribute != null ) {
195            attribute.setValue( newAttr.getValue() );
196        }
197        else {
198            attribute = createAttribute( newAttr );
199            add( attribute );
200        }
201        return DOMNodeHelper.asDOMAttr( attribute );
202    }
203
204    public org.w3c.dom.Attr removeAttributeNode(org.w3c.dom.Attr oldAttr) throws DOMException {
205        Attribute attribute = attribute(oldAttr);
206        if ( attribute != null ) {
207            attribute.detach();
208            return DOMNodeHelper.asDOMAttr( attribute );
209        }
210        else {
211            throw new DOMException( 
212                DOMException.NOT_FOUND_ERR, 
213                "No such attribute" 
214            );
215        }
216    }
217
218    public String getAttributeNS(String namespaceURI,  String localName) {
219        Attribute attribute = attribute( namespaceURI, localName );
220        if ( attribute != null ) {
221            String answer = attribute.getValue();
222            if ( answer != null ) {
223                return answer;
224            }
225        }
226        return "";
227    }
228
229    public void setAttributeNS(
230        String namespaceURI, 
231        String qualifiedName, 
232        String value
233    ) throws DOMException {
234        Attribute attribute = attribute( namespaceURI, qualifiedName );
235        if ( attribute != null ) {
236            attribute.setValue(value);
237        }
238        else {
239            QName qname = getQName( namespaceURI, qualifiedName );
240            addAttribute( qname, value );
241        }
242    }
243
244    public void removeAttributeNS(
245        String namespaceURI, 
246        String localName
247    ) throws DOMException {
248        Attribute attribute = attribute( namespaceURI, localName );
249        if ( attribute != null ) {
250            remove( attribute );
251        }
252    }
253
254    public org.w3c.dom.Attr getAttributeNodeNS(String namespaceURI,  String localName) {
255        Attribute attribute = attribute( namespaceURI, localName );
256        if ( attribute != null ) {
257            DOMNodeHelper.asDOMAttr( attribute );
258        }
259        return null;
260    }
261
262    public org.w3c.dom.Attr setAttributeNodeNS(org.w3c.dom.Attr newAttr) throws DOMException {
263        Attribute attribute = attribute( 
264            newAttr.getNamespaceURI(), newAttr.getLocalName() 
265        );
266        if ( attribute != null ) {
267            attribute.setValue( newAttr.getValue() );
268        }
269        else {
270            attribute = createAttribute( newAttr );
271            add( attribute );
272        }
273        return DOMNodeHelper.asDOMAttr( attribute );
274    }
275
276    public NodeList getElementsByTagName(String name) {
277        ArrayList list = new ArrayList();
278        DOMNodeHelper.appendElementsByTagName( list, this, name );
279        return DOMNodeHelper.createNodeList( list );
280    }
281    
282    public NodeList getElementsByTagNameNS(
283        String namespaceURI, String localName
284    ) {
285        ArrayList list = new ArrayList();
286        DOMNodeHelper.appendElementsByTagNameNS(list, this, namespaceURI, localName );
287        return DOMNodeHelper.createNodeList( list );
288    }
289
290    public boolean hasAttribute(String name) {
291        return attribute(name) != null;
292    }
293
294    public boolean hasAttributeNS(String namespaceURI, String localName) {
295        return attribute(namespaceURI, localName) != null;
296    }
297
298    
299    // Implementation methods
300    //-------------------------------------------------------------------------            
301    protected DocumentFactory getDocumentFactory() {
302        DocumentFactory factory = getQName().getDocumentFactory();
303        return ( factory != null ) ? factory : DOCUMENT_FACTORY;
304    }
305    
306    protected Attribute attribute(org.w3c.dom.Attr attr) {
307        return attribute( 
308            DOCUMENT_FACTORY.createQName( 
309                attr.getLocalName(), 
310                attr.getPrefix(), 
311                attr.getNamespaceURI() 
312            )
313        );
314    }
315
316    protected Attribute attribute(String namespaceURI,  String localName) {
317        List attributes = attributeList();
318        int size = attributes.size();
319        for ( int i = 0; i < size; i++ ) {
320            Attribute attribute = (Attribute) attributes.get(i);
321            if ( localName.equals( attribute.getName() ) &&
322                namespaceURI.equals( attribute.getNamespaceURI() ) ) {
323                return attribute;
324            }
325        }
326        return null;
327    }
328
329    protected Attribute createAttribute( org.w3c.dom.Attr newAttr ) {
330        QName qname = null;
331        String name = newAttr.getLocalName();
332        String uri = newAttr.getNamespaceURI();
333        if ( uri != null && uri.length() > 0 ) {
334            Namespace namespace = getNamespaceForURI( uri );
335            if ( namespace != null ) {
336                qname = DOCUMENT_FACTORY.createQName( name, namespace );
337            }
338        }
339        if ( qname == null ) {
340            qname = DOCUMENT_FACTORY.createQName( name );
341        }
342        return new DOMAttribute( qname, newAttr.getValue() );
343    }
344    
345    protected QName getQName( String namespaceURI, String qualifiedName ) {
346        int index = qualifiedName.indexOf( ':' );
347        String prefix = "";
348        String localName = qualifiedName;
349        if ( index >= 0 ) {
350            prefix = qualifiedName.substring(0, index);
351            localName = qualifiedName.substring(index+1);
352        }
353        return DOCUMENT_FACTORY.createQName( localName, prefix, namespaceURI );
354    }
355}
356
357
358
359
360/*
361 * Redistribution and use of this software and associated documentation
362 * ("Software"), with or without modification, are permitted provided
363 * that the following conditions are met:
364 *
365 * 1. Redistributions of source code must retain copyright
366 *    statements and notices.  Redistributions must also contain a
367 *    copy of this document.
368 *
369 * 2. Redistributions in binary form must reproduce the
370 *    above copyright notice, this list of conditions and the
371 *    following disclaimer in the documentation and/or other
372 *    materials provided with the distribution.
373 *
374 * 3. The name "DOM4J" must not be used to endorse or promote
375 *    products derived from this Software without prior written
376 *    permission of MetaStuff, Ltd.  For written permission,
377 *    please contact dom4j-info@metastuff.com.
378 *
379 * 4. Products derived from this Software may not be called "DOM4J"
380 *    nor may "DOM4J" appear in their names without prior written
381 *    permission of MetaStuff, Ltd. DOM4J is a registered
382 *    trademark of MetaStuff, Ltd.
383 *
384 * 5. Due credit should be given to the DOM4J Project
385 *    (http://dom4j.org/).
386 *
387 * THIS SOFTWARE IS PROVIDED BY METASTUFF, LTD. AND CONTRIBUTORS
388 * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
389 * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
390 * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
391 * METASTUFF, LTD. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
392 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
393 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
394 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
395 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
396 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
397 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
398 * OF THE POSSIBILITY OF SUCH DAMAGE.
399 *
400 * Copyright 2001 (C) MetaStuff, Ltd. All Rights Reserved.
401 *
402 * $Id: DOMElement.java,v 1.14 2002/02/01 10:13:39 jstrachan Exp $
403 */