KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.io.IOException JavaDoc;
20 import java.io.ObjectOutputStream JavaDoc;
21 import java.io.Serializable JavaDoc;
22 import java.util.Hashtable JavaDoc;
23
24 import org.w3c.dom.UserDataHandler JavaDoc;
25 import org.w3c.dom.DOMException JavaDoc;
26 import org.w3c.dom.Document JavaDoc;
27 import org.w3c.dom.DocumentType JavaDoc;
28 import org.w3c.dom.NamedNodeMap JavaDoc;
29 import org.w3c.dom.Node JavaDoc;
30 import org.w3c.dom.NodeList JavaDoc;
31 import org.w3c.dom.events.Event JavaDoc;
32 import org.w3c.dom.events.EventListener JavaDoc;
33 import org.w3c.dom.events.EventTarget JavaDoc;
34
35 /**
36  * NodeImpl provides the basic structure of a DOM tree. It is never used
37  * directly, but instead is subclassed to add type and data
38  * information, and additional methods, appropriate to each node of
39  * the tree. Only its subclasses should be instantiated -- and those,
40  * with the exception of Document itself, only through a specific
41  * Document's factory methods.
42  * <P>
43  * The Node interface provides shared behaviors such as siblings and
44  * children, both for consistancy and so that the most common tree
45  * operations may be performed without constantly having to downcast
46  * to specific node types. When there is no obvious mapping for one of
47  * these queries, it will respond with null.
48  * Note that the default behavior is that children are forbidden. To
49  * permit them, the subclass ParentNode overrides several methods.
50  * <P>
51  * NodeImpl also implements NodeList, so it can return itself in
52  * response to the getChildNodes() query. This eliminiates the need
53  * for a separate ChildNodeList object. Note that this is an
54  * IMPLEMENTATION DETAIL; applications should _never_ assume that
55  * this identity exists.
56  * <P>
57  * All nodes in a single document must originate
58  * in that document. (Note that this is much tighter than "must be
59  * same implementation") Nodes are all aware of their ownerDocument,
60  * and attempts to mismatch will throw WRONG_DOCUMENT_ERR.
61  * <P>
62  * However, to save memory not all nodes always have a direct reference
63  * to their ownerDocument. When a node is owned by another node it relies
64  * on its owner to store its ownerDocument. Parent nodes always store it
65  * though, so there is never more than one level of indirection.
66  * And when a node doesn't have an owner, ownerNode refers to its
67  * ownerDocument.
68  * <p>
69  * This class doesn't directly support mutation events, however, it still
70  * implements the EventTarget interface and forward all related calls to the
71  * document so that the document class do so.
72  *
73  * @xerces.internal
74  *
75  * @author Arnaud Le Hors, IBM
76  * @author Joe Kesselman, IBM
77  * @version $Id: NodeImpl.java,v 1.75 2005/05/02 22:02:22 mrglavas Exp $
78  * @since PR-DOM-Level-1-19980818.
79  */

80 public abstract class NodeImpl
81     implements Node JavaDoc, NodeList JavaDoc, EventTarget JavaDoc, Cloneable JavaDoc, Serializable JavaDoc{
82
83     //
84
// Constants
85
//
86

87
88     // TreePosition Constants.
89
// Taken from DOM L3 Node interface.
90
/**
91      * The node precedes the reference node.
92      */

93     public static final short TREE_POSITION_PRECEDING = 0x01;
94     /**
95      * The node follows the reference node.
96      */

97     public static final short TREE_POSITION_FOLLOWING = 0x02;
98     /**
99      * The node is an ancestor of the reference node.
100      */

101     public static final short TREE_POSITION_ANCESTOR = 0x04;
102     /**
103      * The node is a descendant of the reference node.
104      */

105     public static final short TREE_POSITION_DESCENDANT = 0x08;
106     /**
107      * The two nodes have an equivalent position. This is the case of two
108      * attributes that have the same <code>ownerElement</code>, and two
109      * nodes that are the same.
110      */

111     public static final short TREE_POSITION_EQUIVALENT = 0x10;
112     /**
113      * The two nodes are the same. Two nodes that are the same have an
114      * equivalent position, though the reverse may not be true.
115      */

116     public static final short TREE_POSITION_SAME_NODE = 0x20;
117     /**
118      * The two nodes are disconnected, they do not have any common ancestor.
119      * This is the case of two nodes that are not in the same document.
120      */

121     public static final short TREE_POSITION_DISCONNECTED = 0x00;
122
123
124     // DocumentPosition
125
public static final short DOCUMENT_POSITION_DISCONNECTED = 0x01;
126     public static final short DOCUMENT_POSITION_PRECEDING = 0x02;
127     public static final short DOCUMENT_POSITION_FOLLOWING = 0x04;
128     public static final short DOCUMENT_POSITION_CONTAINS = 0x08;
129     public static final short DOCUMENT_POSITION_IS_CONTAINED = 0x10;
130     public static final short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
131
132     /** Serialization version. */
133     static final long serialVersionUID = -6316591992167219696L;
134
135     // public
136

137     /** Element definition node type. */
138     public static final short ELEMENT_DEFINITION_NODE = 21;
139
140     //
141
// Data
142
//
143

144     // links
145

146     protected NodeImpl ownerNode; // typically the parent but not always!
147

148     // data
149

150     protected short flags;
151
152     protected final static short READONLY = 0x1<<0;
153     protected final static short SYNCDATA = 0x1<<1;
154     protected final static short SYNCCHILDREN = 0x1<<2;
155     protected final static short OWNED = 0x1<<3;
156     protected final static short FIRSTCHILD = 0x1<<4;
157     protected final static short SPECIFIED = 0x1<<5;
158     protected final static short IGNORABLEWS = 0x1<<6;
159     protected final static short HASSTRING = 0x1<<7;
160     protected final static short NORMALIZED = 0x1<<8;
161     protected final static short ID = 0x1<<9;
162
163     //
164
// Constructors
165
//
166

167     /**
168      * No public constructor; only subclasses of Node should be
169      * instantiated, and those normally via a Document's factory methods
170      * <p>
171      * Every Node knows what Document it belongs to.
172      */

173     protected NodeImpl(CoreDocumentImpl ownerDocument) {
174         // as long as we do not have any owner, ownerNode is our ownerDocument
175
ownerNode = ownerDocument;
176     } // <init>(CoreDocumentImpl)
177

178     /** Constructor for serialization. */
179     public NodeImpl() {}
180
181     //
182
// Node methods
183
//
184

185     /**
186      * A short integer indicating what type of node this is. The named
187      * constants for this value are defined in the org.w3c.dom.Node interface.
188      */

189     public abstract short getNodeType();
190
191     /**
192      * the name of this node.
193      */

194     public abstract String JavaDoc getNodeName();
195     
196     /**
197      * Returns the node value.
198      * @throws DOMException(DOMSTRING_SIZE_ERR)
199      */

200     public String JavaDoc getNodeValue()
201         throws DOMException JavaDoc {
202         return null; // overridden in some subclasses
203
}
204
205     /**
206      * Sets the node value.
207      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR)
208      */

209     public void setNodeValue(String JavaDoc x)
210         throws DOMException JavaDoc {
211         // Default behavior is to do nothing, overridden in some subclasses
212
}
213
214     /**
215      * Adds a child node to the end of the list of children for this node.
216      * Convenience shorthand for insertBefore(newChild,null).
217      * @see #insertBefore(Node, Node)
218      * <P>
219      * By default we do not accept any children, ParentNode overrides this.
220      * @see ParentNode
221      *
222      * @return newChild, in its new state (relocated, or emptied in the case of
223      * DocumentNode.)
224      *
225      * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
226      * type that shouldn't be a child of this node.
227      *
228      * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
229      * different owner document than we do.
230      *
231      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
232      * read-only.
233      */

234     public Node JavaDoc appendChild(Node JavaDoc newChild) throws DOMException JavaDoc {
235         return insertBefore(newChild, null);
236     }
237
238     /**
239      * Returns a duplicate of a given node. You can consider this a
240      * generic "copy constructor" for nodes. The newly returned object should
241      * be completely independent of the source object's subtree, so changes
242      * in one after the clone has been made will not affect the other.
243      * <P>
244      * Note: since we never have any children deep is meaningless here,
245      * ParentNode overrides this behavior.
246      * @see ParentNode
247      *
248      * <p>
249      * Example: Cloning a Text node will copy both the node and the text it
250      * contains.
251      * <p>
252      * Example: Cloning something that has children -- Element or Attr, for
253      * example -- will _not_ clone those children unless a "deep clone"
254      * has been requested. A shallow clone of an Attr node will yield an
255      * empty Attr of the same name.
256      * <p>
257      * NOTE: Clones will always be read/write, even if the node being cloned
258      * is read-only, to permit applications using only the DOM API to obtain
259      * editable copies of locked portions of the tree.
260      */

261     public Node JavaDoc cloneNode(boolean deep) {
262
263         if (needsSyncData()) {
264             synchronizeData();
265     }
266         
267         NodeImpl newnode;
268         try {
269             newnode = (NodeImpl)clone();
270         }
271         catch (CloneNotSupportedException JavaDoc e) {
272             // if we get here we have an error in our program we may as well
273
// be vocal about it, so that people can take appropriate action.
274
throw new RuntimeException JavaDoc("**Internal Error**" + e);
275         }
276         
277         // Need to break the association w/ original kids
278
newnode.ownerNode = ownerDocument();
279         newnode.isOwned(false);
280
281         // By default we make all clones readwrite,
282
// this is overriden in readonly subclasses
283
newnode.isReadOnly(false);
284
285         ownerDocument().callUserDataHandlers(this, newnode,
286                                              UserDataHandler.NODE_CLONED);
287
288         return newnode;
289
290     } // cloneNode(boolean):Node
291

292     /**
293      * Find the Document that this Node belongs to (the document in
294      * whose context the Node was created). The Node may or may not
295      * currently be part of that Document's actual contents.
296      */

297     public Document JavaDoc getOwnerDocument() {
298         // if we have an owner simply forward the request
299
// otherwise ownerNode is our ownerDocument
300
if (isOwned()) {
301             return ownerNode.ownerDocument();
302         } else {
303             return (Document JavaDoc) ownerNode;
304         }
305     }
306
307     /**
308      * same as above but returns internal type and this one is not overridden
309      * by CoreDocumentImpl to return null
310      */

311     CoreDocumentImpl ownerDocument() {
312         // if we have an owner simply forward the request
313
// otherwise ownerNode is our ownerDocument
314
if (isOwned()) {
315             return ownerNode.ownerDocument();
316         } else {
317             return (CoreDocumentImpl) ownerNode;
318         }
319     }
320
321     /**
322      * NON-DOM
323      * set the ownerDocument of this node
324      */

325     void setOwnerDocument(CoreDocumentImpl doc) {
326         if (needsSyncData()) {
327             synchronizeData();
328         }
329         // if we have an owner we rely on it to have it right
330
// otherwise ownerNode is our ownerDocument
331
if (!isOwned()) {
332             ownerNode = doc;
333         }
334     }
335
336     /**
337      * Returns the node number
338      */

339     protected int getNodeNumber() {
340         int nodeNumber;
341         CoreDocumentImpl cd = (CoreDocumentImpl)(this.getOwnerDocument());
342         nodeNumber = cd.getNodeNumber(this);
343         return nodeNumber;
344     }
345
346     /**
347      * Obtain the DOM-tree parent of this node, or null if it is not
348      * currently active in the DOM tree (perhaps because it has just been
349      * created or removed). Note that Document, DocumentFragment, and
350      * Attribute will never have parents.
351      */

352     public Node JavaDoc getParentNode() {
353         return null; // overriden by ChildNode
354
}
355
356     /*
357      * same as above but returns internal type
358      */

359     NodeImpl parentNode() {
360         return null;
361     }
362
363     /** The next child of this node's parent, or null if none */
364     public Node JavaDoc getNextSibling() {
365         return null; // default behavior, overriden in ChildNode
366
}
367
368     /** The previous child of this node's parent, or null if none */
369     public Node JavaDoc getPreviousSibling() {
370         return null; // default behavior, overriden in ChildNode
371
}
372
373     ChildNode previousSibling() {
374         return null; // default behavior, overriden in ChildNode
375
}
376
377     /**
378      * Return the collection of attributes associated with this node,
379      * or null if none. At this writing, Element is the only type of node
380      * which will ever have attributes.
381      *
382      * @see ElementImpl
383      */

384     public NamedNodeMap JavaDoc getAttributes() {
385         return null; // overridden in ElementImpl
386
}
387
388     /**
389      * Returns whether this node (if it is an element) has any attributes.
390      * @return <code>true</code> if this node has any attributes,
391      * <code>false</code> otherwise.
392      * @since DOM Level 2
393      * @see ElementImpl
394      */

395     public boolean hasAttributes() {
396         return false; // overridden in ElementImpl
397
}
398
399     /**
400      * Test whether this node has any children. Convenience shorthand
401      * for (Node.getFirstChild()!=null)
402      * <P>
403      * By default we do not have any children, ParentNode overrides this.
404      * @see ParentNode
405      */

406     public boolean hasChildNodes() {
407         return false;
408     }
409
410     /**
411      * Obtain a NodeList enumerating all children of this node. If there
412      * are none, an (initially) empty NodeList is returned.
413      * <p>
414      * NodeLists are "live"; as children are added/removed the NodeList
415      * will immediately reflect those changes. Also, the NodeList refers
416      * to the actual nodes, so changes to those nodes made via the DOM tree
417      * will be reflected in the NodeList and vice versa.
418      * <p>
419      * In this implementation, Nodes implement the NodeList interface and
420      * provide their own getChildNodes() support. Other DOMs may solve this
421      * differently.
422      */

423     public NodeList JavaDoc getChildNodes() {
424         return this;
425     }
426
427     /** The first child of this Node, or null if none.
428      * <P>
429      * By default we do not have any children, ParentNode overrides this.
430      * @see ParentNode
431      */

432     public Node JavaDoc getFirstChild() {
433         return null;
434     }
435
436     /** The first child of this Node, or null if none.
437      * <P>
438      * By default we do not have any children, ParentNode overrides this.
439      * @see ParentNode
440      */

441     public Node JavaDoc getLastChild() {
442     return null;
443     }
444
445     /**
446      * Move one or more node(s) to our list of children. Note that this
447      * implicitly removes them from their previous parent.
448      * <P>
449      * By default we do not accept any children, ParentNode overrides this.
450      * @see ParentNode
451      *
452      * @param newChild The Node to be moved to our subtree. As a
453      * convenience feature, inserting a DocumentNode will instead insert
454      * all its children.
455      *
456      * @param refChild Current child which newChild should be placed
457      * immediately before. If refChild is null, the insertion occurs
458      * after all existing Nodes, like appendChild().
459      *
460      * @return newChild, in its new state (relocated, or emptied in the case of
461      * DocumentNode.)
462      *
463      * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
464      * type that shouldn't be a child of this node, or if newChild is an
465      * ancestor of this node.
466      *
467      * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
468      * different owner document than we do.
469      *
470      * @throws DOMException(NOT_FOUND_ERR) if refChild is not a child of
471      * this node.
472      *
473      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
474      * read-only.
475      */

476     public Node JavaDoc insertBefore(Node JavaDoc newChild, Node JavaDoc refChild)
477     throws DOMException JavaDoc {
478     throw new DOMException JavaDoc(DOMException.HIERARCHY_REQUEST_ERR,
479               DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
480                  "HIERARCHY_REQUEST_ERR", null));
481     }
482
483     /**
484      * Remove a child from this Node. The removed child's subtree
485      * remains intact so it may be re-inserted elsewhere.
486      * <P>
487      * By default we do not have any children, ParentNode overrides this.
488      * @see ParentNode
489      *
490      * @return oldChild, in its new state (removed).
491      *
492      * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
493      * this node.
494      *
495      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
496      * read-only.
497      */

498     public Node JavaDoc removeChild(Node JavaDoc oldChild)
499         throws DOMException JavaDoc {
500     throw new DOMException JavaDoc(DOMException.NOT_FOUND_ERR,
501               DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
502                  "NOT_FOUND_ERR", null));
503     }
504
505     /**
506      * Make newChild occupy the location that oldChild used to
507      * have. Note that newChild will first be removed from its previous
508      * parent, if any. Equivalent to inserting newChild before oldChild,
509      * then removing oldChild.
510      * <P>
511      * By default we do not have any children, ParentNode overrides this.
512      * @see ParentNode
513      *
514      * @return oldChild, in its new state (removed).
515      *
516      * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
517      * type that shouldn't be a child of this node, or if newChild is
518      * one of our ancestors.
519      *
520      * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
521      * different owner document than we do.
522      *
523      * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
524      * this node.
525      *
526      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
527      * read-only.
528      */

529     public Node JavaDoc replaceChild(Node JavaDoc newChild, Node JavaDoc oldChild)
530         throws DOMException JavaDoc {
531     throw new DOMException JavaDoc(DOMException.HIERARCHY_REQUEST_ERR,
532               DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
533                  "HIERARCHY_REQUEST_ERR", null));
534     }
535
536     //
537
// NodeList methods
538
//
539

540     /**
541      * NodeList method: Count the immediate children of this node
542      * <P>
543      * By default we do not have any children, ParentNode overrides this.
544      * @see ParentNode
545      *
546      * @return int
547      */

548     public int getLength() {
549     return 0;
550     }
551
552     /**
553      * NodeList method: Return the Nth immediate child of this node, or
554      * null if the index is out of bounds.
555      * <P>
556      * By default we do not have any children, ParentNode overrides this.
557      * @see ParentNode
558      *
559      * @return org.w3c.dom.Node
560      * @param Index int
561      */

562     public Node JavaDoc item(int index) {
563     return null;
564     }
565
566     //
567
// DOM2: methods, getters, setters
568
//
569

570     /**
571      * Puts all <code>Text</code> nodes in the full depth of the sub-tree
572      * underneath this <code>Node</code>, including attribute nodes, into a
573      * "normal" form where only markup (e.g., tags, comments, processing
574      * instructions, CDATA sections, and entity references) separates
575      * <code>Text</code> nodes, i.e., there are no adjacent <code>Text</code>
576      * nodes. This can be used to ensure that the DOM view of a document is
577      * the same as if it were saved and re-loaded, and is useful when
578      * operations (such as XPointer lookups) that depend on a particular
579      * document tree structure are to be used.In cases where the document
580      * contains <code>CDATASections</code>, the normalize operation alone may
581      * not be sufficient, since XPointers do not differentiate between
582      * <code>Text</code> nodes and <code>CDATASection</code> nodes.
583      * <p>
584      * Note that this implementation simply calls normalize() on this Node's
585      * children. It is up to implementors or Node to override normalize()
586      * to take action.
587      */

588     public void normalize() {
589     /* by default we do not have any children,
590        ParentNode overrides this behavior */

591     }
592
593     /**
594      * Introduced in DOM Level 2. <p>
595      * Tests whether the DOM implementation implements a specific feature and
596      * that feature is supported by this node.
597      * @param feature The package name of the feature to test. This is the same
598      * name as what can be passed to the method hasFeature on
599      * DOMImplementation.
600      * @param version This is the version number of the package name to
601      * test. In Level 2, version 1, this is the string "2.0". If the version is
602      * not specified, supporting any version of the feature will cause the
603      * method to return true.
604      * @return boolean Returns true if this node defines a subtree within which
605      * the specified feature is supported, false otherwise.
606      * @since WD-DOM-Level-2-19990923
607      */

608     public boolean isSupported(String JavaDoc feature, String JavaDoc version)
609     {
610         return ownerDocument().getImplementation().hasFeature(feature,
611                                                               version);
612     }
613
614     /**
615      * Introduced in DOM Level 2. <p>
616      *
617      * The namespace URI of this node, or null if it is unspecified. When this
618      * node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE, this is
619      * always null and setting it has no effect. <p>
620      *
621      * This is not a computed value that is the result of a namespace lookup
622      * based on an examination of the namespace declarations in scope. It is
623      * merely the namespace URI given at creation time.<p>
624      *
625      * For nodes created with a DOM Level 1 method, such as createElement
626      * from the Document interface, this is null.
627      * @since WD-DOM-Level-2-19990923
628      * @see AttrNSImpl
629      * @see ElementNSImpl
630      */

631     public String JavaDoc getNamespaceURI()
632     {
633         return null;
634     }
635
636     /**
637      * Introduced in DOM Level 2. <p>
638      *
639      * The namespace prefix of this node, or null if it is unspecified. When
640      * this node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE this
641      * is always null and setting it has no effect.<p>
642      *
643      * For nodes created with a DOM Level 1 method, such as createElement
644      * from the Document interface, this is null. <p>
645      *
646      * @since WD-DOM-Level-2-19990923
647      * @see AttrNSImpl
648      * @see ElementNSImpl
649      */

650     public String JavaDoc getPrefix()
651     {
652         return null;
653     }
654
655     /**
656      * Introduced in DOM Level 2. <p>
657      *
658      * The namespace prefix of this node, or null if it is unspecified. When
659      * this node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE
660      * this is always null and setting it has no effect.<p>
661      *
662      * For nodes created with a DOM Level 1 method, such as createElement from
663      * the Document interface, this is null.<p>
664      *
665      * Note that setting this attribute changes the nodeName attribute, which
666      * holds the qualified name, as well as the tagName and name attributes of
667      * the Element and Attr interfaces, when applicable.<p>
668      *
669      * @throws INVALID_CHARACTER_ERR Raised if the specified
670      * prefix contains an invalid character.
671      *
672      * @since WD-DOM-Level-2-19990923
673      * @see AttrNSImpl
674      * @see ElementNSImpl
675      */

676     public void setPrefix(String JavaDoc prefix)
677         throws DOMException JavaDoc
678     {
679     throw new DOMException JavaDoc(DOMException.NAMESPACE_ERR,
680               DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
681                  "NAMESPACE_ERR", null));
682     }
683
684     /**
685      * Introduced in DOM Level 2. <p>
686      *
687      * Returns the local part of the qualified name of this node.
688      * For nodes created with a DOM Level 1 method, such as createElement
689      * from the Document interface, and for nodes of any type other than
690      * ELEMENT_NODE and ATTRIBUTE_NODE this is the same as the nodeName
691      * attribute.
692      * @since WD-DOM-Level-2-19990923
693      * @see AttrNSImpl
694      * @see ElementNSImpl
695      */

696     public String JavaDoc getLocalName()
697     {
698         return null;
699     }
700     
701     //
702
// EventTarget support
703
//
704

705     public void addEventListener(String JavaDoc type, EventListener JavaDoc listener,
706                                  boolean useCapture) {
707         // simply forward to Document
708
ownerDocument().addEventListener(this, type, listener, useCapture);
709     }
710
711     public void removeEventListener(String JavaDoc type, EventListener JavaDoc listener,
712                                     boolean useCapture) {
713         // simply forward to Document
714
ownerDocument().removeEventListener(this, type, listener, useCapture);
715     }
716
717     public boolean dispatchEvent(Event JavaDoc event) {
718         // simply forward to Document
719
return ownerDocument().dispatchEvent(this, event);
720     }
721
722     //
723
// Public DOM Level 3 methods
724
//
725

726     /**
727      * The absolute base URI of this node or <code>null</code> if undefined.
728      * This value is computed according to . However, when the
729      * <code>Document</code> supports the feature "HTML" , the base URI is
730      * computed using first the value of the href attribute of the HTML BASE
731      * element if any, and the value of the <code>documentURI</code>
732      * attribute from the <code>Document</code> interface otherwise.
733      * <br> When the node is an <code>Element</code>, a <code>Document</code>
734      * or a a <code>ProcessingInstruction</code>, this attribute represents
735      * the properties [base URI] defined in . When the node is a
736      * <code>Notation</code>, an <code>Entity</code>, or an
737      * <code>EntityReference</code>, this attribute represents the
738      * properties [declaration base URI] in the . How will this be affected
739      * by resolution of relative namespace URIs issue?It's not.Should this
740      * only be on Document, Element, ProcessingInstruction, Entity, and
741      * Notation nodes, according to the infoset? If not, what is it equal to
742      * on other nodes? Null? An empty string? I think it should be the
743      * parent's.No.Should this be read-only and computed or and actual
744      * read-write attribute?Read-only and computed (F2F 19 Jun 2000 and
745      * teleconference 30 May 2001).If the base HTML element is not yet
746      * attached to a document, does the insert change the Document.baseURI?
747      * Yes. (F2F 26 Sep 2001)
748      * @since DOM Level 3
749      */

750     public String JavaDoc getBaseURI() {
751         return null;
752     }
753
754     /**
755      * Compares a node with this node with regard to their position in the
756      * tree and according to the document order. This order can be extended
757      * by module that define additional types of nodes.
758      * @param other The node to compare against this node.
759      * @return Returns how the given node is positioned relatively to this
760      * node.
761      * @since DOM Level 3
762      * @deprecated
763      */

764     public short compareTreePosition(Node JavaDoc other) {
765         // Questions of clarification for this method - to be answered by the
766
// DOM WG. Current assumptions listed - LM
767
//
768
// 1. How do ENTITY nodes compare?
769
// Current assumption: TREE_POSITION_DISCONNECTED, as ENTITY nodes
770
// aren't really 'in the tree'
771
//
772
// 2. How do NOTATION nodes compare?
773
// Current assumption: TREE_POSITION_DISCONNECTED, as NOTATION nodes
774
// aren't really 'in the tree'
775
//
776
// 3. Are TREE_POSITION_ANCESTOR and TREE_POSITION_DESCENDANT
777
// only relevant for nodes that are "part of the document tree"?
778
// <outer>
779
// <inner myattr="true"/>
780
// </outer>
781
// Is the element node "outer" considered an ancestor of "myattr"?
782
// Current assumption: No.
783
//
784
// 4. How do children of ATTRIBUTE nodes compare (with eachother, or
785
// with children of other attribute nodes with the same element)
786
// Current assumption: Children of ATTRIBUTE nodes are treated as if
787
// they they are the attribute node itself, unless the 2 nodes
788
// are both children of the same attribute.
789
//
790
// 5. How does an ENTITY_REFERENCE node compare with it's children?
791
// Given the DOM, it should precede its children as an ancestor.
792
// Given "document order", does it represent the same position?
793
// Current assumption: An ENTITY_REFERENCE node is an ancestor of its
794
// children.
795
//
796
// 6. How do children of a DocumentFragment compare?
797
// Current assumption: If both nodes are part of the same document
798
// fragment, there are compared as if they were part of a document.
799

800         
801         // If the nodes are the same...
802
if (this==other)
803           return (TREE_POSITION_SAME_NODE | TREE_POSITION_EQUIVALENT);
804         
805         // If either node is of type ENTITY or NOTATION, compare as disconnected
806
short thisType = this.getNodeType();
807         short otherType = other.getNodeType();
808
809         // If either node is of type ENTITY or NOTATION, compare as disconnected
810
if (thisType == Node.ENTITY_NODE ||
811             thisType == Node.NOTATION_NODE ||
812             otherType == Node.ENTITY_NODE ||
813             otherType == Node.NOTATION_NODE ) {
814           return TREE_POSITION_DISCONNECTED;
815         }
816
817         // Find the ancestor of each node, and the distance each node is from
818
// its ancestor.
819
// During this traversal, look for ancestor/descendent relationships
820
// between the 2 nodes in question.
821
// We do this now, so that we get this info correct for attribute nodes
822
// and their children.
823

824         Node JavaDoc node;
825         Node JavaDoc thisAncestor = this;
826         Node JavaDoc otherAncestor = other;
827         int thisDepth=0;
828         int otherDepth=0;
829         for (node=this; node != null; node = node.getParentNode()) {
830             thisDepth +=1;
831             if (node == other)
832               // The other node is an ancestor of this one.
833
return (TREE_POSITION_ANCESTOR | TREE_POSITION_PRECEDING);
834             thisAncestor = node;
835         }
836
837         for (node=other; node!=null; node=node.getParentNode()) {
838             otherDepth +=1;
839             if (node == this)
840               // The other node is a descendent of the reference node.
841
return (TREE_POSITION_DESCENDANT | TREE_POSITION_FOLLOWING);
842             otherAncestor = node;
843         }
844         
845        
846         Node JavaDoc thisNode = this;
847         Node JavaDoc otherNode = other;
848
849         int thisAncestorType = thisAncestor.getNodeType();
850         int otherAncestorType = otherAncestor.getNodeType();
851
852         // if the ancestor is an attribute, get owning element.
853
// we are now interested in the owner to determine position.
854

855         if (thisAncestorType == Node.ATTRIBUTE_NODE) {
856            thisNode = ((AttrImpl)thisAncestor).getOwnerElement();
857         }
858         if (otherAncestorType == Node.ATTRIBUTE_NODE) {
859            otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
860         }
861
862         // Before proceeding, we should check if both ancestor nodes turned
863
// out to be attributes for the same element
864
if (thisAncestorType == Node.ATTRIBUTE_NODE &&
865             otherAncestorType == Node.ATTRIBUTE_NODE &&
866             thisNode==otherNode)
867             return TREE_POSITION_EQUIVALENT;
868
869         // Now, find the ancestor of the owning element, if the original
870
// ancestor was an attribute
871

872         // Note: the following 2 loops are quite close to the ones above.
873
// May want to common them up. LM.
874
if (thisAncestorType == Node.ATTRIBUTE_NODE) {
875             thisDepth=0;
876             for (node=thisNode; node != null; node=node.getParentNode()) {
877                 thisDepth +=1;
878                 if (node == otherNode)
879                   // The other node is an ancestor of the owning element
880
{
881                   return TREE_POSITION_PRECEDING;
882                   }
883                 thisAncestor = node;
884             }
885         }
886
887         // Now, find the ancestor of the owning element, if the original
888
// ancestor was an attribute
889
if (otherAncestorType == Node.ATTRIBUTE_NODE) {
890             otherDepth=0;
891             for (node=otherNode; node != null; node=node.getParentNode()) {
892                 otherDepth +=1;
893                 if (node == thisNode)
894                   // The other node is a descendent of the reference
895
// node's element
896
return TREE_POSITION_FOLLOWING;
897                 otherAncestor = node;
898             }
899         }
900
901         // thisAncestor and otherAncestor must be the same at this point,
902
// otherwise, we are not in the same tree or document fragment
903
if (thisAncestor != otherAncestor)
904           return TREE_POSITION_DISCONNECTED;
905
906       
907         // Go up the parent chain of the deeper node, until we find a node
908
// with the same depth as the shallower node
909

910         if (thisDepth > otherDepth) {
911           for (int i=0; i<thisDepth - otherDepth; i++)
912             thisNode = thisNode.getParentNode();
913           // Check if the node we have reached is in fact "otherNode". This can
914
// happen in the case of attributes. In this case, otherNode
915
// "precedes" this.
916
if (thisNode == otherNode)
917             return TREE_POSITION_PRECEDING;
918         }
919  
920         else {
921           for (int i=0; i<otherDepth - thisDepth; i++)
922             otherNode = otherNode.getParentNode();
923           // Check if the node we have reached is in fact "thisNode". This can
924
// happen in the case of attributes. In this case, otherNode
925
// "follows" this.
926
if (otherNode == thisNode)
927             return TREE_POSITION_FOLLOWING;
928         }
929              
930         // We now have nodes at the same depth in the tree. Find a common
931
// ancestor.
932
Node JavaDoc thisNodeP, otherNodeP;
933         for (thisNodeP=thisNode.getParentNode(),
934                   otherNodeP=otherNode.getParentNode();
935              thisNodeP!=otherNodeP;) {
936              thisNode = thisNodeP;
937              otherNode = otherNodeP;
938              thisNodeP = thisNodeP.getParentNode();
939              otherNodeP = otherNodeP.getParentNode();
940         }
941
942         // At this point, thisNode and otherNode are direct children of
943
// the common ancestor.
944
// See whether thisNode or otherNode is the leftmost
945

946         for (Node JavaDoc current=thisNodeP.getFirstChild();
947                   current!=null;
948                   current=current.getNextSibling()) {
949                if (current==otherNode) {
950                  return TREE_POSITION_PRECEDING;
951                }
952                else if (current==thisNode) {
953                  return TREE_POSITION_FOLLOWING;
954                }
955         }
956         // REVISIT: shouldn't get here. Should probably throw an
957
// exception
958
return 0;
959
960     }
961     /**
962      * Compares a node with this node with regard to their position in the
963      * document.
964      * @param other The node to compare against this node.
965      * @return Returns how the given node is positioned relatively to this
966      * node.
967      * @since DOM Level 3
968      */

969     public short compareDocumentPosition(Node JavaDoc other) throws DOMException JavaDoc {
970
971         // If the nodes are the same, no flags should be set
972
if (this==other)
973           return 0;
974
975         // check if other is from a different implementation
976
try {
977             NodeImpl node = (NodeImpl) other;
978         } catch (ClassCastException JavaDoc e) {
979             // other comes from a different implementation
980
String JavaDoc msg = DOMMessageFormatter.formatMessage(
981                DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
982             throw new DOMException JavaDoc(DOMException.NOT_SUPPORTED_ERR, msg);
983         }
984
985         Document JavaDoc thisOwnerDoc, otherOwnerDoc;
986         // get the respective Document owners.
987
if (this.getNodeType() == Node.DOCUMENT_NODE)
988           thisOwnerDoc = (Document JavaDoc)this;
989         else
990           thisOwnerDoc = this.getOwnerDocument();
991         if (other.getNodeType() == Node.DOCUMENT_NODE)
992           otherOwnerDoc = (Document JavaDoc)other;
993         else
994           otherOwnerDoc = other.getOwnerDocument();
995
996         // If from different documents, we know they are disconnected.
997
// and have an implementation dependent order
998
if (thisOwnerDoc != otherOwnerDoc &&
999             thisOwnerDoc !=null &&
1000            otherOwnerDoc !=null)
1001 {
1002          int otherDocNum = ((CoreDocumentImpl)otherOwnerDoc).getNodeNumber();
1003          int thisDocNum = ((CoreDocumentImpl)thisOwnerDoc).getNodeNumber();
1004          if (otherDocNum > thisDocNum)
1005            return DOCUMENT_POSITION_DISCONNECTED |
1006                   DOCUMENT_POSITION_FOLLOWING |
1007                   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
1008          else
1009            return DOCUMENT_POSITION_DISCONNECTED |
1010                   DOCUMENT_POSITION_PRECEDING |
1011                   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
1012                  
1013        }
1014     
1015        // Find the ancestor of each node, and the distance each node is from
1016
// its ancestor.
1017
// During this traversal, look for ancestor/descendent relationships
1018
// between the 2 nodes in question.
1019
// We do this now, so that we get this info correct for attribute nodes
1020
// and their children.
1021

1022        Node JavaDoc node;
1023        Node JavaDoc thisAncestor = this;
1024        Node JavaDoc otherAncestor = other;
1025       
1026        int thisDepth=0;
1027        int otherDepth=0;
1028        for (node=this; node != null; node = node.getParentNode()) {
1029            thisDepth +=1;
1030            if (node == other)
1031              // The other node is an ancestor of this one.
1032
return (DOCUMENT_POSITION_CONTAINS |
1033                      DOCUMENT_POSITION_PRECEDING);
1034            thisAncestor = node;
1035        }
1036
1037        for (node=other; node!=null; node=node.getParentNode()) {
1038            otherDepth +=1;
1039            if (node == this)
1040              // The other node is a descendent of the reference node.
1041
return (DOCUMENT_POSITION_IS_CONTAINED |
1042                      DOCUMENT_POSITION_FOLLOWING);
1043            otherAncestor = node;
1044        }
1045        
1046       
1047
1048        int thisAncestorType = thisAncestor.getNodeType();
1049        int otherAncestorType = otherAncestor.getNodeType();
1050        Node JavaDoc thisNode = this;
1051        Node JavaDoc otherNode = other;
1052
1053        // Special casing for ENTITY, NOTATION, DOCTYPE and ATTRIBUTES
1054
// LM: should rewrite this.
1055
switch (thisAncestorType) {
1056          case Node.NOTATION_NODE:
1057          case Node.ENTITY_NODE: {
1058            DocumentType JavaDoc container = thisOwnerDoc.getDoctype();
1059            if (container == otherAncestor) return
1060                   (DOCUMENT_POSITION_CONTAINS | DOCUMENT_POSITION_PRECEDING);
1061            switch (otherAncestorType) {
1062              case Node.NOTATION_NODE:
1063              case Node.ENTITY_NODE: {
1064                if (thisAncestorType != otherAncestorType)
1065                 // the nodes are of different types
1066
return ((thisAncestorType>otherAncestorType) ?
1067                    DOCUMENT_POSITION_PRECEDING:DOCUMENT_POSITION_FOLLOWING);
1068                else {
1069                 // the nodes are of the same type. Find order.
1070
if (thisAncestorType == Node.NOTATION_NODE)
1071                 
1072                     if (((NamedNodeMapImpl)container.getNotations()).precedes(otherAncestor,thisAncestor))
1073                       return (DOCUMENT_POSITION_PRECEDING |
1074                               DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1075                     else
1076                       return (DOCUMENT_POSITION_FOLLOWING |
1077                               DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1078                 else
1079                     if (((NamedNodeMapImpl)container.getEntities()).precedes(otherAncestor,thisAncestor))
1080                       return (DOCUMENT_POSITION_PRECEDING |
1081                               DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1082                     else
1083                       return (DOCUMENT_POSITION_FOLLOWING |
1084                               DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1085                }
1086              }
1087            }
1088            thisNode = thisAncestor = thisOwnerDoc;
1089            break;
1090          }
1091          case Node.DOCUMENT_TYPE_NODE: {
1092            if (otherNode == thisOwnerDoc)
1093              return (DOCUMENT_POSITION_PRECEDING |
1094                      DOCUMENT_POSITION_CONTAINS);
1095            else if (thisOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc)
1096              return (DOCUMENT_POSITION_FOLLOWING);
1097            break;
1098          }
1099          case Node.ATTRIBUTE_NODE: {
1100            thisNode = ((AttrImpl)thisAncestor).getOwnerElement();
1101            if (otherAncestorType==Node.ATTRIBUTE_NODE) {
1102              otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
1103              if (otherNode == thisNode) {
1104                if (((NamedNodeMapImpl)thisNode.getAttributes()).precedes(other,this))
1105                  return (DOCUMENT_POSITION_PRECEDING |
1106                          DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1107                else
1108                  return (DOCUMENT_POSITION_FOLLOWING |
1109                          DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1110              }
1111            }
1112
1113            // Now, find the ancestor of the element
1114
thisDepth=0;
1115            for (node=thisNode; node != null; node=node.getParentNode()) {
1116                thisDepth +=1;
1117                if (node == otherNode)
1118                  {
1119                  // The other node is an ancestor of the owning element
1120
return (DOCUMENT_POSITION_CONTAINS |
1121                          DOCUMENT_POSITION_PRECEDING);
1122                  }
1123                thisAncestor = node;
1124            }
1125          }
1126        }
1127        switch (otherAncestorType) {
1128          case Node.NOTATION_NODE:
1129          case Node.ENTITY_NODE: {
1130          DocumentType JavaDoc container = thisOwnerDoc.getDoctype();
1131            if (container == this) return (DOCUMENT_POSITION_IS_CONTAINED |
1132                                          DOCUMENT_POSITION_FOLLOWING);
1133            otherNode = otherAncestor = thisOwnerDoc;
1134            break;
1135          }
1136          case Node.DOCUMENT_TYPE_NODE: {
1137            if (thisNode == otherOwnerDoc)
1138              return (DOCUMENT_POSITION_FOLLOWING |
1139                      DOCUMENT_POSITION_IS_CONTAINED);
1140            else if (otherOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc)
1141              return (DOCUMENT_POSITION_PRECEDING);
1142            break;
1143          }
1144          case Node.ATTRIBUTE_NODE: {
1145            otherDepth=0;
1146            otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
1147            for (node=otherNode; node != null; node=node.getParentNode()) {
1148                otherDepth +=1;
1149                if (node == thisNode)
1150                  // The other node is a descendent of the reference
1151
// node's element
1152
return DOCUMENT_POSITION_FOLLOWING |
1153                         DOCUMENT_POSITION_IS_CONTAINED;
1154                otherAncestor = node;
1155            }
1156
1157          }
1158        }
1159 
1160        // thisAncestor and otherAncestor must be the same at this point,
1161
// otherwise, the original nodes are disconnected
1162
if (thisAncestor != otherAncestor) {
1163          int thisAncestorNum, otherAncestorNum;
1164          thisAncestorNum = ((NodeImpl)thisAncestor).getNodeNumber();
1165          otherAncestorNum = ((NodeImpl)otherAncestor).getNodeNumber();
1166          
1167          if (thisAncestorNum > otherAncestorNum)
1168            return DOCUMENT_POSITION_DISCONNECTED |
1169                   DOCUMENT_POSITION_FOLLOWING |
1170                   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
1171          else
1172            return DOCUMENT_POSITION_DISCONNECTED |
1173                   DOCUMENT_POSITION_PRECEDING |
1174                   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
1175        }
1176
1177      
1178        // Go up the parent chain of the deeper node, until we find a node
1179
// with the same depth as the shallower node
1180

1181        if (thisDepth > otherDepth) {
1182          for (int i=0; i<thisDepth - otherDepth; i++)
1183            thisNode = thisNode.getParentNode();
1184          // Check if the node we have reached is in fact "otherNode". This can
1185
// happen in the case of attributes. In this case, otherNode
1186
// "precedes" this.
1187
if (thisNode == otherNode)
1188{
1189            return DOCUMENT_POSITION_PRECEDING;
1190          }
1191        }
1192 
1193        else {
1194          for (int i=0; i<otherDepth - thisDepth; i++)
1195            otherNode = otherNode.getParentNode();
1196          // Check if the node we have reached is in fact "thisNode". This can
1197
// happen in the case of attributes. In this case, otherNode
1198
// "follows" this.
1199
if (otherNode == thisNode)
1200            return DOCUMENT_POSITION_FOLLOWING;
1201        }
1202             
1203        // We now have nodes at the same depth in the tree. Find a common
1204
// ancestor.
1205
Node JavaDoc thisNodeP, otherNodeP;
1206        for (thisNodeP=thisNode.getParentNode(),
1207                  otherNodeP=otherNode.getParentNode();
1208             thisNodeP!=otherNodeP;) {
1209             thisNode = thisNodeP;
1210             otherNode = otherNodeP;
1211             thisNodeP = thisNodeP.getParentNode();
1212             otherNodeP = otherNodeP.getParentNode();
1213        }
1214
1215        // At this point, thisNode and otherNode are direct children of
1216
// the common ancestor.
1217
// See whether thisNode or otherNode is the leftmost
1218

1219        for (Node JavaDoc current=thisNodeP.getFirstChild();
1220                  current!=null;
1221                  current=current.getNextSibling()) {
1222               if (current==otherNode) {
1223                 return DOCUMENT_POSITION_PRECEDING;
1224               }
1225               else if (current==thisNode) {
1226                 return DOCUMENT_POSITION_FOLLOWING;
1227               }
1228        }
1229        // REVISIT: shouldn't get here. Should probably throw an
1230
// exception
1231
return 0;
1232
1233    }
1234
1235    /**
1236     * This attribute returns the text content of this node and its
1237     * descendants. When it is defined to be null, setting it has no effect.
1238     * When set, any possible children this node may have are removed and
1239     * replaced by a single <code>Text</code> node containing the string
1240     * this attribute is set to. On getting, no serialization is performed,
1241     * the returned string does not contain any markup. No whitespace
1242     * normalization is performed, the returned string does not contain the
1243     * element content whitespaces . Similarly, on setting, no parsing is
1244     * performed either, the input string is taken as pure textual content.
1245     * <br>The string returned is made of the text content of this node
1246     * depending on its type, as defined below:
1247     * <table border='1'>
1248     * <tr>
1249     * <th>Node type</th>
1250     * <th>Content</th>
1251     * </tr>
1252
1253    /**
1254     * This attribute returns the text content of this node and its
1255     * descendants. When it is defined to be null, setting it has no effect.
1256     * When set, any possible children this node may have are removed and
1257     * replaced by a single <code>Text</code> node containing the string
1258     * this attribute is set to. On getting, no serialization is performed,
1259     * the returned string does not contain any markup. No whitespace
1260     * normalization is performed, the returned string does not contain the
1261     * element content whitespaces . Similarly, on setting, no parsing is
1262     * performed either, the input string is taken as pure textual content.
1263     * <br>The string returned is made of the text content of this node
1264     * depending on its type, as defined below:
1265     * <table border='1'>
1266     * <tr>
1267     * <th>Node type</th>
1268     * <th>Content</th>
1269     * </tr>
1270     * <tr>
1271     * <td valign='top' rowspan='1' colspan='1'>
1272     * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
1273     * DOCUMENT_FRAGMENT_NODE</td>
1274     * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code>
1275     * attribute value of every child node, excluding COMMENT_NODE and
1276     * PROCESSING_INSTRUCTION_NODE nodes</td>
1277     * </tr>
1278     * <tr>
1279     * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE,
1280     * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
1281     * <td valign='top' rowspan='1' colspan='1'>
1282     * <code>nodeValue</code></td>
1283     * </tr>
1284     * <tr>
1285     * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
1286     * <td valign='top' rowspan='1' colspan='1'>
1287     * null</td>
1288     * </tr>
1289     * </table>
1290     * @exception DOMException
1291     * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
1292     * @exception DOMException
1293     * DOMSTRING_SIZE_ERR: Raised when it would return more characters than
1294     * fit in a <code>DOMString</code> variable on the implementation
1295     * platform.
1296     * @since DOM Level 3
1297     */

1298    public String JavaDoc getTextContent() throws DOMException JavaDoc {
1299        return getNodeValue(); // overriden in some subclasses
1300
}
1301
1302    // internal method taking a StringBuffer in parameter
1303
void getTextContent(StringBuffer JavaDoc buf) throws DOMException JavaDoc {
1304        String JavaDoc content = getNodeValue();
1305        if (content != null) {
1306            buf.append(content);
1307        }
1308    }
1309
1310    /**
1311     * This attribute returns the text content of this node and its
1312     * descendants. When it is defined to be null, setting it has no effect.
1313     * When set, any possible children this node may have are removed and
1314     * replaced by a single <code>Text</code> node containing the string
1315     * this attribute is set to. On getting, no serialization is performed,
1316     * the returned string does not contain any markup. No whitespace
1317     * normalization is performed, the returned string does not contain the
1318     * element content whitespaces . Similarly, on setting, no parsing is
1319     * performed either, the input string is taken as pure textual content.
1320     * <br>The string returned is made of the text content of this node
1321     * depending on its type, as defined below:
1322     * <table border='1'>
1323     * <tr>
1324     * <th>Node type</th>
1325     * <th>Content</th>
1326     * </tr>
1327     * <tr>
1328     * <td valign='top' rowspan='1' colspan='1'>
1329     * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
1330     * DOCUMENT_FRAGMENT_NODE</td>
1331     * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code>
1332     * attribute value of every child node, excluding COMMENT_NODE and
1333     * PROCESSING_INSTRUCTION_NODE nodes</td>
1334     * </tr>
1335     * <tr>
1336     * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE,
1337     * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
1338     * <td valign='top' rowspan='1' colspan='1'>
1339     * <code>nodeValue</code></td>
1340     * </tr>
1341     * <tr>
1342     * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
1343     * <td valign='top' rowspan='1' colspan='1'>
1344     * null</td>
1345     * </tr>
1346     * </table>
1347     * @exception DOMException
1348     * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
1349     * @exception DOMException
1350     * DOMSTRING_SIZE_ERR: Raised when it would return more characters than
1351     * fit in a <code>DOMString</code> variable on the implementation
1352     * platform.
1353     * @since DOM Level 3
1354     */

1355    public void setTextContent(String JavaDoc textContent)
1356        throws DOMException JavaDoc {
1357        setNodeValue(textContent);
1358    }
1359
1360    /**
1361     * Returns whether this node is the same node as the given one.
1362     * <br>This method provides a way to determine whether two
1363     * <code>Node</code> references returned by the implementation reference
1364     * the same object. When two <code>Node</code> references are references
1365     * to the same object, even if through a proxy, the references may be
1366     * used completely interchangably, such that all attributes have the
1367     * same values and calling the same DOM method on either reference
1368     * always has exactly the same effect.
1369     * @param other The node to test against.
1370     * @return Returns <code>true</code> if the nodes are the same,
1371     * <code>false</code> otherwise.
1372     * @since DOM Level 3
1373     */

1374    public boolean isSameNode(Node JavaDoc other) {
1375        // we do not use any wrapper so the answer is obvious
1376
return this == other;
1377    }
1378
1379
1380     
1381
1382    /**
1383     * DOM Level 3: Experimental
1384     * This method checks if the specified <code>namespaceURI</code> is the
1385     * default namespace or not.
1386     * @param namespaceURI The namespace URI to look for.
1387     * @return <code>true</code> if the specified <code>namespaceURI</code>
1388     * is the default namespace, <code>false</code> otherwise.
1389     * @since DOM Level 3
1390     */

1391    public boolean isDefaultNamespace(String JavaDoc namespaceURI){
1392        // REVISIT: remove casts when DOM L3 becomes REC.
1393
short type = this.getNodeType();
1394        switch (type) {
1395        case Node.ELEMENT_NODE: {
1396            String JavaDoc namespace = this.getNamespaceURI();
1397            String JavaDoc prefix = this.getPrefix();
1398            
1399            // REVISIT: is it possible that prefix is empty string?
1400
if (prefix == null || prefix.length() == 0) {
1401                if (namespaceURI == null) {
1402                    return (namespace == namespaceURI);
1403                }
1404                return namespaceURI.equals(namespace);
1405            }
1406            if (this.hasAttributes()) {
1407                ElementImpl elem = (ElementImpl)this;
1408                NodeImpl attr = (NodeImpl)elem.getAttributeNodeNS("http://www.w3.org/2000/xmlns/", "xmlns");
1409                if (attr != null) {
1410                    String JavaDoc value = attr.getNodeValue();
1411                    if (namespaceURI == null) {
1412                        return (namespace == value);
1413                    }
1414                    return namespaceURI.equals(value);
1415                }
1416            }
1417
1418            NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
1419            if (ancestor != null) {
1420                return ancestor.isDefaultNamespace(namespaceURI);
1421            }
1422            return false;
1423        }
1424        case Node.DOCUMENT_NODE:{
1425                return((NodeImpl)((Document JavaDoc)this).getDocumentElement()).isDefaultNamespace(namespaceURI);
1426            }
1427
1428        case Node.ENTITY_NODE :
1429        case Node.NOTATION_NODE:
1430        case Node.DOCUMENT_FRAGMENT_NODE:
1431        case Node.DOCUMENT_TYPE_NODE:
1432            // type is unknown
1433
return false;
1434        case Node.ATTRIBUTE_NODE:{
1435                if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
1436                    return ownerNode.isDefaultNamespace(namespaceURI);
1437
1438                }
1439                return false;
1440            }
1441        default:{
1442                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
1443                if (ancestor != null) {
1444                    return ancestor.isDefaultNamespace(namespaceURI);
1445                }
1446                return false;
1447            }
1448
1449        }
1450
1451
1452    }
1453
1454
1455    /**
1456     *
1457     * DOM Level 3 - Experimental:
1458     * Look up the prefix associated to the given namespace URI, starting from this node.
1459     *
1460     * @param namespaceURI
1461     * @return the prefix for the namespace
1462     */

1463    public String JavaDoc lookupPrefix(String JavaDoc namespaceURI){
1464        
1465        // REVISIT: When Namespaces 1.1 comes out this may not be true
1466
// Prefix can't be bound to null namespace
1467
if (namespaceURI == null) {
1468            return null;
1469        }
1470
1471        short type = this.getNodeType();
1472
1473        switch (type) {
1474        case Node.ELEMENT_NODE: {
1475
1476                String JavaDoc namespace = this.getNamespaceURI(); // to flip out children
1477
return lookupNamespacePrefix(namespaceURI, (ElementImpl)this);
1478            }
1479        case Node.DOCUMENT_NODE:{
1480                return((NodeImpl)((Document JavaDoc)this).getDocumentElement()).lookupPrefix(namespaceURI);
1481            }
1482
1483        case Node.ENTITY_NODE :
1484        case Node.NOTATION_NODE:
1485        case Node.DOCUMENT_FRAGMENT_NODE:
1486        case Node.DOCUMENT_TYPE_NODE:
1487            // type is unknown
1488
return null;
1489        case Node.ATTRIBUTE_NODE:{
1490                if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
1491                    return ownerNode.lookupPrefix(namespaceURI);
1492
1493                }
1494                return null;
1495            }
1496        default:{
1497                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
1498                if (ancestor != null) {
1499                    return ancestor.lookupPrefix(namespaceURI);
1500                }
1501                return null;
1502            }
1503
1504        }
1505    }
1506    /**
1507     * DOM Level 3 - Experimental:
1508     * Look up the namespace URI associated to the given prefix, starting from this node.
1509     * Use lookupNamespaceURI(null) to lookup the default namespace
1510     *
1511     * @param namespaceURI
1512     * @return th URI for the namespace
1513     * @since DOM Level 3
1514     */

1515    public String JavaDoc lookupNamespaceURI(String JavaDoc specifiedPrefix) {
1516        short type = this.getNodeType();
1517        switch (type) {
1518        case Node.ELEMENT_NODE : {
1519                
1520                String JavaDoc namespace = this.getNamespaceURI();
1521                String JavaDoc prefix = this.getPrefix();
1522                if (namespace !=null) {
1523                    // REVISIT: is it possible that prefix is empty string?
1524
if (specifiedPrefix== null && prefix==specifiedPrefix) {
1525                        // looking for default namespace
1526
return namespace;
1527                    } else if (prefix != null && prefix.equals(specifiedPrefix)) {
1528                        // non default namespace
1529
return namespace;
1530                    }
1531                }
1532                if (this.hasAttributes()) {
1533                    NamedNodeMap JavaDoc map = this.getAttributes();
1534                    int length = map.getLength();
1535                    for (int i=0;i<length;i++) {
1536                        Node JavaDoc attr = map.item(i);
1537                        String JavaDoc attrPrefix = attr.getPrefix();
1538                        String JavaDoc value = attr.getNodeValue();
1539                        namespace = attr.getNamespaceURI();
1540                        if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) {
1541                            // at this point we are dealing with DOM Level 2 nodes only
1542
if (specifiedPrefix == null &&
1543                                attr.getNodeName().equals("xmlns")) {
1544                                // default namespace
1545
return value;
1546                            } else if (attrPrefix !=null &&
1547                                       attrPrefix.equals("xmlns") &&
1548                                       attr.getLocalName().equals(specifiedPrefix)) {
1549                                // non default namespace
1550
return value;
1551                            }
1552                        }
1553                    }
1554                }
1555                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
1556                if (ancestor != null) {
1557                    return ancestor.lookupNamespaceURI(specifiedPrefix);
1558                }
1559
1560                return null;
1561
1562
1563            }
1564        case Node.DOCUMENT_NODE : {
1565                return((NodeImpl)((Document JavaDoc)this).getDocumentElement()).lookupNamespaceURI(specifiedPrefix);
1566            }
1567        case Node.ENTITY_NODE :
1568        case Node.NOTATION_NODE:
1569        case Node.DOCUMENT_FRAGMENT_NODE:
1570        case Node.DOCUMENT_TYPE_NODE:
1571            // type is unknown
1572
return null;
1573        case Node.ATTRIBUTE_NODE:{
1574                if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
1575                    return ownerNode.lookupNamespaceURI(specifiedPrefix);
1576
1577                }
1578                return null;
1579            }
1580        default:{
1581                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
1582                if (ancestor != null) {
1583                    return ancestor.lookupNamespaceURI(specifiedPrefix);
1584                }
1585                return null;
1586            }
1587
1588        }
1589    }
1590
1591
1592    Node JavaDoc getElementAncestor (Node JavaDoc currentNode){
1593        Node JavaDoc parent = currentNode.getParentNode();
1594        if (parent != null) {
1595            short type = parent.getNodeType();
1596            if (type == Node.ELEMENT_NODE) {
1597                return parent;
1598            }
1599            return getElementAncestor(parent);
1600        }
1601        return null;
1602    }
1603
1604    String JavaDoc lookupNamespacePrefix(String JavaDoc namespaceURI, ElementImpl el){
1605        String JavaDoc namespace = this.getNamespaceURI();
1606        // REVISIT: if no prefix is available is it null or empty string, or
1607
// could be both?
1608
String JavaDoc prefix = this.getPrefix();
1609
1610        if (namespace!=null && namespace.equals(namespaceURI)) {
1611            if (prefix != null) {
1612                String JavaDoc foundNamespace = el.lookupNamespaceURI(prefix);
1613                if (foundNamespace !=null && foundNamespace.equals(namespaceURI)) {
1614                    return prefix;
1615                }
1616
1617            }
1618        }
1619        if (this.hasAttributes()) {
1620            NamedNodeMap JavaDoc map = this.getAttributes();
1621            int length = map.getLength();
1622            for (int i=0;i<length;i++) {
1623                Node JavaDoc attr = map.item(i);
1624                String JavaDoc attrPrefix = attr.getPrefix();
1625                String JavaDoc value = attr.getNodeValue();
1626                namespace = attr.getNamespaceURI();
1627                if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) {
1628                    // DOM Level 2 nodes
1629
if (((attr.getNodeName().equals("xmlns")) ||
1630                         (attrPrefix !=null && attrPrefix.equals("xmlns")) &&
1631                         value.equals(namespaceURI))) {
1632
1633                        String JavaDoc localname= attr.getLocalName();
1634                        String JavaDoc foundNamespace = el.lookupNamespaceURI(localname);
1635                        if (foundNamespace !=null && foundNamespace.equals(namespaceURI)) {
1636                            return localname;
1637                        }
1638                    }
1639
1640
1641                }
1642            }
1643        }
1644        NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
1645
1646        if (ancestor != null) {
1647            return ancestor.lookupNamespacePrefix(namespaceURI, el);
1648        }
1649        return null;
1650    }
1651
1652    /**
1653     * Tests whether two nodes are equal.
1654     * <br>This method tests for equality of nodes, not sameness (i.e.,
1655     * whether the two nodes are references to the same object) which can be
1656     * tested with <code>Node.isSameNode</code>. All nodes that are the same
1657     * will also be equal, though the reverse may not be true.
1658     * <br>Two nodes are equal if and only if the following conditions are
1659     * satisfied: The two nodes are of the same type.The following string
1660     * attributes are equal: <code>nodeName</code>, <code>localName</code>,
1661     * <code>namespaceURI</code>, <code>prefix</code>, <code>nodeValue</code>
1662     * , <code>baseURI</code>. This is: they are both <code>null</code>, or
1663     * they have the same length and are character for character identical.
1664     * The <code>attributes</code> <code>NamedNodeMaps</code> are equal.
1665     * This is: they are both <code>null</code>, or they have the same
1666     * length and for each node that exists in one map there is a node that
1667     * exists in the other map and is equal, although not necessarily at the
1668     * same index.The <code>childNodes</code> <code>NodeLists</code> are
1669     * equal. This is: they are both <code>null</code>, or they have the
1670     * same length and contain equal nodes at the same index. This is true
1671     * for <code>Attr</code> nodes as for any other type of node. Note that
1672     * normalization can affect equality; to avoid this, nodes should be
1673     * normalized before being compared.
1674     * <br>For two <code>DocumentType</code> nodes to be equal, the following
1675     * conditions must also be satisfied: The following string attributes
1676     * are equal: <code>publicId</code>, <code>systemId</code>,
1677     * <code>internalSubset</code>.The <code>entities</code>
1678     * <code>NamedNodeMaps</code> are equal.The <code>notations</code>
1679     * <code>NamedNodeMaps</code> are equal.
1680     * <br>On the other hand, the following do not affect equality: the
1681     * <code>ownerDocument</code> attribute, the <code>specified</code>
1682     * attribute for <code>Attr</code> nodes, the
1683     * <code>isWhitespaceInElementContent</code> attribute for
1684     * <code>Text</code> nodes, as well as any user data or event listeners
1685     * registered on the nodes.
1686     * @param arg The node to compare equality with.
1687     * @param deep If <code>true</code>, recursively compare the subtrees; if
1688     * <code>false</code>, compare only the nodes themselves (and its
1689     * attributes, if it is an <code>Element</code>).
1690     * @return If the nodes, and possibly subtrees are equal,
1691     * <code>true</code> otherwise <code>false</code>.
1692     * @since DOM Level 3
1693     */

1694    public boolean isEqualNode(Node JavaDoc arg) {
1695        if (arg == this) {
1696            return true;
1697        }
1698        if (arg.getNodeType() != getNodeType()) {
1699            return false;
1700        }
1701        // in theory nodeName can't be null but better be careful
1702
// who knows what other implementations may be doing?...
1703
if (getNodeName() == null) {
1704            if (arg.getNodeName() != null) {
1705                return false;
1706            }
1707        }
1708        else if (!getNodeName().equals(arg.getNodeName())) {
1709            return false;
1710        }
1711
1712        if (getLocalName() == null) {
1713            if (arg.getLocalName() != null) {
1714                return false;
1715            }
1716        }
1717        else if (!getLocalName().equals(arg.getLocalName())) {
1718            return false;
1719        }
1720
1721        if (getNamespaceURI() == null) {
1722            if (arg.getNamespaceURI() != null) {
1723                return false;
1724            }
1725        }
1726        else if (!getNamespaceURI().equals(arg.getNamespaceURI())) {
1727            return false;
1728        }
1729
1730        if (getPrefix() == null) {
1731            if (arg.getPrefix() != null) {
1732                return false;
1733            }
1734        }
1735        else if (!getPrefix().equals(arg.getPrefix())) {
1736            return false;
1737        }
1738
1739        if (getNodeValue() == null) {
1740            if (arg.getNodeValue() != null) {
1741                return false;
1742            }
1743        }
1744        else if (!getNodeValue().equals(arg.getNodeValue())) {
1745            return false;
1746        }
1747
1748
1749        return true;
1750    }
1751
1752    /**
1753     * @since DOM Level 3
1754     */

1755    public Object JavaDoc getFeature(String JavaDoc feature, String JavaDoc version) {
1756        // we don't have any alternate node, either this node does the job
1757
// or we don't have anything that does
1758
return isSupported(feature, version) ? this : null;
1759    }
1760
1761    /**
1762     * Associate an object to a key on this node. The object can later be
1763     * retrieved from this node by calling <code>getUserData</code> with the
1764     * same key.
1765     * @param key The key to associate the object to.
1766     * @param data The object to associate to the given key, or
1767     * <code>null</code> to remove any existing association to that key.
1768     * @param handler The handler to associate to that key, or
1769     * <code>null</code>.
1770     * @return Returns the <code>DOMObject</code> previously associated to
1771     * the given key on this node, or <code>null</code> if there was none.
1772     * @since DOM Level 3
1773     */

1774    public Object JavaDoc setUserData(String JavaDoc key,
1775                              Object JavaDoc data,
1776                              UserDataHandler JavaDoc handler) {
1777        return ownerDocument().setUserData(this, key, data, handler);
1778    }
1779
1780    /**
1781     * Retrieves the object associated to a key on a this node. The object
1782     * must first have been set to this node by calling
1783     * <code>setUserData</code> with the same key.
1784     * @param key The key the object is associated to.
1785     * @return Returns the <code>DOMObject</code> associated to the given key
1786     * on this node, or <code>null</code> if there was none.
1787     * @since DOM Level 3
1788     */

1789    public Object JavaDoc getUserData(String JavaDoc key) {
1790        return ownerDocument().getUserData(this, key);
1791    }
1792
1793    protected Hashtable JavaDoc getUserDataRecord(){
1794        return ownerDocument().getUserDataRecord(this);
1795    }
1796
1797    //
1798
// Public methods
1799
//
1800

1801    /**
1802     * NON-DOM: PR-DOM-Level-1-19980818 mentions readonly nodes in conjunction
1803     * with Entities, but provides no API to support this.
1804     * <P>
1805     * Most DOM users should not touch this method. Its anticpated use
1806     * is during construction of EntityRefernces, where it will be used to
1807     * lock the contents replicated from Entity so they can't be casually
1808     * altered. It _could_ be published as a DOM extension, if desired.
1809     * <P>
1810     * Note: since we never have any children deep is meaningless here,
1811     * ParentNode overrides this behavior.
1812     * @see ParentNode
1813     *
1814     * @param readOnly True or false as desired.
1815     * @param deep If true, children are also toggled. Note that this will
1816     * not change the state of an EntityReference or its children,
1817     * which are always read-only.
1818     */

1819    public void setReadOnly(boolean readOnly, boolean deep) {
1820
1821        if (needsSyncData()) {
1822            synchronizeData();
1823        }
1824        isReadOnly(readOnly);
1825
1826    } // setReadOnly(boolean,boolean)
1827

1828    /**
1829     * NON-DOM: Returns true if this node is read-only. This is a
1830     * shallow check.
1831     */

1832    public boolean getReadOnly() {
1833
1834        if (needsSyncData()) {
1835            synchronizeData();
1836        }
1837        return isReadOnly();
1838
1839    } // getReadOnly():boolean
1840

1841    /**
1842     * NON-DOM: As an alternative to subclassing the DOM, this implementation
1843     * has been extended with the ability to attach an object to each node.
1844     * (If you need multiple objects, you can attach a collection such as a
1845     * vector or hashtable, then attach your application information to that.)
1846     * <p><b>Important Note:</b> You are responsible for removing references
1847     * to your data on nodes that are no longer used. Failure to do so will
1848     * prevent the nodes, your data is attached to, to be garbage collected
1849     * until the whole document is.
1850     *
1851     * @param data the object to store or null to remove any existing reference
1852     */

1853    public void setUserData(Object JavaDoc data) {
1854        ownerDocument().setUserData(this, data);
1855    }
1856
1857    /**
1858     * NON-DOM:
1859     * Returns the user data associated to this node.
1860     */

1861    public Object JavaDoc getUserData() {
1862        return ownerDocument().getUserData(this);
1863    }
1864
1865    //
1866
// Protected methods
1867
//
1868

1869    /**
1870     * Denotes that this node has changed.
1871     */

1872    protected void changed() {
1873        // we do not actually store this information on every node, we only
1874
// have a global indicator on the Document. Doing otherwise cost us too
1875
// much for little gain.
1876
ownerDocument().changed();
1877    }
1878
1879    /**
1880     * Returns the number of changes to this node.
1881     */

1882    protected int changes() {
1883        // we do not actually store this information on every node, we only
1884
// have a global indicator on the Document. Doing otherwise cost us too
1885
// much for little gain.
1886
return ownerDocument().changes();
1887    }
1888
1889    /**
1890     * Override this method in subclass to hook in efficient
1891     * internal data structure.
1892     */

1893    protected void synchronizeData() {
1894        // By default just change the flag to avoid calling this method again
1895
needsSyncData(false);
1896    }
1897
1898    /**
1899     * For non-child nodes, the node which "points" to this node.
1900     * For example, the owning element for an attribute
1901     */

1902    protected Node JavaDoc getContainer() {
1903       return null;
1904    }
1905
1906
1907    /*
1908     * Flags setters and getters
1909     */

1910
1911    final boolean isReadOnly() {
1912        return (flags & READONLY) != 0;
1913    }
1914
1915    final void isReadOnly(boolean value) {
1916        flags = (short) (value ? flags | READONLY : flags & ~READONLY);
1917    }
1918
1919    final boolean needsSyncData() {
1920        return (flags & SYNCDATA) != 0;
1921    }
1922
1923    final void needsSyncData(boolean value) {
1924        flags = (short) (value ? flags | SYNCDATA : flags & ~SYNCDATA);
1925    }
1926
1927    final boolean needsSyncChildren() {
1928        return (flags & SYNCCHILDREN) != 0;
1929    }
1930
1931    public final void needsSyncChildren(boolean value) {
1932        flags = (short) (value ? flags | SYNCCHILDREN : flags & ~SYNCCHILDREN);
1933    }
1934
1935    final boolean isOwned() {
1936        return (flags & OWNED) != 0;
1937    }
1938
1939    final void isOwned(boolean value) {
1940        flags = (short) (value ? flags | OWNED : flags & ~OWNED);
1941    }
1942
1943    final boolean isFirstChild() {
1944        return (flags & FIRSTCHILD) != 0;
1945    }
1946
1947    final void isFirstChild(boolean value) {
1948        flags = (short) (value ? flags | FIRSTCHILD : flags & ~FIRSTCHILD);
1949    }
1950
1951    final boolean isSpecified() {
1952        return (flags & SPECIFIED) != 0;
1953    }
1954
1955    final void isSpecified(boolean value) {
1956        flags = (short) (value ? flags | SPECIFIED : flags & ~SPECIFIED);
1957    }
1958
1959    // inconsistent name to avoid clash with public method on TextImpl
1960
final boolean internalIsIgnorableWhitespace() {
1961        return (flags & IGNORABLEWS) != 0;
1962    }
1963
1964    final void isIgnorableWhitespace(boolean value) {
1965        flags = (short) (value ? flags | IGNORABLEWS : flags & ~IGNORABLEWS);
1966    }
1967
1968    final boolean hasStringValue() {
1969        return (flags & HASSTRING) != 0;
1970    }
1971
1972    final void hasStringValue(boolean value) {
1973        flags = (short) (value ? flags | HASSTRING : flags & ~HASSTRING);
1974    }
1975
1976    final boolean isNormalized() {
1977        return (flags & NORMALIZED) != 0;
1978    }
1979
1980    final void isNormalized(boolean value) {
1981        // See if flag should propagate to parent.
1982
if (!value && isNormalized() && ownerNode != null) {
1983            ownerNode.isNormalized(false);
1984        }
1985        flags = (short) (value ? flags | NORMALIZED : flags & ~NORMALIZED);
1986    }
1987
1988    final boolean isIdAttribute() {
1989        return (flags & ID) != 0;
1990    }
1991
1992    final void isIdAttribute(boolean value) {
1993        flags = (short) (value ? flags | ID : flags & ~ID);
1994    }
1995
1996    //
1997
// Object methods
1998
//
1999

2000    /** NON-DOM method for debugging convenience. */
2001    public String JavaDoc toString() {
2002        return "["+getNodeName()+": "+getNodeValue()+"]";
2003    }
2004
2005    //
2006
// Serialization methods
2007
//
2008

2009    /** Serialize object. */
2010    private void writeObject(ObjectOutputStream JavaDoc out) throws IOException JavaDoc {
2011
2012        // synchronize data
2013
if (needsSyncData()) {
2014            synchronizeData();
2015        }
2016        // write object
2017
out.defaultWriteObject();
2018
2019    } // writeObject(ObjectOutputStream)
2020

2021} // class NodeImpl
2022
Popular Tags