KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > xml > xdm > nodes > Element


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.xml.xdm.nodes;
21 import java.io.IOException JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.Map JavaDoc;
26 import javax.xml.XMLConstants JavaDoc;
27 import org.netbeans.modules.xml.spi.dom.NodeListImpl;
28 import org.netbeans.modules.xml.xdm.XDMModel;
29 import org.netbeans.modules.xml.xdm.visitor.FlushVisitor;
30 import org.netbeans.modules.xml.xdm.visitor.Utils;
31 import org.netbeans.modules.xml.xdm.visitor.XMLNodeVisitor;
32 import org.w3c.dom.DOMException JavaDoc;
33 import org.w3c.dom.NamedNodeMap JavaDoc;
34 import org.w3c.dom.NodeList JavaDoc;
35
36 /**
37  * This class represents the XML Element.
38  * An element is of the form <elmName[attributes]/> or <element[attributes]>[TextNode]</elmName>
39  * In terms of tokens attibute can have upto 12 tokens.
40  * Start of start element token, <.
41  * element namespace token, optional.
42  * element namespace seperator, optional.
43  * element name token.
44  * whitespace token, optional.
45  * end of start element token, > or />.
46  * start of end element token, </.
47  * element namespace token, optional.
48  * element namespace seperator, optional.
49  * element name token.
50  * whitespace token, optional.
51  * end of end element token, >.
52  * the end element tokens are optional.
53  * @author Ajit
54  */

55 public class Element extends NodeImpl implements Node, org.w3c.dom.Element JavaDoc {
56     
57     
58     Element() {
59     super();
60     }
61     
62     Element(String JavaDoc tagName) {
63     super();
64     List JavaDoc<Token> tokens = getTokensForWrite();
65     tokens.add(Token.create("<".concat(tagName), TokenType.TOKEN_ELEMENT_START_TAG));
66     tokens.add(Token.create("/>", TokenType.TOKEN_ELEMENT_END_TAG));
67     }
68     
69     public short getNodeType() {
70     return Node.ELEMENT_NODE;
71     }
72     
73     public String JavaDoc getNodeName() {
74     return getTagName();
75     }
76     
77     public void accept(XMLNodeVisitor visitor) {
78     visitor.visit(this);
79     }
80     
81     public String JavaDoc getTagName() {
82     if(tagName == null){
83         for(Token token : getTokens()) {
84         if(token.getType() == TokenType.TOKEN_ELEMENT_START_TAG) {
85             tagName = token.getValue().substring(1);
86             break;
87         }
88         }
89     }
90     return tagName;
91     }
92     
93     public void setTagName(String JavaDoc tagName) {
94     assert tagName!= null && !"".equals(tagName);
95     checkNotInTree();
96     this.tagName = tagName;
97     int tokenIndex = -1;
98     for(Token token : getTokens()) {
99         tokenIndex++;
100         if(token.getType() == TokenType.TOKEN_ELEMENT_START_TAG) {
101         String JavaDoc image;
102         String JavaDoc oldImage = token.getValue();
103         if(oldImage.startsWith("</")) {
104             image = "</".concat(tagName);
105         } else {
106             image = "<".concat(tagName);
107         }
108         Token newToken =
109             Token.create(image,TokenType.TOKEN_ELEMENT_START_TAG);
110         getTokensForWrite().set(tokenIndex,newToken);
111         }
112     }
113     }
114     
115     public String JavaDoc getPrefix() {
116     String JavaDoc qName = getTagName();
117     if(qName != null){
118         int idx = qName.indexOf(':');
119         if(idx >0) return qName.substring(0,idx);
120     }
121     return null;
122     }
123     
124     public void setPrefix(String JavaDoc prefix) {
125     String JavaDoc localName = getLocalName();
126     if(prefix == null || prefix.equals("")) {
127         setTagName(localName);
128     } else {
129         setTagName(prefix.concat(":").concat(localName));
130     }
131     }
132     
133     public String JavaDoc getLocalName() {
134     String JavaDoc qName = getTagName();
135     if(qName != null){
136         int idx = qName.indexOf(':')+1;
137         if(idx >0) return qName.substring(idx);
138     }
139     return qName;
140     }
141     
142     public void setLocalName(String JavaDoc localName) {
143     String JavaDoc prefix = getPrefix();
144     if(prefix == null) {
145         setTagName(localName);
146     } else if(localName == null || localName.equals("")) {
147         setTagName(prefix);
148     } else {
149         setTagName(prefix.concat(":").concat(localName));
150     }
151     }
152     
153     void setTokens(List JavaDoc<Token> newTokens) {
154     tagName = null;
155     super.setTokens(newTokens);
156     }
157     
158     /**
159      * Retrieves an attribute value by name.
160      * @param name The name of the attribute to retrieve.
161      * @return The <code>Attr</code> value as a string, or the empty string
162      * if that attribute does not have a specified or default value.
163      */

164     public String JavaDoc getAttribute(String JavaDoc name) {
165     Attribute attribute = getAttributeNode(name);
166     return attribute!=null?attribute.getValue():null;
167     }
168     
169     /**
170      * Retrieves an attribute node by name.
171      * <br>To retrieve an attribute node by qualified name and namespace URI,
172      * use the <code>getAttributeNodeNS</code> method.
173      * @param name The name (<code>nodeName</code>) of the attribute to
174      * retrieve.
175      * @return The <code>Attr</code> node with the specified name (
176      * <code>nodeName</code>) or <code>null</code> if there is no such
177      * attribute.
178      */

179     public Attribute getAttributeNode(String JavaDoc name) {
180         for(Attribute attr:getAttributesForRead()) {
181             if(name.equals(attr.getName()))
182                 return attr;
183         }
184         return null;
185     }
186     
187     /**
188      * Returns <code>true</code> when an attribute with a given name is
189      * specified on this element or has a default value, <code>false</code>
190      * otherwise.
191      * @param name The name of the attribute to look for.
192      * @return <code>true</code> if an attribute with the given name is
193      * specified on this element or has a default value, <code>false</code>
194      * otherwise.
195      * @since DOM Level 2
196      */

197     public boolean hasAttribute(String JavaDoc name) {
198     return getAttributeNode(name)!=null;
199     }
200     
201     /**
202      * Retrieves an attribute value by local name and namespace URI.
203      * <br>Per [<a HREF='http://www.w3.org/TR/1999/REC-xml-names-19990114/'>XML Namespaces</a>]
204      * , applications must use the value <code>null</code> as the
205      * <code>namespaceURI</code> parameter for methods if they wish to have
206      * no namespace.
207      * @param namespaceURI The namespace URI of the attribute to retrieve.
208      * @param localName The local name of the attribute to retrieve.
209      * @return The <code>Attr</code> value as a string, or the empty string
210      * if that attribute does not have a specified or default value.
211      * @exception DOMException
212      * NOT_SUPPORTED_ERR: May be raised if the implementation does not
213      * support the feature <code>"XML"</code> and the language exposed
214      * through the Document does not support XML Namespaces (such as [<a HREF='http://www.w3.org/TR/1999/REC-html401-19991224/'>HTML 4.01</a>]).
215      * @since DOM Level 2
216      */

217     public String JavaDoc getAttributeNS(String JavaDoc namespaceURI, String JavaDoc localName) {
218     Attribute attribute = getAttributeNodeNS(namespaceURI,localName);
219     return attribute!=null?attribute.getValue():null;
220     }
221     
222     /**
223      * Retrieves an <code>Attr</code> node by local name and namespace URI.
224      * <br>Per [<a HREF='http://www.w3.org/TR/1999/REC-xml-names-19990114/'>XML Namespaces</a>]
225      * , applications must use the value <code>null</code> as the
226      * <code>namespaceURI</code> parameter for methods if they wish to have
227      * no namespace.
228      * @param namespaceURI The namespace URI of the attribute to retrieve.
229      * @param localName The local name of the attribute to retrieve.
230      * @return The <code>Attr</code> node with the specified attribute local
231      * name and namespace URI or <code>null</code> if there is no such
232      * attribute.
233      * @exception DOMException
234      * NOT_SUPPORTED_ERR: May be raised if the implementation does not
235      * support the feature <code>"XML"</code> and the language exposed
236      * through the Document does not support XML Namespaces (such as [<a HREF='http://www.w3.org/TR/1999/REC-html401-19991224/'>HTML 4.01</a>]).
237      * @since DOM Level 2
238      */

239     public Attribute getAttributeNodeNS(String JavaDoc namespaceURI, String JavaDoc localName) {
240     String JavaDoc prefix = lookupPrefix(namespaceURI);
241     String JavaDoc qualifiedName = localName;
242     if (prefix != null && !prefix.equals("")) qualifiedName = prefix+":"+localName;
243     return getAttributeNode(qualifiedName);
244     }
245     
246     /**
247      * Returns <code>true</code> when an attribute with a given local name and
248      * namespace URI is specified on this element or has a default value,
249      * <code>false</code> otherwise.
250      * <br>Per [<a HREF='http://www.w3.org/TR/1999/REC-xml-names-19990114/'>XML Namespaces</a>]
251      * , applications must use the value <code>null</code> as the
252      * <code>namespaceURI</code> parameter for methods if they wish to have
253      * no namespace.
254      * @param namespaceURI The namespace URI of the attribute to look for.
255      * @param localName The local name of the attribute to look for.
256      * @return <code>true</code> if an attribute with the given local name
257      * and namespace URI is specified or has a default value on this
258      * element, <code>false</code> otherwise.
259      * @exception DOMException
260      * NOT_SUPPORTED_ERR: May be raised if the implementation does not
261      * support the feature <code>"XML"</code> and the language exposed
262      * through the Document does not support XML Namespaces (such as [<a HREF='http://www.w3.org/TR/1999/REC-html401-19991224/'>HTML 4.01</a>]).
263      * @since DOM Level 2
264      */

265     public boolean hasAttributeNS(String JavaDoc namespaceURI, String JavaDoc localName) {
266     return getAttributeNodeNS(namespaceURI,localName)!=null;
267     }
268     
269     /**
270      * Adds a new attribute. If an attribute with that name is already present
271      * in the element, its value is changed to be that of the value
272      * parameter. This value is a simple string; it is not parsed as it is
273      * being set. So any markup (such as syntax to be recognized as an
274      * entity reference) is treated as literal text, and needs to be
275      * appropriately escaped by the implementation when it is written out.
276      * In order to assign an attribute value that contains entity
277      * references, the user must create an <code>Attr</code> node plus any
278      * <code>Text</code> and <code>EntityReference</code> nodes, build the
279      * appropriate subtree, and use <code>setAttributeNode</code> to assign
280      * it as the value of an attribute.
281      * <br>To set an attribute with a qualified name and namespace URI, use
282      * the <code>setAttributeNS</code> method.
283      * @param name The name of the attribute to create or alter.
284      * @param value Value to set in string form.
285      * @exception DOMException
286      * INVALID_CHARACTER_ERR: Raised if the specified name is not an XML
287      * name according to the XML version in use specified in the
288      * <code>Document.xmlVersion</code> attribute.
289      * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
290      */

291     public void setAttribute(String JavaDoc name, String JavaDoc value) {
292     checkNotInTree();
293     Attribute oldAttr = getAttributeNode(name);
294     if (oldAttr!=null) {
295         if(!oldAttr.isInTree()) {
296         oldAttr.setValue(value);
297         } else {
298         Attribute newAttr = (Attribute)oldAttr.clone(true,false,false);
299         newAttr.setValue(value);
300         int index = getAttributesForRead().indexOf(oldAttr);
301         getAttributesForWrite().set(index,newAttr);
302         }
303     } else {
304         Attribute attribute = new Attribute(name, value);
305         getAttributesForWrite().add(attribute);
306     }
307     }
308     
309     /**
310      * Adds a new attribute node. If an attribute with that name (
311      * <code>nodeName</code>) is already present in the element, it is
312      * replaced by the new one. Replacing an attribute node by itself has no
313      * effect.
314      * <br>To add a new attribute node with a qualified name and namespace
315      * URI, use the <code>setAttributeNodeNS</code> method.
316      * @param newAttr The <code>Attr</code> node to add to the attribute list.
317      * @return If the <code>newAttr</code> attribute replaces an existing
318      * attribute, the replaced <code>Attr</code> node is returned,
319      * otherwise <code>null</code> is returned.
320      * @exception DOMException
321      * WRONG_DOCUMENT_ERR: Raised if <code>newAttr</code> was created from a
322      * different document than the one that created the element.
323      * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
324      * <br>INUSE_ATTRIBUTE_ERR: Raised if <code>newAttr</code> is already an
325      * attribute of another <code>Element</code> object. The DOM user must
326      * explicitly clone <code>Attr</code> nodes to re-use them in other
327      * elements.
328      */

329     public Attribute setAttributeNode(org.w3c.dom.Attr JavaDoc newAttr) {
330     checkNotInTree();
331     if(newAttr instanceof Attribute) {
332         Attribute attribute = (Attribute)newAttr;
333         Attribute oldAttr = getAttributeNode(newAttr.getName());
334         if (oldAttr==null) {
335         getAttributesForWrite().add(attribute);
336         return attribute;
337         } else {
338         int index = getAttributesForRead().indexOf(oldAttr);
339         return getAttributesForWrite().set(index,attribute);
340         }
341     } else {
342         throw new DOMException JavaDoc(DOMException.TYPE_MISMATCH_ERR,null);
343     }
344     }
345     
346     /**
347      * Removes an attribute by name. If a default value for the removed
348      * attribute is defined in the DTD, a new attribute immediately appears
349      * with the default value as well as the corresponding namespace URI,
350      * local name, and prefix when applicable. The implementation may handle
351      * default values from other schemas similarly but applications should
352      * use <code>Document.normalizeDocument()</code> to guarantee this
353      * information is up-to-date.
354      * <br>If no attribute with this name is found, this method has no effect.
355      * <br>To remove an attribute by local name and namespace URI, use the
356      * <code>removeAttributeNS</code> method.
357      * @param name The name of the attribute to remove.
358      * @exception DOMException
359      * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
360      */

361     public void removeAttribute(String JavaDoc name) {
362     Attribute attribute = getAttributeNode(name);
363     removeAttributeNode(attribute);
364     }
365     
366     /**
367      * Removes the specified attribute node. If a default value for the
368      * removed <code>Attr</code> node is defined in the DTD, a new node
369      * immediately appears with the default value as well as the
370      * corresponding namespace URI, local name, and prefix when applicable.
371      * The implementation may handle default values from other schemas
372      * similarly but applications should use
373      * <code>Document.normalizeDocument()</code> to guarantee this
374      * information is up-to-date.
375      * @param oldAttr The <code>Attr</code> node to remove from the attribute
376      * list.
377      * @return The <code>Attr</code> node that was removed.
378      * @exception DOMException
379      * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
380      * <br>NOT_FOUND_ERR: Raised if <code>oldAttr</code> is not an attribute
381      * of the element.
382      */

383     public Attribute removeAttributeNode(org.w3c.dom.Attr JavaDoc oldAttr) {
384     checkNotInTree();
385     getAttributesForWrite().remove(oldAttr);
386     return (Attribute) oldAttr;
387     }
388     
389     /**
390      * Adds a new attribute. If an attribute with that local name and that
391      * namespace URI is already present in the element, it is replaced by
392      * the new one. Replacing an attribute node by itself has no effect.
393      * <br>Per [<a HREF='http://www.w3.org/TR/1999/REC-xml-names-19990114/'>XML Namespaces</a>]
394      * , applications must use the value <code>null</code> as the
395      * <code>namespaceURI</code> parameter for methods if they wish to have
396      * no namespace.
397      * @param newAttr The <code>Attr</code> node to add to the attribute list.
398      * @return If the <code>newAttr</code> attribute replaces an existing
399      * attribute with the same local name and namespace URI, the replaced
400      * <code>Attr</code> node is returned, otherwise <code>null</code> is
401      * returned.
402      * @exception DOMException
403      * WRONG_DOCUMENT_ERR: Raised if <code>newAttr</code> was created from a
404      * different document than the one that created the element.
405      * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
406      * <br>INUSE_ATTRIBUTE_ERR: Raised if <code>newAttr</code> is already an
407      * attribute of another <code>Element</code> object. The DOM user must
408      * explicitly clone <code>Attr</code> nodes to re-use them in other
409      * elements.
410      * <br>NOT_SUPPORTED_ERR: May be raised if the implementation does not
411      * support the feature <code>"XML"</code> and the language exposed
412      * through the Document does not support XML Namespaces (such as [<a HREF='http://www.w3.org/TR/1999/REC-html401-19991224/'>HTML 4.01</a>]).
413      * @since DOM Level 2
414      */

415     public org.w3c.dom.Attr JavaDoc setAttributeNodeNS(org.w3c.dom.Attr JavaDoc newAttr) {
416     return setAttributeNode(newAttr);
417     }
418     
419     /**
420      * Adds a new attribute. If an attribute with the same local name and
421      * namespace URI is already present on the element, its prefix is
422      * changed to be the prefix part of the <code>qualifiedName</code>, and
423      * its value is changed to be the <code>value</code> parameter. This
424      * value is a simple string; it is not parsed as it is being set. So any
425      * markup (such as syntax to be recognized as an entity reference) is
426      * treated as literal text, and needs to be appropriately escaped by the
427      * implementation when it is written out. In order to assign an
428      * attribute value that contains entity references, the user must create
429      * an <code>Attr</code> node plus any <code>Text</code> and
430      * <code>EntityReference</code> nodes, build the appropriate subtree,
431      * and use <code>setAttributeNodeNS</code> or
432      * <code>setAttributeNode</code> to assign it as the value of an
433      * attribute.
434      * <br>Per [<a HREF='http://www.w3.org/TR/1999/REC-xml-names-19990114/'>XML Namespaces</a>]
435      * , applications must use the value <code>null</code> as the
436      * <code>namespaceURI</code> parameter for methods if they wish to have
437      * no namespace.
438      * @param namespaceURI The namespace URI of the attribute to create or
439      * alter.
440      * @param qualifiedName The qualified name of the attribute to create or
441      * alter.
442      * @param value The value to set in string form.
443      * @exception DOMException
444      * INVALID_CHARACTER_ERR: Raised if the specified qualified name is not
445      * an XML name according to the XML version in use specified in the
446      * <code>Document.xmlVersion</code> attribute.
447      * <br>NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
448      * <br>NAMESPACE_ERR: Raised if the <code>qualifiedName</code> is
449      * malformed per the Namespaces in XML specification, if the
450      * <code>qualifiedName</code> has a prefix and the
451      * <code>namespaceURI</code> is <code>null</code>, if the
452      * <code>qualifiedName</code> has a prefix that is "xml" and the
453      * <code>namespaceURI</code> is different from "<a HREF='http://www.w3.org/XML/1998/namespace'>
454      * http://www.w3.org/XML/1998/namespace</a>", if the <code>qualifiedName</code> or its prefix is "xmlns" and the
455      * <code>namespaceURI</code> is different from "<a HREF='http://www.w3.org/2000/xmlns/'>http://www.w3.org/2000/xmlns/</a>", or if the <code>namespaceURI</code> is "<a HREF='http://www.w3.org/2000/xmlns/'>http://www.w3.org/2000/xmlns/</a>" and neither the <code>qualifiedName</code> nor its prefix is "xmlns".
456      * <br>NOT_SUPPORTED_ERR: May be raised if the implementation does not
457      * support the feature <code>"XML"</code> and the language exposed
458      * through the Document does not support XML Namespaces (such as [<a HREF='http://www.w3.org/TR/1999/REC-html401-19991224/'>HTML 4.01</a>]).
459      * @since DOM Level 2
460      */

461     public void setAttributeNS(String JavaDoc namespaceURI, String JavaDoc qualifiedName, String JavaDoc value) {
462     //TODO Implement later
463
checkNotInTree();
464     Attribute oldAttr = getAttributeNodeNS(namespaceURI, qualifiedName);
465     if (oldAttr!=null) {
466         if(!oldAttr.isInTree()) {
467         oldAttr.setValue(value);
468         } else {
469         Attribute newAttr = (Attribute)oldAttr.clone(true,false,false);
470         newAttr.setValue(value);
471         int index = getAttributesForRead().indexOf(oldAttr);
472         getAttributesForWrite().set(index,newAttr);
473         }
474     } else {
475         String JavaDoc prefix = lookupPrefix(namespaceURI);
476         String JavaDoc name = qualifiedName;
477         if (prefix != null && !prefix.equals("")) name = prefix + ":" + qualifiedName;
478         Attribute attribute = new Attribute(name, value);
479         getAttributesForWrite().add(attribute);
480     }
481     }
482     
483     /**
484      * Removes an attribute by local name and namespace URI. If a default
485      * value for the removed attribute is defined in the DTD, a new
486      * attribute immediately appears with the default value as well as the
487      * corresponding namespace URI, local name, and prefix when applicable.
488      * The implementation may handle default values from other schemas
489      * similarly but applications should use
490      * <code>Document.normalizeDocument()</code> to guarantee this
491      * information is up-to-date.
492      * <br>If no attribute with this local name and namespace URI is found,
493      * this method has no effect.
494      * <br>Per [<a HREF='http://www.w3.org/TR/1999/REC-xml-names-19990114/'>XML Namespaces</a>]
495      * , applications must use the value <code>null</code> as the
496      * <code>namespaceURI</code> parameter for methods if they wish to have
497      * no namespace.
498      * @param namespaceURI The namespace URI of the attribute to remove.
499      * @param localName The local name of the attribute to remove.
500      * @exception DOMException
501      * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
502      * <br>NOT_SUPPORTED_ERR: May be raised if the implementation does not
503      * support the feature <code>"XML"</code> and the language exposed
504      * through the Document does not support XML Namespaces (such as [<a HREF='http://www.w3.org/TR/1999/REC-html401-19991224/'>HTML 4.01</a>]).
505      * @since DOM Level 2
506      */

507     public void removeAttributeNS(String JavaDoc namespaceURI, String JavaDoc localName) {
508     removeAttributeNode(getAttributeNodeNS(namespaceURI, localName));
509     }
510     
511     /**
512      * Returns a <code>NodeList</code> of all descendant <code>Elements</code>
513      * with a given tag name, in document order.
514      * @param name The name of the tag to match on. The special value "*"
515      * matches all tags.
516      * @return A list of matching <code>Element</code> nodes.
517      */

518     public org.w3c.dom.NodeList JavaDoc getElementsByTagName(String JavaDoc name) {
519     NodeList JavaDoc nl = getChildNodes();
520     List JavaDoc<Element> l = new ArrayList JavaDoc<Element>(nl.getLength());
521     boolean matchesAll = "*".equals(name); // NOI18N
522
for (int i = 0; i < nl.getLength(); i++) {
523         org.w3c.dom.Node JavaDoc n = nl.item(i);
524         boolean matchesValue =
525         n instanceof Element &&
526         (matchesAll || n.getNodeName().equals(name));
527         if (matchesValue) {
528         l.add((Element)n);
529         }
530     }
531     return new NodeListImpl(l);
532     }
533     
534     /**
535      * Returns a <code>NodeList</code> of all the descendant
536      * <code>Elements</code> with a given local name and namespace URI in
537      * document order.
538      * @param namespaceURI The namespace URI of the elements to match on. The
539      * special value "*" matches all namespaces.
540      * @param localName The local name of the elements to match on. The
541      * special value "*" matches all local names.
542      * @return A new <code>NodeList</code> object containing all the matched
543      * <code>Elements</code>.
544      * @exception DOMException
545      * NOT_SUPPORTED_ERR: May be raised if the implementation does not
546      * support the feature <code>"XML"</code> and the language exposed
547      * through the Document does not support XML Namespaces (such as [<a HREF='http://www.w3.org/TR/1999/REC-html401-19991224/'>HTML 4.01</a>]).
548      * @since DOM Level 2
549      */

550     public org.w3c.dom.NodeList JavaDoc getElementsByTagNameNS(String JavaDoc namespaceURI, String JavaDoc localName) {
551     //TODO Implement later
552
return null;
553     }
554     
555     /**
556      * If the parameter <code>isId</code> is <code>true</code>, this method
557      * declares the specified attribute to be a user-determined ID attribute
558      * . This affects the value of <code>Attr.isId</code> and the behavior
559      * of <code>Document.getElementById</code>, but does not change any
560      * schema that may be in use, in particular this does not affect the
561      * <code>Attr.schemaTypeInfo</code> of the specified <code>Attr</code>
562      * node. Use the value <code>false</code> for the parameter
563      * <code>isId</code> to undeclare an attribute for being a
564      * user-determined ID attribute.
565      * @param idAttr The attribute node.
566      * @param isId Whether the attribute is a of type ID.
567      * @exception DOMException
568      * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
569      * <br>NOT_FOUND_ERR: Raised if the specified node is not an attribute
570      * of this element.
571      * @since DOM Level 3
572      */

573     public void setIdAttributeNode(org.w3c.dom.Attr JavaDoc idAttr, boolean isId) {
574     //TODO Implement later
575
}
576     
577     /**
578      * If the parameter <code>isId</code> is <code>true</code>, this method
579      * declares the specified attribute to be a user-determined ID attribute
580      * . This affects the value of <code>Attr.isId</code> and the behavior
581      * of <code>Document.getElementById</code>, but does not change any
582      * schema that may be in use, in particular this does not affect the
583      * <code>Attr.schemaTypeInfo</code> of the specified <code>Attr</code>
584      * node. Use the value <code>false</code> for the parameter
585      * <code>isId</code> to undeclare an attribute for being a
586      * user-determined ID attribute.
587      * <br> To specify an attribute by local name and namespace URI, use the
588      * <code>setIdAttributeNS</code> method.
589      * @param name The name of the attribute.
590      * @param isId Whether the attribute is a of type ID.
591      * @exception DOMException
592      * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
593      * <br>NOT_FOUND_ERR: Raised if the specified node is not an attribute
594      * of this element.
595      * @since DOM Level 3
596      */

597     public void setIdAttribute(String JavaDoc name, boolean isId) {
598     //TODO Implement later
599
}
600     
601     /**
602      * If the parameter <code>isId</code> is <code>true</code>, this method
603      * declares the specified attribute to be a user-determined ID attribute
604      * . This affects the value of <code>Attr.isId</code> and the behavior
605      * of <code>Document.getElementById</code>, but does not change any
606      * schema that may be in use, in particular this does not affect the
607      * <code>Attr.schemaTypeInfo</code> of the specified <code>Attr</code>
608      * node. Use the value <code>false</code> for the parameter
609      * <code>isId</code> to undeclare an attribute for being a
610      * user-determined ID attribute.
611      * @param namespaceURI The namespace URI of the attribute.
612      * @param localName The local name of the attribute.
613      * @param isId Whether the attribute is a of type ID.
614      * @exception DOMException
615      * NO_MODIFICATION_ALLOWED_ERR: Raised if this node is readonly.
616      * <br>NOT_FOUND_ERR: Raised if the specified node is not an attribute
617      * of this element.
618      * @since DOM Level 3
619      */

620     public void setIdAttributeNS(String JavaDoc namespaceURI, String JavaDoc localName, boolean isId) {
621     //TODO Implement later
622
}
623     
624     /**
625      * The type information associated with this element.
626      * @since DOM Level 3
627      */

628     public org.w3c.dom.TypeInfo JavaDoc getSchemaTypeInfo() {
629     //TODO Implement later
630
return null;
631     }
632     
633     /**
634      * This api replaces old attribute of this element with new attribute.
635      * This api is provided for XDMModel purposes only.
636      * @param newAttr The new attribute.
637      * @param oldAttr The old attribute to replace.
638      * @throws IllegalStateException if a newAttr has already been added to a tree.
639      */

640     public void replaceAttribute(Attribute newAttr, Attribute oldAttr) {
641     checkNotInTree();
642     List JavaDoc<Attribute> attributes = getAttributesForRead();
643     int index = attributes.indexOf(oldAttr);
644     assert newAttr != null && index>-1;
645     newAttr.checkNotInTree();
646     getAttributesForWrite().set(attributes.indexOf(oldAttr),newAttr);
647     }
648     
649     /**
650      * This api adds new attribute at a given index.
651      * This api is provided for XDMModel purposes only.
652      * @param newAttr The new attribute to be added.
653      * @param index The index at which attribute to be added
654      * @throws IndexOutOfBoundsException if the index is out of range (index < 0 || index > size()).
655      * @throws IllegalStateException if a newAttr has already been added to a tree.
656      */

657     public void addAttribute(Attribute newAttr, int index) {
658     checkNotInTree();
659     assert newAttr != null;
660     newAttr.checkNotInTree();
661     getAttributesForWrite().add(index,newAttr);
662     }
663
664     /**
665      * Moves attribute to the given index.
666      * This api is provided for XDMModel purposes only.
667      * @param attr The new attribute to be moved.
668      * @param index The index at which attribute to be moved
669      * @throws IndexOutOfBoundsException if the index is out of range (index < 0 || index > size()).
670      * @throws IllegalStateException if a attr has not already been added to a tree.
671      */

672     public void reorderAttribute(Attribute attr, int index) {
673         checkNotInTree();
674         if (! attr.isInTree()) {
675             throw new IllegalArgumentException JavaDoc("Node is not in tree");
676         }
677         if (! getAttributesForWrite().remove(attr)) {
678             throw new IllegalArgumentException JavaDoc("Node is not in children");
679         }
680         getAttributesForWrite().add(index, attr);
681     }
682     
683     /**
684      * Rearranges attribute list to the given permutaion.
685      * @param permutation integer array with index represents current index and
686      * value is final index after reordered.
687      */

688     public void reorderAttribute(int[] permutation) {
689         checkNotInTree();
690
691         List JavaDoc<Attribute> attrs = new ArrayList JavaDoc<Attribute>(getAttributesForRead());
692         if (permutation.length != attrs.size()) {
693             throw new IllegalArgumentException JavaDoc(
694                 "Permutation length: "+permutation.length+" " +
695                 "is different than children size: "+attrs.size());
696         }
697         
698         for (int i = 0; i < attrs.size(); i++ ) {
699             Attribute child = attrs.get(i);
700             getAttributesForWrite().set(permutation[i], child);
701         }
702     }
703
704     /**
705      * This api adds new attribute at the end.
706      * This api is provided for XDMModel purposes only.
707      * @param newAttr The new attribute to be added.
708      * @throws IllegalStateException if a newAttr has already been added to a tree.
709      */

710     public void appendAttribute(Attribute newAttr) {
711     checkNotInTree();
712     assert newAttr != null;
713     newAttr.checkNotInTree();
714     getAttributesForWrite().add(newAttr);
715     }
716     
717     public Node appendChild(org.w3c.dom.Node JavaDoc node) {
718         boolean consolidateNamespace =
719                 (getModel() == null || getModel().getStatus() != XDMModel.Status.PARSING);
720         return appendChild(node, consolidateNamespace);
721     }
722     
723     public Node appendChild(org.w3c.dom.Node JavaDoc node, boolean consolidateNamespaces) {
724     boolean selfClosingElement =
725         getChildNodes().getLength() == 0 &&
726         isStartTagSelfClosing();
727     
728     Node n = super.appendChild(node);
729     if (selfClosingElement) {
730         Token endToken = getEndToken();
731         assert endToken != null;
732         
733         List JavaDoc<Token> tokens = getTokensForWrite();
734         
735         // remove / from end tag
736
int endPosition = tokens.indexOf(endToken);
737         assert endPosition != -1;
738         tokens.set(endPosition,
739         Token.create(">",TokenType.TOKEN_ELEMENT_END_TAG));
740         
741         tokens.add(Token.create("</"+getTagName(),
742         TokenType.TOKEN_ELEMENT_START_TAG));
743         tokens.add(Token.create(">",TokenType.TOKEN_ELEMENT_END_TAG));
744     }
745         if (n instanceof Element && consolidateNamespaces) {
746             consolidateNamespaces((Element)n);
747         }
748     return n;
749     }
750
751     public Node insertBefore(org.w3c.dom.Node JavaDoc newChild, org.w3c.dom.Node JavaDoc refChild) throws DOMException JavaDoc {
752         Node n = super.insertBefore(newChild, refChild);
753         if (n instanceof Element) {
754             if (getModel() == null || getModel().getStatus() != XDMModel.Status.PARSING) {
755                 consolidateNamespaces((Element)n);
756             }
757         }
758         return n;
759     }
760     
761     private Token getEndToken() {
762     Token endToken = null;
763     for (Token t: getTokens()) {
764         if (t.getType().equals(TokenType.TOKEN_ELEMENT_END_TAG)) {
765         endToken = t;
766         break;
767         }
768     }
769     return endToken;
770     }
771     
772     private boolean isStartTagSelfClosing() {
773     boolean selfClosing = false;
774     for (Token t: getTokens()) {
775         if (t.getType().equals(TokenType.TOKEN_ELEMENT_END_TAG)) {
776         selfClosing = t.getValue().equals(
777             Token.create("/>",TokenType.TOKEN_ELEMENT_END_TAG)
778             .getValue());
779         }
780     }
781     return selfClosing;
782     }
783     
784     public String JavaDoc getXmlFragmentText() {
785         return new FlushVisitor().flush(getChildNodes());
786     }
787     
788     public void setXmlFragmentText(String JavaDoc text) throws IOException JavaDoc {
789         while(hasChildNodes()) {
790             removeChild(getFirstChild());
791         }
792         NodeList JavaDoc children = Utils.parseFragment(text);
793         for (int i=0; i<children.getLength(); i++) {
794             appendChild(children.item(i));
795         }
796     }
797     
798     /**
799      * If child element is same namespace, should use same prefix
800      */

801     private void consolidateNamespaces(Element newChild) {
802         if (getModel() != null) return;
803         
804         // use parent's prefixes
805
String JavaDoc parentNamespace = getNamespaceURI();
806         if (parentNamespace != null && parentNamespace.equals(newChild.getNamespaceURI())) {
807             newChild.setPrefix(getPrefix());
808         }
809         
810         //consolidate attribute prefixes and qname values
811
List JavaDoc attributes = newChild.getAttributesForRead();
812         ArrayList JavaDoc<String JavaDoc> sparedPrefixes = new ArrayList JavaDoc<String JavaDoc>();
813         for (int i=0; i<attributes.size(); i++) {
814             Attribute attr = (Attribute) attributes.get(i);
815             // skip namsspace declaration attributes
816
if (attr.isXmlnsAttribute()) {
817                 continue;
818             }
819             // check on attribute prefix
820
String JavaDoc prefix = attr.getPrefix();
821             if (prefix != null) {
822                 String JavaDoc namespace = newChild.lookupNamespaceURI(prefix);
823                 if (namespace == null) { // undeclared prefix
824
continue;
825                 }
826                 String JavaDoc newPrefix = lookupPrefix(namespace);
827                 if (newPrefix == null || newPrefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) {
828                     sparedPrefixes.add(prefix);
829                 } else if (! newPrefix.equals(prefix)) {
830                     // new prefix points to different namespace
831
if (newChild.lookupNamespaceURI(newPrefix) != null) {
832                         sparedPrefixes.add(prefix);
833                     } else {
834                         attr.setPrefix(newPrefix);
835                     }
836                 }
837             }
838             
839             // check on attribute value
840
String JavaDoc value = attr.getValue().trim();
841             String JavaDoc[] parts = value.split(":"); //NOI18N
842
if (parts.length > 1) {
843                 // conservatively add to list prefixes to be spared from consolidation
844
// will be take cared of by other consolidation when added to tree
845
sparedPrefixes.add(parts[0]);
846             }
847         }
848
849         //let child prefixe declarations consolidate to parent prefixes
850
for (int i=0; i<attributes.size(); i++) {
851             Attribute attr = (Attribute) attributes.get(i);
852             if (! attr.isXmlnsAttribute()) continue;
853             
854             String JavaDoc prefix = attr.getLocalName();
855             if (sparedPrefixes.contains(prefix)) {
856                 continue;
857             }
858             
859             if (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix)) {
860                 prefix = XMLConstants.DEFAULT_NS_PREFIX;
861             }
862             String JavaDoc namespace = attr.getValue();
863             assert namespace != null;
864             
865             String JavaDoc existingNS = lookupNamespaceURI(prefix);
866             String JavaDoc existingPrefix = lookupPrefix(namespace);
867             
868             // 1. prefix is free (existingNS == null) and namespace is never declared (existingPrefix == null)
869
// 2. prefix is used and for the same namespace
870
// 3. namespace is declared by different prefix
871
// 4. prefix is used and for different namespace
872

873             if (existingNS == null && existingPrefix == null) { // case 1.
874
newChild.removeAttributeNode(attr);
875                 appendAttribute(attr);
876             } else if (namespace.equals(existingNS) && prefix.equals(existingPrefix)) { // case 2
877
// this assume new node has namespaces only at top level
878
newChild.removeAttributeNode(attr);
879             } else if (existingPrefix != null) { // case 3.
880
// this assume we took care of attribute refactoring before enter this loop
881
newChild.removeAttributeNode(attr); //
882
} else {
883                // case 4 do nothing, i.e., leave prefix as overriding with different namespace
884
}
885         }
886     }
887     
888     public Element cloneNode(boolean deep, boolean cloneNamespacePrefix) {
889         Document root = isInTree() ? (Document) getOwnerDocument() : null;
890         Map JavaDoc<Integer JavaDoc,String JavaDoc> allNamespaces = null;
891         if (root != null && cloneNamespacePrefix) {
892             allNamespaces = root.getNamespaceMap();
893         }
894         Map JavaDoc<String JavaDoc,String JavaDoc> clonePrefixes = new HashMap JavaDoc<String JavaDoc,String JavaDoc>();
895         Element clone = (Element) super.cloneNode(deep, allNamespaces, clonePrefixes);
896         for (Map.Entry JavaDoc e : clonePrefixes.entrySet()) {
897             String JavaDoc prefix = (String JavaDoc) e.getKey();
898             String JavaDoc attr = prefix.length() > 0 ?
899                 XMLConstants.XMLNS_ATTRIBUTE+":"+prefix :
900                 XMLConstants.XMLNS_ATTRIBUTE;
901             Attribute attrNode = new Attribute(attr, (String JavaDoc) e.getValue());
902             clone.setAttributeNode(attrNode);
903         }
904         return clone;
905     }
906     
907     protected void cloneNamespacePrefix(Map JavaDoc<Integer JavaDoc,String JavaDoc> allNS, Map JavaDoc<String JavaDoc,String JavaDoc> prefixes) {
908         if (allNS == null) return;
909
910         String JavaDoc namespace = allNS.get(getId());
911         if (namespace == null) return;
912         
913         String JavaDoc prefix = getPrefix();
914         if (prefix == null && getAttribute(XMLConstants.XMLNS_ATTRIBUTE) != null) {
915             prefix = XMLConstants.DEFAULT_NS_PREFIX;
916         }
917         if (prefix != null) {
918             prefixes.put(prefix, namespace);
919         }
920     }
921     
922     private String JavaDoc tagName = null;
923 }
924
Popular Tags