KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > dom > ElementImpl


1 /*
2  * Copyright 1999-2002,2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.xerces.dom;
18
19 import org.w3c.dom.Attr JavaDoc;
20 import org.w3c.dom.DOMException JavaDoc;
21 import org.w3c.dom.Element JavaDoc;
22 import org.w3c.dom.NamedNodeMap JavaDoc;
23 import org.w3c.dom.Node JavaDoc;
24 import org.w3c.dom.NodeList JavaDoc;
25 import org.w3c.dom.Text JavaDoc;
26
27 import org.w3c.dom.TypeInfo JavaDoc;
28 import org.apache.xerces.util.URI;
29
30 /**
31  * Elements represent most of the "markup" and structure of the
32  * document. They contain both the data for the element itself
33  * (element name and attributes), and any contained nodes, including
34  * document text (as children).
35  * <P>
36  * Elements may have Attributes associated with them; the API for this is
37  * defined in Node, but the function is implemented here. In general, XML
38  * applications should retrive Attributes as Nodes, since they may contain
39  * entity references and hence be a fairly complex sub-tree. HTML users will
40  * be dealing with simple string values, and convenience methods are provided
41  * to work in terms of Strings.
42  * <P>
43  * ElementImpl does not support Namespaces. ElementNSImpl, which inherits from
44  * it, does.
45  * @see ElementNSImpl
46  *
47  * @xerces.internal
48  *
49  * @author Arnaud Le Hors, IBM
50  * @author Joe Kesselman, IBM
51  * @author Andy Clark, IBM
52  * @author Ralf Pfeiffer, IBM
53  * @version $Id: ElementImpl.java,v 1.71 2005/06/21 14:06:57 nddelima Exp $
54  * @since PR-DOM-Level-1-19980818.
55  */

56 public class ElementImpl
57     extends ParentNode
58     implements Element JavaDoc, TypeInfo JavaDoc {
59
60     //
61
// Constants
62
//
63

64     /** Serialization version. */
65     static final long serialVersionUID = 3717253516652722278L;
66     //
67
// Data
68
//
69

70     /** Element name. */
71     protected String JavaDoc name;
72
73     /** Attributes. */
74     protected AttributeMap attributes;
75
76     //
77
// Constructors
78
//
79

80     /** Factory constructor. */
81     public ElementImpl(CoreDocumentImpl ownerDoc, String JavaDoc name) {
82         super(ownerDoc);
83         this.name = name;
84         needsSyncData(true); // synchronizeData will initialize attributes
85
}
86
87     // for ElementNSImpl
88
protected ElementImpl() {}
89
90     // Support for DOM Level 3 renameNode method.
91
// Note: This only deals with part of the pb. CoreDocumentImpl
92
// does all the work.
93
void rename(String JavaDoc name) {
94         if (needsSyncData()) {
95             synchronizeData();
96         }
97         this.name = name;
98         reconcileDefaultAttributes();
99     }
100
101     //
102
// Node methods
103
//
104

105
106     /**
107      * A short integer indicating what type of node this is. The named
108      * constants for this value are defined in the org.w3c.dom.Node interface.
109      */

110     public short getNodeType() {
111         return Node.ELEMENT_NODE;
112     }
113
114     /**
115      * Returns the element name
116      */

117     public String JavaDoc getNodeName() {
118         if (needsSyncData()) {
119             synchronizeData();
120         }
121         return name;
122     }
123
124     /**
125      * Retrieve all the Attributes as a set. Note that this API is inherited
126      * from Node rather than specified on Element; in fact only Elements will
127      * ever have Attributes, but they want to allow folks to "blindly" operate
128      * on the tree as a set of Nodes.
129      */

130     public NamedNodeMap JavaDoc getAttributes() {
131
132         if (needsSyncData()) {
133             synchronizeData();
134         }
135         if (attributes == null) {
136             attributes = new AttributeMap(this, null);
137         }
138         return attributes;
139
140     } // getAttributes():NamedNodeMap
141

142     /**
143      * Return a duplicate copy of this Element. Note that its children
144      * will not be copied unless the "deep" flag is true, but Attributes
145      * are <i>always</i> replicated.
146      *
147      * @see org.w3c.dom.Node#cloneNode(boolean)
148      */

149     public Node JavaDoc cloneNode(boolean deep) {
150
151         ElementImpl newnode = (ElementImpl) super.cloneNode(deep);
152         // Replicate NamedNodeMap rather than sharing it.
153
if (attributes != null) {
154             newnode.attributes = (AttributeMap) attributes.cloneMap(newnode);
155         }
156         return newnode;
157
158     } // cloneNode(boolean):Node
159

160    /**
161      * DOM Level 3 WD - Experimental.
162      * Retrieve baseURI
163      */

164     public String JavaDoc getBaseURI() {
165
166         if (needsSyncData()) {
167             synchronizeData();
168         }
169         // Absolute base URI is computed according to
170
// XML Base (http://www.w3.org/TR/xmlbase/#granularity)
171
// 1. The base URI specified by an xml:base attribute on the element,
172
// if one exists
173
if (attributes != null) {
174             Attr JavaDoc attrNode = (Attr JavaDoc)attributes.getNamedItem("xml:base");
175             if (attrNode != null) {
176                 String JavaDoc uri = attrNode.getNodeValue();
177                 if (uri.length() != 0 ) {// attribute value is always empty string
178
try {
179                        uri = new URI(uri).toString();
180                     }
181                     catch (org.apache.xerces.util.URI.MalformedURIException e) {
182                         // This may be a relative URI.
183

184                         // Make any parentURI into a URI object to use with the URI(URI, String) constructor
185
String JavaDoc parentBaseURI = (this.ownerNode != null) ? this.ownerNode.getBaseURI() : null;
186                         if (parentBaseURI != null){
187                             try{
188                                 uri = new URI(new URI(parentBaseURI), uri).toString();
189                             }
190                             catch (org.apache.xerces.util.URI.MalformedURIException ex){
191                                 // This should never happen: parent should have checked the URI and returned null if invalid.
192
return null;
193                             }
194                             return uri;
195                         }
196                         return null;
197                     }
198                     return uri;
199                 }
200             }
201         }
202
203         // 2.the base URI of the element's parent element within the
204
// document or external entity, if one exists
205
// 3. the base URI of the document entity or external entity
206
// containing the element
207

208         // ownerNode serves as a parent or as document
209
String JavaDoc baseURI = (this.ownerNode != null) ? this.ownerNode.getBaseURI() : null ;
210         //base URI of parent element is not null
211
if(baseURI != null){
212             try {
213                 //return valid absolute base URI
214
return new URI(baseURI).toString();
215             }
216             catch (org.apache.xerces.util.URI.MalformedURIException e){
217                 return null;
218             }
219         }
220         return null;
221     } //getBaseURI
222

223
224
225     /**
226      * NON-DOM
227      * set the ownerDocument of this node, its children, and its attributes
228      */

229     void setOwnerDocument(CoreDocumentImpl doc) {
230     super.setOwnerDocument(doc);
231         if (attributes != null) {
232             attributes.setOwnerDocument(doc);
233         }
234     }
235
236     //
237
// Element methods
238
//
239

240     /**
241      * Look up a single Attribute by name. Returns the Attribute's
242      * string value, or an empty string (NOT null!) to indicate that the
243      * name did not map to a currently defined attribute.
244      * <p>
245      * Note: Attributes may contain complex node trees. This method
246      * returns the "flattened" string obtained from Attribute.getValue().
247      * If you need the structure information, see getAttributeNode().
248      */

249     public String JavaDoc getAttribute(String JavaDoc name) {
250
251         if (needsSyncData()) {
252             synchronizeData();
253         }
254         if (attributes == null) {
255             return "";
256         }
257         Attr JavaDoc attr = (Attr JavaDoc)(attributes.getNamedItem(name));
258         return (attr == null) ? "" : attr.getValue();
259
260     } // getAttribute(String):String
261

262
263     /**
264      * Look up a single Attribute by name. Returns the Attribute Node,
265      * so its complete child tree is available. This could be important in
266      * XML, where the string rendering may not be sufficient information.
267      * <p>
268      * If no matching attribute is available, returns null.
269      */

270     public Attr JavaDoc getAttributeNode(String JavaDoc name) {
271
272         if (needsSyncData()) {
273             synchronizeData();
274         }
275         if (attributes == null) {
276             return null;
277         }
278         return (Attr JavaDoc)attributes.getNamedItem(name);
279
280     } // getAttributeNode(String):Attr
281

282
283     /**
284      * Returns a NodeList of all descendent nodes (children,
285      * grandchildren, and so on) which are Elements and which have the
286      * specified tag name.
287      * <p>
288      * Note: NodeList is a "live" view of the DOM. Its contents will
289      * change as the DOM changes, and alterations made to the NodeList
290      * will be reflected in the DOM.
291      *
292      * @param tagname The type of element to gather. To obtain a list of
293      * all elements no matter what their names, use the wild-card tag
294      * name "*".
295      *
296      * @see DeepNodeListImpl
297      */

298     public NodeList JavaDoc getElementsByTagName(String JavaDoc tagname) {
299         return new DeepNodeListImpl(this,tagname);
300     }
301
302     /**
303      * Returns the name of the Element. Note that Element.nodeName() is
304      * defined to also return the tag name.
305      * <p>
306      * This is case-preserving in XML. HTML should uppercasify it on the
307      * way in.
308      */

309     public String JavaDoc getTagName() {
310         if (needsSyncData()) {
311             synchronizeData();
312         }
313         return name;
314     }
315
316     /**
317      * In "normal form" (as read from a source file), there will never be two
318      * Text children in succession. But DOM users may create successive Text
319      * nodes in the course of manipulating the document. Normalize walks the
320      * sub-tree and merges adjacent Texts, as if the DOM had been written out
321      * and read back in again. This simplifies implementation of higher-level
322      * functions that may want to assume that the document is in standard form.
323      * <p>
324      * To normalize a Document, normalize its top-level Element child.
325      * <p>
326      * As of PR-DOM-Level-1-19980818, CDATA -- despite being a subclass of
327      * Text -- is considered "markup" and will _not_ be merged either with
328      * normal Text or with other CDATASections.
329      */

330     public void normalize() {
331         // No need to normalize if already normalized.
332
if (isNormalized()) {
333             return;
334         }
335         if (needsSyncChildren()) {
336             synchronizeChildren();
337         }
338         ChildNode kid, next;
339         for (kid = firstChild; kid != null; kid = next) {
340             next = kid.nextSibling;
341
342             // If kid is a text node, we need to check for one of two
343
// conditions:
344
// 1) There is an adjacent text node
345
// 2) There is no adjacent text node, but kid is
346
// an empty text node.
347
if ( kid.getNodeType() == Node.TEXT_NODE )
348             {
349                 // If an adjacent text node, merge it with kid
350
if ( next!=null && next.getNodeType() == Node.TEXT_NODE )
351                 {
352                     ((Text JavaDoc)kid).appendData(next.getNodeValue());
353                     removeChild( next );
354                     next = kid; // Don't advance; there might be another.
355
}
356                 else
357                 {
358                     // If kid is empty, remove it
359
if ( kid.getNodeValue() == null || kid.getNodeValue().length() == 0 ) {
360                         removeChild( kid );
361                     }
362                 }
363             }
364
365             // Otherwise it might be an Element, which is handled recursively
366
else if (kid.getNodeType() == Node.ELEMENT_NODE) {
367                 kid.normalize();
368             }
369         }
370
371         // We must also normalize all of the attributes
372
if ( attributes!=null )
373         {
374             for( int i=0; i<attributes.getLength(); ++i )
375             {
376                 Node JavaDoc attr = attributes.item(i);
377                 attr.normalize();
378             }
379         }
380
381         // changed() will have occurred when the removeChild() was done,
382
// so does not have to be reissued.
383

384         isNormalized(true);
385     } // normalize()
386

387     /**
388      * Remove the named attribute from this Element. If the removed
389      * Attribute has a default value, it is immediately replaced thereby.
390      * <P>
391      * The default logic is actually implemented in NamedNodeMapImpl.
392      * PR-DOM-Level-1-19980818 doesn't fully address the DTD, so some
393      * of this behavior is likely to change in future versions. ?????
394      * <P>
395      * Note that this call "succeeds" even if no attribute by this name
396      * existed -- unlike removeAttributeNode, which will throw a not-found
397      * exception in that case.
398      *
399      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if the node is
400      * readonly.
401      */

402     public void removeAttribute(String JavaDoc name) {
403
404         if (ownerDocument.errorChecking && isReadOnly()) {
405             String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
406             throw new DOMException JavaDoc(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
407         }
408
409         if (needsSyncData()) {
410             synchronizeData();
411         }
412
413         if (attributes == null) {
414             return;
415         }
416
417         attributes.safeRemoveNamedItem(name);
418
419     } // removeAttribute(String)
420

421
422     /**
423      * Remove the specified attribute/value pair. If the removed
424      * Attribute has a default value, it is immediately replaced.
425      * <p>
426      * NOTE: Specifically removes THIS NODE -- not the node with this
427      * name, nor the node with these contents. If the specific Attribute
428      * object passed in is not stored in this Element, we throw a
429      * DOMException. If you really want to remove an attribute by name,
430      * use removeAttribute().
431      *
432      * @return the Attribute object that was removed.
433      * @throws DOMException(NOT_FOUND_ERR) if oldattr is not an attribute of
434      * this Element.
435      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if the node is
436      * readonly.
437      */

438     public Attr JavaDoc removeAttributeNode(Attr JavaDoc oldAttr)
439         throws DOMException JavaDoc {
440
441         if (ownerDocument.errorChecking && isReadOnly()) {
442             String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
443             throw new DOMException JavaDoc(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
444         }
445
446         if (needsSyncData()) {
447             synchronizeData();
448         }
449
450         if (attributes == null) {
451             String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
452             throw new DOMException JavaDoc(DOMException.NOT_FOUND_ERR, msg);
453         }
454         return (Attr JavaDoc) attributes.removeItem(oldAttr, true);
455
456     } // removeAttributeNode(Attr):Attr
457

458
459     /**
460      * Add a new name/value pair, or replace the value of the existing
461      * attribute having that name.
462      *
463      * Note: this method supports only the simplest kind of Attribute,
464      * one whose value is a string contained in a single Text node.
465      * If you want to assert a more complex value (which XML permits,
466      * though HTML doesn't), see setAttributeNode().
467      *
468      * The attribute is created with specified=true, meaning it's an
469      * explicit value rather than inherited from the DTD as a default.
470      * Again, setAttributeNode can be used to achieve other results.
471      *
472      * @throws DOMException(INVALID_NAME_ERR) if the name is not acceptable.
473      * (Attribute factory will do that test for us.)
474      *
475      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if the node is
476      * readonly.
477      */

478     public void setAttribute(String JavaDoc name, String JavaDoc value) {
479
480         if (ownerDocument.errorChecking && isReadOnly()) {
481             String JavaDoc msg =
482                 DOMMessageFormatter.formatMessage(
483                     DOMMessageFormatter.DOM_DOMAIN,
484                     "NO_MODIFICATION_ALLOWED_ERR",
485                     null);
486             throw new DOMException JavaDoc(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
487         }
488
489         if (needsSyncData()) {
490             synchronizeData();
491         }
492
493         Attr JavaDoc newAttr = getAttributeNode(name);
494         if (newAttr == null) {
495             newAttr = getOwnerDocument().createAttribute(name);
496
497             if (attributes == null) {
498                 attributes = new AttributeMap(this, null);
499             }
500
501             newAttr.setNodeValue(value);
502             attributes.setNamedItem(newAttr);
503         }
504         else {
505             newAttr.setNodeValue(value);
506         }
507
508     } // setAttribute(String,String)
509

510     /**
511      * Add a new attribute/value pair, or replace the value of the
512      * existing attribute with that name.
513      * <P>
514      * This method allows you to add an Attribute that has already been
515      * constructed, and hence avoids the limitations of the simple
516      * setAttribute() call. It can handle attribute values that have
517      * arbitrarily complex tree structure -- in particular, those which
518      * had entity references mixed into their text.
519      *
520      * @throws DOMException(INUSE_ATTRIBUTE_ERR) if the Attribute object
521      * has already been assigned to another Element.
522      */

523     public Attr JavaDoc setAttributeNode(Attr JavaDoc newAttr)
524         throws DOMException JavaDoc
525         {
526
527         if (needsSyncData()) {
528             synchronizeData();
529         }
530
531         if (ownerDocument.errorChecking) {
532             if (isReadOnly()) {
533                 String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
534                 throw new DOMException JavaDoc(
535                                      DOMException.NO_MODIFICATION_ALLOWED_ERR,
536                                      msg);
537             }
538
539             if (newAttr.getOwnerDocument() != ownerDocument) {
540                 String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
541                 throw new DOMException JavaDoc(DOMException.WRONG_DOCUMENT_ERR, msg);
542             }
543         }
544
545         if (attributes == null) {
546             attributes = new AttributeMap(this, null);
547         }
548         // This will throw INUSE if necessary
549
return (Attr JavaDoc) attributes.setNamedItem(newAttr);
550
551     } // setAttributeNode(Attr):Attr
552

553     //
554
// DOM2: Namespace methods
555
//
556

557     /**
558      * Introduced in DOM Level 2. <p>
559      *
560      * Retrieves an attribute value by local name and namespace URI.
561      *
562      * @param namespaceURI
563      * The namespace URI of the attribute to
564      * retrieve.
565      * @param localName The local name of the attribute to retrieve.
566      * @return String The Attr value as a string, or empty string
567      * if that attribute
568      * does not have a specified or default value.
569      * @since WD-DOM-Level-2-19990923
570      */

571     public String JavaDoc getAttributeNS(String JavaDoc namespaceURI, String JavaDoc localName) {
572
573         if (needsSyncData()) {
574             synchronizeData();
575         }
576
577         if (attributes == null) {
578             return "";
579         }
580
581         Attr JavaDoc attr = (Attr JavaDoc)(attributes.getNamedItemNS(namespaceURI, localName));
582         return (attr == null) ? "" : attr.getValue();
583
584     } // getAttributeNS(String,String):String
585

586     /**
587      * Introduced in DOM Level 2. <p>
588      *
589      * Adds a new attribute.
590      * If the given namespaceURI is null or an empty string and the
591      * qualifiedName has a prefix that is "xml", the new attribute is bound to
592      * the predefined namespace "http://www.w3.org/XML/1998/namespace"
593      * [Namespaces]. If an attribute with the same local name and namespace
594      * URI is already present on the element, its prefix is changed to be the
595      * prefix part of the qualifiedName, and its value is changed to be the
596      * value parameter. This value is a simple string, it is not parsed as it
597      * is being set. So any markup (such as syntax to be recognized as an
598      * entity reference) is treated as literal text, and needs to be
599      * appropriately escaped by the implementation when it is written out. In
600      * order to assign an attribute value that contains entity references, the
601      * user must create an Attr node plus any Text and EntityReference nodes,
602      * build the appropriate subtree, and use setAttributeNodeNS or
603      * setAttributeNode to assign it as the value of an attribute.
604      *
605      * @param namespaceURI The namespace URI of the attribute to create
606      * or alter.
607      * @param qualifiedName The qualified name of the attribute to create or
608      * alter.
609      * @param value The value to set in string form.
610      * @throws INVALID_CHARACTER_ERR: Raised if the specified
611      * name contains an invalid character.
612      *
613      * @throws NO_MODIFICATION_ALLOWED_ERR: Raised if this
614      * node is readonly.
615      *
616      * @throws NAMESPACE_ERR: Raised if the qualifiedName
617      * has a prefix that is "xml" and the namespaceURI
618      * is neither null nor an empty string nor
619      * "http://www.w3.org/XML/1998/namespace", or if
620      * the qualifiedName has a prefix that is "xmlns"
621      * but the namespaceURI is neither null nor an
622      * empty string, or if if the qualifiedName has a
623      * prefix different from "xml" and "xmlns" and the
624      * namespaceURI is null or an empty string.
625      * @since WD-DOM-Level-2-19990923
626      */

627      public void setAttributeNS(String JavaDoc namespaceURI,String JavaDoc qualifiedName,
628                                   String JavaDoc value) {
629         if (ownerDocument.errorChecking && isReadOnly()) {
630             String JavaDoc msg =
631                 DOMMessageFormatter.formatMessage(
632                     DOMMessageFormatter.DOM_DOMAIN,
633                     "NO_MODIFICATION_ALLOWED_ERR",
634                     null);
635             throw new DOMException JavaDoc(
636                 DOMException.NO_MODIFICATION_ALLOWED_ERR,
637                 msg);
638         }
639         if (needsSyncData()) {
640             synchronizeData();
641         }
642         int index = qualifiedName.indexOf(':');
643         String JavaDoc prefix, localName;
644         if (index < 0) {
645             prefix = null;
646             localName = qualifiedName;
647         }
648         else {
649             prefix = qualifiedName.substring(0, index);
650             localName = qualifiedName.substring(index + 1);
651         }
652         Attr JavaDoc newAttr = getAttributeNodeNS(namespaceURI, localName);
653         if (newAttr == null) {
654             // REVISIT: this is not efficient, we are creating twice the same
655
// strings for prefix and localName.
656
newAttr = getOwnerDocument().createAttributeNS(
657                     namespaceURI,
658                     qualifiedName);
659             if (attributes == null) {
660                 attributes = new AttributeMap(this, null);
661             }
662             newAttr.setNodeValue(value);
663             attributes.setNamedItemNS(newAttr);
664         }
665         else {
666             if (newAttr instanceof AttrNSImpl){
667                 // change prefix and value
668
((AttrNSImpl)newAttr).name= (prefix!=null)?(prefix+":"+localName):localName;
669             }
670             else {
671                 // This case may happen if user calls:
672
// elem.setAttribute("name", "value");
673
// elem.setAttributeNS(null, "name", "value");
674
// This case is not defined by the DOM spec, we choose
675
// to create a new attribute in this case and remove an old one from the tree
676
// note this might cause events to be propagated or user data to be lost
677
newAttr = new AttrNSImpl((CoreDocumentImpl)getOwnerDocument(), namespaceURI, qualifiedName, localName);
678                 attributes.setNamedItemNS(newAttr);
679             }
680
681             newAttr.setNodeValue(value);
682         }
683
684     } // setAttributeNS(String,String,String)
685

686
687     /**
688      * Introduced in DOM Level 2. <p>
689      *
690      * Removes an attribute by local name and namespace URI. If the removed
691      * attribute has a default value it is immediately replaced.
692      * The replacing attribute has the same namespace URI and local name,
693      * as well as the original prefix.<p>
694      *
695      * @param namespaceURI The namespace URI of the attribute to remove.
696      *
697      * @param localName The local name of the attribute to remove.
698      * @throws NO_MODIFICATION_ALLOWED_ERR: Raised if this
699      * node is readonly.
700      * @since WD-DOM-Level-2-19990923
701      */

702     public void removeAttributeNS(String JavaDoc namespaceURI, String JavaDoc localName) {
703
704         if (ownerDocument.errorChecking && isReadOnly()) {
705             String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
706             throw new DOMException JavaDoc(DOMException.NO_MODIFICATION_ALLOWED_ERR, msg);
707         }
708
709         if (needsSyncData()) {
710             synchronizeData();
711         }
712
713         if (attributes == null) {
714             return;
715         }
716
717         attributes.safeRemoveNamedItemNS(namespaceURI, localName);
718
719     } // removeAttributeNS(String,String)
720

721     /**
722      * Retrieves an Attr node by local name and namespace URI.
723      *
724      * @param namespaceURI The namespace URI of the attribute to
725      * retrieve.
726      * @param localName The local name of the attribute to retrieve.
727      * @return Attr The Attr node with the specified attribute
728      * local name and namespace
729      * URI or null if there is no such attribute.
730      * @since WD-DOM-Level-2-19990923
731      */

732     public Attr JavaDoc getAttributeNodeNS(String JavaDoc namespaceURI, String JavaDoc localName){
733
734         if (needsSyncData()) {
735             synchronizeData();
736         }
737         if (attributes == null) {
738             return null;
739         }
740         return (Attr JavaDoc)attributes.getNamedItemNS(namespaceURI, localName);
741
742     } // getAttributeNodeNS(String,String):Attr
743

744     /**
745      * Introduced in DOM Level 2. <p>
746      *
747      * Adds a new attribute. If an attribute with that local name and
748      * namespace URI is already present in the element, it is replaced
749      * by the new one.
750      *
751      * @param Attr The Attr node to add to the attribute list. When
752      * the Node has no namespaceURI, this method behaves
753      * like setAttributeNode.
754      * @return Attr If the newAttr attribute replaces an existing attribute
755      * with the same local name and namespace URI, the *
756      * previously existing Attr node is returned, otherwise
757      * null is returned.
758      * @throws WRONG_DOCUMENT_ERR: Raised if newAttr
759      * was created from a different document than the one that
760      * created the element.
761      *
762      * @throws NO_MODIFICATION_ALLOWED_ERR: Raised if
763      * this node is readonly.
764      *
765      * @throws INUSE_ATTRIBUTE_ERR: Raised if newAttr is
766      * already an attribute of another Element object. The
767      * DOM user must explicitly clone Attr nodes to re-use
768      * them in other elements.
769      * @since WD-DOM-Level-2-19990923
770      */

771     public Attr JavaDoc setAttributeNodeNS(Attr JavaDoc newAttr)
772         throws DOMException JavaDoc
773         {
774
775         if (needsSyncData()) {
776             synchronizeData();
777         }
778         if (ownerDocument.errorChecking) {
779             if (isReadOnly()) {
780                 String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
781                 throw new DOMException JavaDoc(
782                                      DOMException.NO_MODIFICATION_ALLOWED_ERR,
783                                      msg);
784             }
785             if (newAttr.getOwnerDocument() != ownerDocument) {
786                 String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "WRONG_DOCUMENT_ERR", null);
787                 throw new DOMException JavaDoc(DOMException.WRONG_DOCUMENT_ERR, msg);
788             }
789         }
790
791         if (attributes == null) {
792             attributes = new AttributeMap(this, null);
793         }
794         // This will throw INUSE if necessary
795
return (Attr JavaDoc) attributes.setNamedItemNS(newAttr);
796
797     } // setAttributeNodeNS(Attr):Attr
798

799     /**
800       * NON-DOM: sets attribute node for this element
801       */

802     protected int setXercesAttributeNode (Attr JavaDoc attr){
803
804         if (needsSyncData()) {
805             synchronizeData();
806         }
807
808         if (attributes == null) {
809             attributes = new AttributeMap(this, null);
810         }
811         return attributes.addItem(attr);
812
813     }
814
815     /**
816       * NON-DOM: get inded of an attribute
817       */

818     protected int getXercesAttribute(String JavaDoc namespaceURI, String JavaDoc localName){
819
820         if (needsSyncData()) {
821             synchronizeData();
822         }
823         if (attributes == null) {
824             return -1;
825         }
826         return attributes.getNamedItemIndex(namespaceURI, localName);
827
828     }
829
830     /**
831      * Introduced in DOM Level 2.
832      */

833     public boolean hasAttributes() {
834         if (needsSyncData()) {
835             synchronizeData();
836         }
837         return (attributes != null && attributes.getLength() != 0);
838     }
839
840     /**
841      * Introduced in DOM Level 2.
842      */

843     public boolean hasAttribute(String JavaDoc name) {
844         return getAttributeNode(name) != null;
845     }
846
847     /**
848      * Introduced in DOM Level 2.
849      */

850     public boolean hasAttributeNS(String JavaDoc namespaceURI, String JavaDoc localName) {
851         return getAttributeNodeNS(namespaceURI, localName) != null;
852     }
853
854     /**
855      * Introduced in DOM Level 2. <p>
856      *
857      * Returns a NodeList of all the Elements with a given local name and
858      * namespace URI in the order in which they would be encountered in a
859      * preorder traversal of the Document tree, starting from this node.
860      *
861      * @param namespaceURI The namespace URI of the elements to match
862      * on. The special value "*" matches all
863      * namespaces. When it is null or an empty
864      * string, this method behaves like
865      * getElementsByTagName.
866      * @param localName The local name of the elements to match on.
867      * The special value "*" matches all local names.
868      * @return NodeList A new NodeList object containing all the matched
869      * Elements.
870      * @since WD-DOM-Level-2-19990923
871      */

872     public NodeList JavaDoc getElementsByTagNameNS(String JavaDoc namespaceURI,
873                                            String JavaDoc localName) {
874         return new DeepNodeListImpl(this, namespaceURI, localName);
875     }
876
877     /**
878      * DOM Level 3 WD- Experimental.
879      * Override inherited behavior from NodeImpl and ParentNode to check on
880      * attributes
881      */

882     public boolean isEqualNode(Node JavaDoc arg) {
883         if (!super.isEqualNode(arg)) {
884             return false;
885         }
886         boolean hasAttrs = hasAttributes();
887         if (hasAttrs != ((Element JavaDoc) arg).hasAttributes()) {
888             return false;
889         }
890         if (hasAttrs) {
891             NamedNodeMap JavaDoc map1 = getAttributes();
892             NamedNodeMap JavaDoc map2 = ((Element JavaDoc) arg).getAttributes();
893             int len = map1.getLength();
894             if (len != map2.getLength()) {
895                 return false;
896             }
897             for (int i = 0; i < len; i++) {
898                 Node JavaDoc n1 = map1.item(i);
899                 if (n1.getLocalName() == null) { // DOM Level 1 Node
900
Node JavaDoc n2 = map2.getNamedItem(n1.getNodeName());
901                     if (n2 == null || !((NodeImpl) n1).isEqualNode(n2)) {
902                         return false;
903                     }
904                 }
905                 else {
906                     Node JavaDoc n2 = map2.getNamedItemNS(n1.getNamespaceURI(),
907                                                   n1.getLocalName());
908                     if (n2 == null || !((NodeImpl) n1).isEqualNode(n2)) {
909                         return false;
910                     }
911                 }
912             }
913         }
914         return true;
915     }
916
917     /**
918      * DOM Level 3: register the given attribute node as an ID attribute
919      */

920     public void setIdAttributeNode(Attr JavaDoc at, boolean makeId) {
921         if (needsSyncData()) {
922             synchronizeData();
923         }
924         if (ownerDocument.errorChecking) {
925             if (isReadOnly()) {
926                 String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
927                 throw new DOMException JavaDoc(
928                                      DOMException.NO_MODIFICATION_ALLOWED_ERR,
929                                      msg);
930             }
931
932             if (at.getOwnerElement() != this) {
933                 String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
934                 throw new DOMException JavaDoc(DOMException.NOT_FOUND_ERR, msg);
935             }
936         }
937         ((AttrImpl) at).isIdAttribute(makeId);
938         if (!makeId) {
939             ownerDocument.removeIdentifier(at.getValue());
940         }
941         else {
942             ownerDocument.putIdentifier(at.getValue(), this);
943         }
944     }
945
946     /**
947      * DOM Level 3: register the given attribute node as an ID attribute
948      */

949     public void setIdAttribute(String JavaDoc name, boolean makeId) {
950         if (needsSyncData()) {
951             synchronizeData();
952         }
953         Attr JavaDoc at = getAttributeNode(name);
954         
955         if( at == null){
956             String JavaDoc msg = DOMMessageFormatter.formatMessage(
957                                     DOMMessageFormatter.DOM_DOMAIN,
958                                     "NOT_FOUND_ERR", null);
959             throw new DOMException JavaDoc(DOMException.NOT_FOUND_ERR, msg);
960         }
961         
962         if (ownerDocument.errorChecking) {
963             if (isReadOnly()) {
964                 String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
965                 throw new DOMException JavaDoc(
966                                      DOMException.NO_MODIFICATION_ALLOWED_ERR,
967                                      msg);
968             }
969
970             if (at.getOwnerElement() != this) {
971                 String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
972                 throw new DOMException JavaDoc(DOMException.NOT_FOUND_ERR, msg);
973             }
974         }
975
976         ((AttrImpl) at).isIdAttribute(makeId);
977         if (!makeId) {
978             ownerDocument.removeIdentifier(at.getValue());
979         }
980         else {
981             ownerDocument.putIdentifier(at.getValue(), this);
982         }
983     }
984
985     /**
986      * DOM Level 3: register the given attribute node as an ID attribute
987      */

988     public void setIdAttributeNS(String JavaDoc namespaceURI, String JavaDoc localName,
989                                     boolean makeId) {
990         if (needsSyncData()) {
991             synchronizeData();
992         }
993         Attr JavaDoc at = getAttributeNodeNS(namespaceURI, localName);
994         
995         if( at == null){
996             String JavaDoc msg = DOMMessageFormatter.formatMessage(
997                                     DOMMessageFormatter.DOM_DOMAIN,
998                                     "NOT_FOUND_ERR", null);
999             throw new DOMException JavaDoc(DOMException.NOT_FOUND_ERR, msg);
1000        }
1001       
1002        if (ownerDocument.errorChecking) {
1003            if (isReadOnly()) {
1004                String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NO_MODIFICATION_ALLOWED_ERR", null);
1005                throw new DOMException JavaDoc(
1006                                     DOMException.NO_MODIFICATION_ALLOWED_ERR,
1007                                     msg);
1008            }
1009
1010            if (at.getOwnerElement() != this) {
1011                String JavaDoc msg = DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "NOT_FOUND_ERR", null);
1012                throw new DOMException JavaDoc(DOMException.NOT_FOUND_ERR, msg);
1013            }
1014        }
1015        ((AttrImpl) at).isIdAttribute(makeId);
1016        if (!makeId) {
1017            ownerDocument.removeIdentifier(at.getValue());
1018        }
1019        else {
1020            ownerDocument.putIdentifier(at.getValue(), this);
1021        }
1022   }
1023
1024    /**
1025     * @see org.w3c.dom.TypeInfo#getTypeName()
1026     */

1027     public String JavaDoc getTypeName() {
1028        return null;
1029     }
1030
1031    /**
1032     * @see org.w3c.dom.TypeInfo#getTypeNamespace()
1033     */

1034    public String JavaDoc getTypeNamespace() {
1035        return null;
1036    }
1037
1038    /**
1039     * Introduced in DOM Level 3. <p>
1040     * Checks if a type is derived from another by restriction. See:
1041     * http://www.w3.org/TR/DOM-Level-3-Core/core.html#TypeInfo-isDerivedFrom
1042     *
1043     * @param ancestorNS
1044     * The namspace of the ancestor type declaration
1045     * @param ancestorName
1046     * The name of the ancestor type declaration
1047     * @param type
1048     * The reference type definition
1049     *
1050     * @return boolean True if the type is derived by restriciton for the
1051     * reference type
1052     */

1053    public boolean isDerivedFrom(String JavaDoc typeNamespaceArg,
1054                                 String JavaDoc typeNameArg,
1055                                 int derivationMethod) {
1056                                    
1057        return false;
1058    }
1059
1060    /**
1061     * Method getSchemaTypeInfo.
1062     * @return TypeInfo
1063     */

1064    public TypeInfo JavaDoc getSchemaTypeInfo(){
1065        if(needsSyncData()) {
1066            synchronizeData();
1067        }
1068        return this;
1069    }
1070
1071    //
1072
// Public methods
1073
//
1074

1075    /**
1076     * NON-DOM: Subclassed to flip the attributes' readonly switch as well.
1077     * @see NodeImpl#setReadOnly
1078     */

1079    public void setReadOnly(boolean readOnly, boolean deep) {
1080        super.setReadOnly(readOnly,deep);
1081        if (attributes != null) {
1082            attributes.setReadOnly(readOnly,true);
1083        }
1084    }
1085
1086
1087
1088    //
1089
// Protected methods
1090
//
1091

1092    /** Synchronizes the data (name and value) for fast nodes. */
1093    protected void synchronizeData() {
1094
1095        // no need to sync in the future
1096
needsSyncData(false);
1097
1098        // we don't want to generate any event for this so turn them off
1099
boolean orig = ownerDocument.getMutationEvents();
1100        ownerDocument.setMutationEvents(false);
1101
1102        // attributes
1103
setupDefaultAttributes();
1104
1105        // set mutation events flag back to its original value
1106
ownerDocument.setMutationEvents(orig);
1107
1108    } // synchronizeData()
1109

1110    // support for DOM Level 3 renameNode method
1111
// @param el The element from which to take the attributes
1112
void moveSpecifiedAttributes(ElementImpl el) {
1113        if (needsSyncData()) {
1114            synchronizeData();
1115        }
1116        if (el.hasAttributes()) {
1117            if (attributes == null) {
1118                attributes = new AttributeMap(this, null);
1119            }
1120            attributes.moveSpecifiedAttributes(el.attributes);
1121        }
1122    }
1123
1124    /** Setup the default attributes. */
1125    protected void setupDefaultAttributes() {
1126        NamedNodeMapImpl defaults = getDefaultAttributes();
1127        if (defaults != null) {
1128            attributes = new AttributeMap(this, defaults);
1129        }
1130    }
1131
1132    /** Reconcile default attributes. */
1133    protected void reconcileDefaultAttributes() {
1134        if (attributes != null) {
1135            NamedNodeMapImpl defaults = getDefaultAttributes();
1136            attributes.reconcileDefaults(defaults);
1137        }
1138    }
1139
1140    /** Get the default attributes. */
1141    protected NamedNodeMapImpl getDefaultAttributes() {
1142
1143        DocumentTypeImpl doctype =
1144            (DocumentTypeImpl) ownerDocument.getDoctype();
1145        if (doctype == null) {
1146            return null;
1147        }
1148        ElementDefinitionImpl eldef =
1149            (ElementDefinitionImpl)doctype.getElements()
1150                                               .getNamedItem(getNodeName());
1151        if (eldef == null) {
1152            return null;
1153        }
1154        return (NamedNodeMapImpl) eldef.getAttributes();
1155
1156    } // getDefaultAttributes()
1157

1158} // class ElementImpl
1159
Popular Tags