KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xerces > internal > dom > NodeImpl


1  /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package com.sun.org.apache.xerces.internal.dom;
59
60 import java.io.IOException JavaDoc;
61 import java.io.ObjectOutputStream JavaDoc;
62 import java.io.Serializable JavaDoc;
63 import java.util.Hashtable JavaDoc;
64
65 import org.w3c.dom.UserDataHandler JavaDoc;
66 import org.w3c.dom.DOMException JavaDoc;
67 import org.w3c.dom.Document JavaDoc;
68 import org.w3c.dom.DocumentType JavaDoc;
69 import org.w3c.dom.NamedNodeMap JavaDoc;
70 import org.w3c.dom.Node JavaDoc;
71 import org.w3c.dom.NodeList JavaDoc;
72 import org.w3c.dom.events.Event JavaDoc;
73 import org.w3c.dom.events.EventListener JavaDoc;
74 import org.w3c.dom.events.EventTarget JavaDoc;
75
76
77 /**
78  * NodeImpl provides the basic structure of a DOM tree. It is never used
79  * directly, but instead is subclassed to add type and data
80  * information, and additional methods, appropriate to each node of
81  * the tree. Only its subclasses should be instantiated -- and those,
82  * with the exception of Document itself, only through a specific
83  * Document's factory methods.
84  * <P>
85  * The Node interface provides shared behaviors such as siblings and
86  * children, both for consistancy and so that the most common tree
87  * operations may be performed without constantly having to downcast
88  * to specific node types. When there is no obvious mapping for one of
89  * these queries, it will respond with null.
90  * Note that the default behavior is that children are forbidden. To
91  * permit them, the subclass ParentNode overrides several methods.
92  * <P>
93  * NodeImpl also implements NodeList, so it can return itself in
94  * response to the getChildNodes() query. This eliminiates the need
95  * for a separate ChildNodeList object. Note that this is an
96  * IMPLEMENTATION DETAIL; applications should _never_ assume that
97  * this identity exists.
98  * <P>
99  * All nodes in a single document must originate
100  * in that document. (Note that this is much tighter than "must be
101  * same implementation") Nodes are all aware of their ownerDocument,
102  * and attempts to mismatch will throw WRONG_DOCUMENT_ERR.
103  * <P>
104  * However, to save memory not all nodes always have a direct reference
105  * to their ownerDocument. When a node is owned by another node it relies
106  * on its owner to store its ownerDocument. Parent nodes always store it
107  * though, so there is never more than one level of indirection.
108  * And when a node doesn't have an owner, ownerNode refers to its
109  * ownerDocument.
110  * <p>
111  * This class doesn't directly support mutation events, however, it still
112  * implements the EventTarget interface and forward all related calls to the
113  * document so that the document class do so.
114  *
115  * @author Arnaud Le Hors, IBM
116  * @author Joe Kesselman, IBM
117  * @version $Id: NodeImpl.java,v 1.71 2004/01/16 16:23:50 elena Exp $
118  * @since PR-DOM-Level-1-19980818.
119  */

120 public abstract class NodeImpl
121     implements Node JavaDoc, NodeList JavaDoc, EventTarget JavaDoc, Cloneable JavaDoc, Serializable JavaDoc{
122
123     //
124
// Constants
125
//
126

127
128     // TreePosition Constants.
129
// Taken from DOM L3 Node interface.
130
/**
131      * The node precedes the reference node.
132      */

133     public static final short TREE_POSITION_PRECEDING = 0x01;
134     /**
135      * The node follows the reference node.
136      */

137     public static final short TREE_POSITION_FOLLOWING = 0x02;
138     /**
139      * The node is an ancestor of the reference node.
140      */

141     public static final short TREE_POSITION_ANCESTOR = 0x04;
142     /**
143      * The node is a descendant of the reference node.
144      */

145     public static final short TREE_POSITION_DESCENDANT = 0x08;
146     /**
147      * The two nodes have an equivalent position. This is the case of two
148      * attributes that have the same <code>ownerElement</code>, and two
149      * nodes that are the same.
150      */

151     public static final short TREE_POSITION_EQUIVALENT = 0x10;
152     /**
153      * The two nodes are the same. Two nodes that are the same have an
154      * equivalent position, though the reverse may not be true.
155      */

156     public static final short TREE_POSITION_SAME_NODE = 0x20;
157     /**
158      * The two nodes are disconnected, they do not have any common ancestor.
159      * This is the case of two nodes that are not in the same document.
160      */

161     public static final short TREE_POSITION_DISCONNECTED = 0x00;
162
163
164     // DocumentPosition
165
public static final short DOCUMENT_POSITION_DISCONNECTED = 0x01;
166     public static final short DOCUMENT_POSITION_PRECEDING = 0x02;
167     public static final short DOCUMENT_POSITION_FOLLOWING = 0x04;
168     public static final short DOCUMENT_POSITION_CONTAINS = 0x08;
169     public static final short DOCUMENT_POSITION_IS_CONTAINED = 0x10;
170     public static final short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
171
172     /** Serialization version. */
173     static final long serialVersionUID = -6316591992167219696L;
174
175     // public
176

177     /** Element definition node type. */
178     public static final short ELEMENT_DEFINITION_NODE = 21;
179
180     //
181
// Data
182
//
183

184     // links
185

186     protected NodeImpl ownerNode; // typically the parent but not always!
187

188     // data
189

190     protected short flags;
191
192     protected final static short READONLY = 0x1<<0;
193     protected final static short SYNCDATA = 0x1<<1;
194     protected final static short SYNCCHILDREN = 0x1<<2;
195     protected final static short OWNED = 0x1<<3;
196     protected final static short FIRSTCHILD = 0x1<<4;
197     protected final static short SPECIFIED = 0x1<<5;
198     protected final static short IGNORABLEWS = 0x1<<6;
199     protected final static short HASSTRING = 0x1<<7;
200     protected final static short NORMALIZED = 0x1<<8;
201     protected final static short ID = 0x1<<9;
202
203     //
204
// Constructors
205
//
206

207     /**
208      * No public constructor; only subclasses of Node should be
209      * instantiated, and those normally via a Document's factory methods
210      * <p>
211      * Every Node knows what Document it belongs to.
212      */

213     protected NodeImpl(CoreDocumentImpl ownerDocument) {
214         // as long as we do not have any owner, ownerNode is our ownerDocument
215
ownerNode = ownerDocument;
216     } // <init>(CoreDocumentImpl)
217

218     /** Constructor for serialization. */
219     public NodeImpl() {}
220
221     //
222
// Node methods
223
//
224

225     /**
226      * A short integer indicating what type of node this is. The named
227      * constants for this value are defined in the org.w3c.dom.Node interface.
228      */

229     public abstract short getNodeType();
230
231     /**
232      * the name of this node.
233      */

234     public abstract String JavaDoc getNodeName();
235     
236     /**
237      * Returns the node value.
238      * @throws DOMException(DOMSTRING_SIZE_ERR)
239      */

240     public String JavaDoc getNodeValue()
241         throws DOMException JavaDoc {
242         return null; // overridden in some subclasses
243
}
244
245     /**
246      * Sets the node value.
247      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR)
248      */

249     public void setNodeValue(String JavaDoc x)
250         throws DOMException JavaDoc {
251         // Default behavior is to do nothing, overridden in some subclasses
252
}
253
254     /**
255      * Adds a child node to the end of the list of children for this node.
256      * Convenience shorthand for insertBefore(newChild,null).
257      * @see #insertBefore(Node, Node)
258      * <P>
259      * By default we do not accept any children, ParentNode overrides this.
260      * @see ParentNode
261      *
262      * @return newChild, in its new state (relocated, or emptied in the case of
263      * DocumentNode.)
264      *
265      * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
266      * type that shouldn't be a child of this node.
267      *
268      * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
269      * different owner document than we do.
270      *
271      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
272      * read-only.
273      */

274     public Node JavaDoc appendChild(Node JavaDoc newChild) throws DOMException JavaDoc {
275         return insertBefore(newChild, null);
276     }
277
278     /**
279      * Returns a duplicate of a given node. You can consider this a
280      * generic "copy constructor" for nodes. The newly returned object should
281      * be completely independent of the source object's subtree, so changes
282      * in one after the clone has been made will not affect the other.
283      * <P>
284      * Note: since we never have any children deep is meaningless here,
285      * ParentNode overrides this behavior.
286      * @see ParentNode
287      *
288      * <p>
289      * Example: Cloning a Text node will copy both the node and the text it
290      * contains.
291      * <p>
292      * Example: Cloning something that has children -- Element or Attr, for
293      * example -- will _not_ clone those children unless a "deep clone"
294      * has been requested. A shallow clone of an Attr node will yield an
295      * empty Attr of the same name.
296      * <p>
297      * NOTE: Clones will always be read/write, even if the node being cloned
298      * is read-only, to permit applications using only the DOM API to obtain
299      * editable copies of locked portions of the tree.
300      */

301     public Node JavaDoc cloneNode(boolean deep) {
302
303         if (needsSyncData()) {
304             synchronizeData();
305     }
306         
307         NodeImpl newnode;
308         try {
309             newnode = (NodeImpl)clone();
310         }
311         catch (CloneNotSupportedException JavaDoc e) {
312             // if we get here we have an error in our program we may as well
313
// be vocal about it, so that people can take appropriate action.
314
throw new RuntimeException JavaDoc("**Internal Error**" + e);
315         }
316         
317         // Need to break the association w/ original kids
318
newnode.ownerNode = ownerDocument();
319         newnode.isOwned(false);
320
321         // By default we make all clones readwrite,
322
// this is overriden in readonly subclasses
323
newnode.isReadOnly(false);
324
325         ownerDocument().callUserDataHandlers(this, newnode,
326                                              UserDataHandler.NODE_CLONED);
327
328         return newnode;
329
330     } // cloneNode(boolean):Node
331

332     /**
333      * Find the Document that this Node belongs to (the document in
334      * whose context the Node was created). The Node may or may not
335      * currently be part of that Document's actual contents.
336      */

337     public Document JavaDoc getOwnerDocument() {
338         // if we have an owner simply forward the request
339
// otherwise ownerNode is our ownerDocument
340
if (isOwned()) {
341             return ownerNode.ownerDocument();
342         } else {
343             return (Document JavaDoc) ownerNode;
344         }
345     }
346
347     /**
348      * same as above but returns internal type and this one is not overridden
349      * by CoreDocumentImpl to return null
350      */

351     CoreDocumentImpl ownerDocument() {
352         // if we have an owner simply forward the request
353
// otherwise ownerNode is our ownerDocument
354
if (isOwned()) {
355             return ownerNode.ownerDocument();
356         } else {
357             return (CoreDocumentImpl) ownerNode;
358         }
359     }
360
361     /**
362      * NON-DOM
363      * set the ownerDocument of this node
364      */

365     void setOwnerDocument(CoreDocumentImpl doc) {
366         if (needsSyncData()) {
367             synchronizeData();
368         }
369         // if we have an owner we rely on it to have it right
370
// otherwise ownerNode is our ownerDocument
371
if (!isOwned()) {
372             ownerNode = doc;
373         }
374     }
375
376     /**
377      * Returns the node number
378      */

379     protected int getNodeNumber() {
380         int nodeNumber;
381         CoreDocumentImpl cd = (CoreDocumentImpl)(this.getOwnerDocument());
382         nodeNumber = cd.getNodeNumber(this);
383         return nodeNumber;
384     }
385
386     /**
387      * Obtain the DOM-tree parent of this node, or null if it is not
388      * currently active in the DOM tree (perhaps because it has just been
389      * created or removed). Note that Document, DocumentFragment, and
390      * Attribute will never have parents.
391      */

392     public Node JavaDoc getParentNode() {
393         return null; // overriden by ChildNode
394
}
395
396     /*
397      * same as above but returns internal type
398      */

399     NodeImpl parentNode() {
400         return null;
401     }
402
403     /** The next child of this node's parent, or null if none */
404     public Node JavaDoc getNextSibling() {
405         return null; // default behavior, overriden in ChildNode
406
}
407
408     /** The previous child of this node's parent, or null if none */
409     public Node JavaDoc getPreviousSibling() {
410         return null; // default behavior, overriden in ChildNode
411
}
412
413     ChildNode previousSibling() {
414         return null; // default behavior, overriden in ChildNode
415
}
416
417     /**
418      * Return the collection of attributes associated with this node,
419      * or null if none. At this writing, Element is the only type of node
420      * which will ever have attributes.
421      *
422      * @see ElementImpl
423      */

424     public NamedNodeMap JavaDoc getAttributes() {
425         return null; // overridden in ElementImpl
426
}
427
428     /**
429      * Returns whether this node (if it is an element) has any attributes.
430      * @return <code>true</code> if this node has any attributes,
431      * <code>false</code> otherwise.
432      * @since DOM Level 2
433      * @see ElementImpl
434      */

435     public boolean hasAttributes() {
436         return false; // overridden in ElementImpl
437
}
438
439     /**
440      * Test whether this node has any children. Convenience shorthand
441      * for (Node.getFirstChild()!=null)
442      * <P>
443      * By default we do not have any children, ParentNode overrides this.
444      * @see ParentNode
445      */

446     public boolean hasChildNodes() {
447         return false;
448     }
449
450     /**
451      * Obtain a NodeList enumerating all children of this node. If there
452      * are none, an (initially) empty NodeList is returned.
453      * <p>
454      * NodeLists are "live"; as children are added/removed the NodeList
455      * will immediately reflect those changes. Also, the NodeList refers
456      * to the actual nodes, so changes to those nodes made via the DOM tree
457      * will be reflected in the NodeList and vice versa.
458      * <p>
459      * In this implementation, Nodes implement the NodeList interface and
460      * provide their own getChildNodes() support. Other DOMs may solve this
461      * differently.
462      */

463     public NodeList JavaDoc getChildNodes() {
464         return this;
465     }
466
467     /** The first child of this Node, or null if none.
468      * <P>
469      * By default we do not have any children, ParentNode overrides this.
470      * @see ParentNode
471      */

472     public Node JavaDoc getFirstChild() {
473         return null;
474     }
475
476     /** The first child of this Node, or null if none.
477      * <P>
478      * By default we do not have any children, ParentNode overrides this.
479      * @see ParentNode
480      */

481     public Node JavaDoc getLastChild() {
482     return null;
483     }
484
485     /**
486      * Move one or more node(s) to our list of children. Note that this
487      * implicitly removes them from their previous parent.
488      * <P>
489      * By default we do not accept any children, ParentNode overrides this.
490      * @see ParentNode
491      *
492      * @param newChild The Node to be moved to our subtree. As a
493      * convenience feature, inserting a DocumentNode will instead insert
494      * all its children.
495      *
496      * @param refChild Current child which newChild should be placed
497      * immediately before. If refChild is null, the insertion occurs
498      * after all existing Nodes, like appendChild().
499      *
500      * @return newChild, in its new state (relocated, or emptied in the case of
501      * DocumentNode.)
502      *
503      * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
504      * type that shouldn't be a child of this node, or if newChild is an
505      * ancestor of this node.
506      *
507      * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
508      * different owner document than we do.
509      *
510      * @throws DOMException(NOT_FOUND_ERR) if refChild is not a child of
511      * this node.
512      *
513      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
514      * read-only.
515      */

516     public Node JavaDoc insertBefore(Node JavaDoc newChild, Node JavaDoc refChild)
517     throws DOMException JavaDoc {
518     throw new DOMException JavaDoc(DOMException.HIERARCHY_REQUEST_ERR,
519               DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
520                  "HIERARCHY_REQUEST_ERR", null));
521     }
522
523     /**
524      * Remove a child from this Node. The removed child's subtree
525      * remains intact so it may be re-inserted elsewhere.
526      * <P>
527      * By default we do not have any children, ParentNode overrides this.
528      * @see ParentNode
529      *
530      * @return oldChild, in its new state (removed).
531      *
532      * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
533      * this node.
534      *
535      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
536      * read-only.
537      */

538     public Node JavaDoc removeChild(Node JavaDoc oldChild)
539         throws DOMException JavaDoc {
540     throw new DOMException JavaDoc(DOMException.NOT_FOUND_ERR,
541               DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
542                  "NOT_FOUND_ERR", null));
543     }
544
545     /**
546      * Make newChild occupy the location that oldChild used to
547      * have. Note that newChild will first be removed from its previous
548      * parent, if any. Equivalent to inserting newChild before oldChild,
549      * then removing oldChild.
550      * <P>
551      * By default we do not have any children, ParentNode overrides this.
552      * @see ParentNode
553      *
554      * @return oldChild, in its new state (removed).
555      *
556      * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
557      * type that shouldn't be a child of this node, or if newChild is
558      * one of our ancestors.
559      *
560      * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
561      * different owner document than we do.
562      *
563      * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
564      * this node.
565      *
566      * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
567      * read-only.
568      */

569     public Node JavaDoc replaceChild(Node JavaDoc newChild, Node JavaDoc oldChild)
570         throws DOMException JavaDoc {
571     throw new DOMException JavaDoc(DOMException.HIERARCHY_REQUEST_ERR,
572               DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
573                  "HIERARCHY_REQUEST_ERR", null));
574     }
575
576     //
577
// NodeList methods
578
//
579

580     /**
581      * NodeList method: Count the immediate children of this node
582      * <P>
583      * By default we do not have any children, ParentNode overrides this.
584      * @see ParentNode
585      *
586      * @return int
587      */

588     public int getLength() {
589     return 0;
590     }
591
592     /**
593      * NodeList method: Return the Nth immediate child of this node, or
594      * null if the index is out of bounds.
595      * <P>
596      * By default we do not have any children, ParentNode overrides this.
597      * @see ParentNode
598      *
599      * @return org.w3c.dom.Node
600      * @param Index int
601      */

602     public Node JavaDoc item(int index) {
603     return null;
604     }
605
606     //
607
// DOM2: methods, getters, setters
608
//
609

610     /**
611      * Puts all <code>Text</code> nodes in the full depth of the sub-tree
612      * underneath this <code>Node</code>, including attribute nodes, into a
613      * "normal" form where only markup (e.g., tags, comments, processing
614      * instructions, CDATA sections, and entity references) separates
615      * <code>Text</code> nodes, i.e., there are no adjacent <code>Text</code>
616      * nodes. This can be used to ensure that the DOM view of a document is
617      * the same as if it were saved and re-loaded, and is useful when
618      * operations (such as XPointer lookups) that depend on a particular
619      * document tree structure are to be used.In cases where the document
620      * contains <code>CDATASections</code>, the normalize operation alone may
621      * not be sufficient, since XPointers do not differentiate between
622      * <code>Text</code> nodes and <code>CDATASection</code> nodes.
623      * <p>
624      * Note that this implementation simply calls normalize() on this Node's
625      * children. It is up to implementors or Node to override normalize()
626      * to take action.
627      */

628     public void normalize() {
629     /* by default we do not have any children,
630        ParentNode overrides this behavior */

631     }
632
633     /**
634      * Introduced in DOM Level 2. <p>
635      * Tests whether the DOM implementation implements a specific feature and
636      * that feature is supported by this node.
637      * @param feature The package name of the feature to test. This is the same
638      * name as what can be passed to the method hasFeature on
639      * DOMImplementation.
640      * @param version This is the version number of the package name to
641      * test. In Level 2, version 1, this is the string "2.0". If the version is
642      * not specified, supporting any version of the feature will cause the
643      * method to return true.
644      * @return boolean Returns true if this node defines a subtree within which
645      * the specified feature is supported, false otherwise.
646      * @since WD-DOM-Level-2-19990923
647      */

648     public boolean isSupported(String JavaDoc feature, String JavaDoc version)
649     {
650         return ownerDocument().getImplementation().hasFeature(feature,
651                                                               version);
652     }
653
654     /**
655      * Introduced in DOM Level 2. <p>
656      *
657      * The namespace URI of this node, or null if it is unspecified. When this
658      * node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE, this is
659      * always null and setting it has no effect. <p>
660      *
661      * This is not a computed value that is the result of a namespace lookup
662      * based on an examination of the namespace declarations in scope. It is
663      * merely the namespace URI given at creation time.<p>
664      *
665      * For nodes created with a DOM Level 1 method, such as createElement
666      * from the Document interface, this is null.
667      * @since WD-DOM-Level-2-19990923
668      * @see AttrNSImpl
669      * @see ElementNSImpl
670      */

671     public String JavaDoc getNamespaceURI()
672     {
673         return null;
674     }
675
676     /**
677      * Introduced in DOM Level 2. <p>
678      *
679      * The namespace prefix of this node, or null if it is unspecified. When
680      * this node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE this
681      * is always null and setting it has no effect.<p>
682      *
683      * For nodes created with a DOM Level 1 method, such as createElement
684      * from the Document interface, this is null. <p>
685      *
686      * @since WD-DOM-Level-2-19990923
687      * @see AttrNSImpl
688      * @see ElementNSImpl
689      */

690     public String JavaDoc getPrefix()
691     {
692         return null;
693     }
694
695     /**
696      * Introduced in DOM Level 2. <p>
697      *
698      * The namespace prefix of this node, or null if it is unspecified. When
699      * this node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE
700      * this is always null and setting it has no effect.<p>
701      *
702      * For nodes created with a DOM Level 1 method, such as createElement from
703      * the Document interface, this is null.<p>
704      *
705      * Note that setting this attribute changes the nodeName attribute, which
706      * holds the qualified name, as well as the tagName and name attributes of
707      * the Element and Attr interfaces, when applicable.<p>
708      *
709      * @throws INVALID_CHARACTER_ERR Raised if the specified
710      * prefix contains an invalid character.
711      *
712      * @since WD-DOM-Level-2-19990923
713      * @see AttrNSImpl
714      * @see ElementNSImpl
715      */

716     public void setPrefix(String JavaDoc prefix)
717         throws DOMException JavaDoc
718     {
719     throw new DOMException JavaDoc(DOMException.NAMESPACE_ERR,
720               DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
721                  "NAMESPACE_ERR", null));
722     }
723
724     /**
725      * Introduced in DOM Level 2. <p>
726      *
727      * Returns the local part of the qualified name of this node.
728      * For nodes created with a DOM Level 1 method, such as createElement
729      * from the Document interface, and for nodes of any type other than
730      * ELEMENT_NODE and ATTRIBUTE_NODE this is the same as the nodeName
731      * attribute.
732      * @since WD-DOM-Level-2-19990923
733      * @see AttrNSImpl
734      * @see ElementNSImpl
735      */

736     public String JavaDoc getLocalName()
737     {
738         return null;
739     }
740     
741     //
742
// EventTarget support
743
//
744

745     public void addEventListener(String JavaDoc type, EventListener JavaDoc listener,
746                                  boolean useCapture) {
747         // simply forward to Document
748
ownerDocument().addEventListener(this, type, listener, useCapture);
749     }
750
751     public void removeEventListener(String JavaDoc type, EventListener JavaDoc listener,
752                                     boolean useCapture) {
753         // simply forward to Document
754
ownerDocument().removeEventListener(this, type, listener, useCapture);
755     }
756
757     public boolean dispatchEvent(Event JavaDoc event) {
758         // simply forward to Document
759
return ownerDocument().dispatchEvent(this, event);
760     }
761
762     //
763
// Public DOM Level 3 methods
764
//
765

766     /**
767      * The absolute base URI of this node or <code>null</code> if undefined.
768      * This value is computed according to . However, when the
769      * <code>Document</code> supports the feature "HTML" , the base URI is
770      * computed using first the value of the href attribute of the HTML BASE
771      * element if any, and the value of the <code>documentURI</code>
772      * attribute from the <code>Document</code> interface otherwise.
773      * <br> When the node is an <code>Element</code>, a <code>Document</code>
774      * or a a <code>ProcessingInstruction</code>, this attribute represents
775      * the properties [base URI] defined in . When the node is a
776      * <code>Notation</code>, an <code>Entity</code>, or an
777      * <code>EntityReference</code>, this attribute represents the
778      * properties [declaration base URI] in the . How will this be affected
779      * by resolution of relative namespace URIs issue?It's not.Should this
780      * only be on Document, Element, ProcessingInstruction, Entity, and
781      * Notation nodes, according to the infoset? If not, what is it equal to
782      * on other nodes? Null? An empty string? I think it should be the
783      * parent's.No.Should this be read-only and computed or and actual
784      * read-write attribute?Read-only and computed (F2F 19 Jun 2000 and
785      * teleconference 30 May 2001).If the base HTML element is not yet
786      * attached to a document, does the insert change the Document.baseURI?
787      * Yes. (F2F 26 Sep 2001)
788      * @since DOM Level 3
789      */

790     public String JavaDoc getBaseURI() {
791         return null;
792     }
793
794     /**
795      * Compares a node with this node with regard to their position in the
796      * tree and according to the document order. This order can be extended
797      * by module that define additional types of nodes.
798      * @param other The node to compare against this node.
799      * @return Returns how the given node is positioned relatively to this
800      * node.
801      * @since DOM Level 3
802      * @deprecated
803      */

804     public short compareTreePosition(Node JavaDoc other) {
805         // Questions of clarification for this method - to be answered by the
806
// DOM WG. Current assumptions listed - LM
807
//
808
// 1. How do ENTITY nodes compare?
809
// Current assumption: TREE_POSITION_DISCONNECTED, as ENTITY nodes
810
// aren't really 'in the tree'
811
//
812
// 2. How do NOTATION nodes compare?
813
// Current assumption: TREE_POSITION_DISCONNECTED, as NOTATION nodes
814
// aren't really 'in the tree'
815
//
816
// 3. Are TREE_POSITION_ANCESTOR and TREE_POSITION_DESCENDANT
817
// only relevant for nodes that are "part of the document tree"?
818
// <outer>
819
// <inner myattr="true"/>
820
// </outer>
821
// Is the element node "outer" considered an ancestor of "myattr"?
822
// Current assumption: No.
823
//
824
// 4. How do children of ATTRIBUTE nodes compare (with eachother, or
825
// with children of other attribute nodes with the same element)
826
// Current assumption: Children of ATTRIBUTE nodes are treated as if
827
// they they are the attribute node itself, unless the 2 nodes
828
// are both children of the same attribute.
829
//
830
// 5. How does an ENTITY_REFERENCE node compare with it's children?
831
// Given the DOM, it should precede its children as an ancestor.
832
// Given "document order", does it represent the same position?
833
// Current assumption: An ENTITY_REFERENCE node is an ancestor of its
834
// children.
835
//
836
// 6. How do children of a DocumentFragment compare?
837
// Current assumption: If both nodes are part of the same document
838
// fragment, there are compared as if they were part of a document.
839

840         
841         // If the nodes are the same...
842
if (this==other)
843           return (TREE_POSITION_SAME_NODE | TREE_POSITION_EQUIVALENT);
844         
845         // If either node is of type ENTITY or NOTATION, compare as disconnected
846
short thisType = this.getNodeType();
847         short otherType = other.getNodeType();
848
849         // If either node is of type ENTITY or NOTATION, compare as disconnected
850
if (thisType == Node.ENTITY_NODE ||
851             thisType == Node.NOTATION_NODE ||
852             otherType == Node.ENTITY_NODE ||
853             otherType == Node.NOTATION_NODE ) {
854           return TREE_POSITION_DISCONNECTED;
855         }
856
857         // Find the ancestor of each node, and the distance each node is from
858
// its ancestor.
859
// During this traversal, look for ancestor/descendent relationships
860
// between the 2 nodes in question.
861
// We do this now, so that we get this info correct for attribute nodes
862
// and their children.
863

864         Node JavaDoc node;
865         Node JavaDoc thisAncestor = this;
866         Node JavaDoc otherAncestor = other;
867         int thisDepth=0;
868         int otherDepth=0;
869         for (node=this; node != null; node = node.getParentNode()) {
870             thisDepth +=1;
871             if (node == other)
872               // The other node is an ancestor of this one.
873
return (TREE_POSITION_ANCESTOR | TREE_POSITION_PRECEDING);
874             thisAncestor = node;
875         }
876
877         for (node=other; node!=null; node=node.getParentNode()) {
878             otherDepth +=1;
879             if (node == this)
880               // The other node is a descendent of the reference node.
881
return (TREE_POSITION_DESCENDANT | TREE_POSITION_FOLLOWING);
882             otherAncestor = node;
883         }
884         
885        
886         Node JavaDoc thisNode = this;
887         Node JavaDoc otherNode = other;
888
889         int thisAncestorType = thisAncestor.getNodeType();
890         int otherAncestorType = otherAncestor.getNodeType();
891
892         // if the ancestor is an attribute, get owning element.
893
// we are now interested in the owner to determine position.
894

895         if (thisAncestorType == Node.ATTRIBUTE_NODE) {
896            thisNode = ((AttrImpl)thisAncestor).getOwnerElement();
897         }
898         if (otherAncestorType == Node.ATTRIBUTE_NODE) {
899            otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
900         }
901
902         // Before proceeding, we should check if both ancestor nodes turned
903
// out to be attributes for the same element
904
if (thisAncestorType == Node.ATTRIBUTE_NODE &&
905             otherAncestorType == Node.ATTRIBUTE_NODE &&
906             thisNode==otherNode)
907             return TREE_POSITION_EQUIVALENT;
908
909         // Now, find the ancestor of the owning element, if the original
910
// ancestor was an attribute
911

912         // Note: the following 2 loops are quite close to the ones above.
913
// May want to common them up. LM.
914
if (thisAncestorType == Node.ATTRIBUTE_NODE) {
915             thisDepth=0;
916             for (node=thisNode; node != null; node=node.getParentNode()) {
917                 thisDepth +=1;
918                 if (node == otherNode)
919                   // The other node is an ancestor of the owning element
920
{
921                   return TREE_POSITION_PRECEDING;
922                   }
923                 thisAncestor = node;
924             }
925         }
926
927         // Now, find the ancestor of the owning element, if the original
928
// ancestor was an attribute
929
if (otherAncestorType == Node.ATTRIBUTE_NODE) {
930             otherDepth=0;
931             for (node=otherNode; node != null; node=node.getParentNode()) {
932                 otherDepth +=1;
933                 if (node == thisNode)
934                   // The other node is a descendent of the reference
935
// node's element
936
return TREE_POSITION_FOLLOWING;
937                 otherAncestor = node;
938             }
939         }
940
941         // thisAncestor and otherAncestor must be the same at this point,
942
// otherwise, we are not in the same tree or document fragment
943
if (thisAncestor != otherAncestor)
944           return TREE_POSITION_DISCONNECTED;
945
946       
947         // Go up the parent chain of the deeper node, until we find a node
948
// with the same depth as the shallower node
949

950         if (thisDepth > otherDepth) {
951           for (int i=0; i<thisDepth - otherDepth; i++)
952             thisNode = thisNode.getParentNode();
953           // Check if the node we have reached is in fact "otherNode". This can
954
// happen in the case of attributes. In this case, otherNode
955
// "precedes" this.
956
if (thisNode == otherNode)
957             return TREE_POSITION_PRECEDING;
958         }
959  
960         else {
961           for (int i=0; i<otherDepth - thisDepth; i++)
962             otherNode = otherNode.getParentNode();
963           // Check if the node we have reached is in fact "thisNode". This can
964
// happen in the case of attributes. In this case, otherNode
965
// "follows" this.
966
if (otherNode == thisNode)
967             return TREE_POSITION_FOLLOWING;
968         }
969              
970         // We now have nodes at the same depth in the tree. Find a common
971
// ancestor.
972
Node JavaDoc thisNodeP, otherNodeP;
973         for (thisNodeP=thisNode.getParentNode(),
974                   otherNodeP=otherNode.getParentNode();
975              thisNodeP!=otherNodeP;) {
976              thisNode = thisNodeP;
977              otherNode = otherNodeP;
978              thisNodeP = thisNodeP.getParentNode();
979              otherNodeP = otherNodeP.getParentNode();
980         }
981
982         // At this point, thisNode and otherNode are direct children of
983
// the common ancestor.
984
// See whether thisNode or otherNode is the leftmost
985

986         for (Node JavaDoc current=thisNodeP.getFirstChild();
987                   current!=null;
988                   current=current.getNextSibling()) {
989                if (current==otherNode) {
990                  return TREE_POSITION_PRECEDING;
991                }
992                else if (current==thisNode) {
993                  return TREE_POSITION_FOLLOWING;
994                }
995         }
996         // REVISIT: shouldn't get here. Should probably throw an
997
// exception
998
return 0;
999
1000    }
1001    /**
1002     * Compares a node with this node with regard to their position in the
1003     * document.
1004     * @param other The node to compare against this node.
1005     * @return Returns how the given node is positioned relatively to this
1006     * node.
1007     * @since DOM Level 3
1008     */

1009    public short compareDocumentPosition(Node JavaDoc other) throws DOMException JavaDoc {
1010
1011        // If the nodes are the same, no flags should be set
1012
if (this==other)
1013          return 0;
1014
1015        // check if other is from a different implementation
1016
try {
1017            NodeImpl node = (NodeImpl) other;
1018        } catch (ClassCastException JavaDoc e) {
1019            // other comes from a different implementation
1020
String JavaDoc msg = DOMMessageFormatter.formatMessage(
1021               DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
1022            throw new DOMException JavaDoc(DOMException.NOT_SUPPORTED_ERR, msg);
1023        }
1024
1025        Document JavaDoc thisOwnerDoc, otherOwnerDoc;
1026        // get the respective Document owners.
1027
if (this.getNodeType() == Node.DOCUMENT_NODE)
1028          thisOwnerDoc = (Document JavaDoc)this;
1029        else
1030          thisOwnerDoc = this.getOwnerDocument();
1031        if (other.getNodeType() == Node.DOCUMENT_NODE)
1032          otherOwnerDoc = (Document JavaDoc)other;
1033        else
1034          otherOwnerDoc = other.getOwnerDocument();
1035
1036        // If from different documents, we know they are disconnected.
1037
// and have an implementation dependent order
1038
if (thisOwnerDoc != otherOwnerDoc &&
1039            thisOwnerDoc !=null &&
1040            otherOwnerDoc !=null)
1041 {
1042          int otherDocNum = ((CoreDocumentImpl)otherOwnerDoc).getNodeNumber();
1043          int thisDocNum = ((CoreDocumentImpl)thisOwnerDoc).getNodeNumber();
1044          if (otherDocNum > thisDocNum)
1045            return DOCUMENT_POSITION_DISCONNECTED |
1046                   DOCUMENT_POSITION_FOLLOWING |
1047                   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
1048          else
1049            return DOCUMENT_POSITION_DISCONNECTED |
1050                   DOCUMENT_POSITION_PRECEDING |
1051                   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
1052                  
1053        }
1054     
1055        // Find the ancestor of each node, and the distance each node is from
1056
// its ancestor.
1057
// During this traversal, look for ancestor/descendent relationships
1058
// between the 2 nodes in question.
1059
// We do this now, so that we get this info correct for attribute nodes
1060
// and their children.
1061

1062        Node JavaDoc node;
1063        Node JavaDoc thisAncestor = this;
1064        Node JavaDoc otherAncestor = other;
1065       
1066        int thisDepth=0;
1067        int otherDepth=0;
1068        for (node=this; node != null; node = node.getParentNode()) {
1069            thisDepth +=1;
1070            if (node == other)
1071              // The other node is an ancestor of this one.
1072
return (DOCUMENT_POSITION_CONTAINS |
1073                      DOCUMENT_POSITION_PRECEDING);
1074            thisAncestor = node;
1075        }
1076
1077        for (node=other; node!=null; node=node.getParentNode()) {
1078            otherDepth +=1;
1079            if (node == this)
1080              // The other node is a descendent of the reference node.
1081
return (DOCUMENT_POSITION_IS_CONTAINED |
1082                      DOCUMENT_POSITION_FOLLOWING);
1083            otherAncestor = node;
1084        }
1085        
1086       
1087
1088        int thisAncestorType = thisAncestor.getNodeType();
1089        int otherAncestorType = otherAncestor.getNodeType();
1090        Node JavaDoc thisNode = this;
1091        Node JavaDoc otherNode = other;
1092
1093        // Special casing for ENTITY, NOTATION, DOCTYPE and ATTRIBUTES
1094
// LM: should rewrite this.
1095
switch (thisAncestorType) {
1096          case Node.NOTATION_NODE:
1097          case Node.ENTITY_NODE: {
1098            DocumentType JavaDoc container = thisOwnerDoc.getDoctype();
1099            if (container == otherAncestor) return
1100                   (DOCUMENT_POSITION_CONTAINS | DOCUMENT_POSITION_PRECEDING);
1101            switch (otherAncestorType) {
1102              case Node.NOTATION_NODE:
1103              case Node.ENTITY_NODE: {
1104                if (thisAncestorType != otherAncestorType)
1105                 // the nodes are of different types
1106
return ((thisAncestorType>otherAncestorType) ?
1107                    DOCUMENT_POSITION_PRECEDING:DOCUMENT_POSITION_FOLLOWING);
1108                else {
1109                 // the nodes are of the same type. Find order.
1110
if (thisAncestorType == Node.NOTATION_NODE)
1111                 
1112                     if (((NamedNodeMapImpl)container.getNotations()).precedes(otherAncestor,thisAncestor))
1113                       return (DOCUMENT_POSITION_PRECEDING |
1114                               DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1115                     else
1116                       return (DOCUMENT_POSITION_FOLLOWING |
1117                               DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1118                 else
1119                     if (((NamedNodeMapImpl)container.getEntities()).precedes(otherAncestor,thisAncestor))
1120                       return (DOCUMENT_POSITION_PRECEDING |
1121                               DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1122                     else
1123                       return (DOCUMENT_POSITION_FOLLOWING |
1124                               DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1125                }
1126              }
1127            }
1128            thisNode = thisAncestor = thisOwnerDoc;
1129            break;
1130          }
1131          case Node.DOCUMENT_TYPE_NODE: {
1132            if (otherNode == thisOwnerDoc)
1133              return (DOCUMENT_POSITION_PRECEDING |
1134                      DOCUMENT_POSITION_CONTAINS);
1135            else if (thisOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc)
1136              return (DOCUMENT_POSITION_FOLLOWING);
1137            break;
1138          }
1139          case Node.ATTRIBUTE_NODE: {
1140            thisNode = ((AttrImpl)thisAncestor).getOwnerElement();
1141            if (otherAncestorType==Node.ATTRIBUTE_NODE) {
1142              otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
1143              if (otherNode == thisNode) {
1144                if (((NamedNodeMapImpl)thisNode.getAttributes()).precedes(other,this))
1145                  return (DOCUMENT_POSITION_PRECEDING |
1146                          DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1147                else
1148                  return (DOCUMENT_POSITION_FOLLOWING |
1149                          DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
1150              }
1151            }
1152
1153            // Now, find the ancestor of the element
1154
thisDepth=0;
1155            for (node=thisNode; node != null; node=node.getParentNode()) {
1156                thisDepth +=1;
1157                if (node == otherNode)
1158                  {
1159                  // The other node is an ancestor of the owning element
1160
return (DOCUMENT_POSITION_CONTAINS |
1161                          DOCUMENT_POSITION_PRECEDING);
1162                  }
1163                thisAncestor = node;
1164            }
1165          }
1166        }
1167        switch (otherAncestorType) {
1168          case Node.NOTATION_NODE:
1169          case Node.ENTITY_NODE: {
1170          DocumentType JavaDoc container = thisOwnerDoc.getDoctype();
1171            if (container == this) return (DOCUMENT_POSITION_IS_CONTAINED |
1172                                          DOCUMENT_POSITION_FOLLOWING);
1173            otherNode = otherAncestor = thisOwnerDoc;
1174            break;
1175          }
1176          case Node.DOCUMENT_TYPE_NODE: {
1177            if (thisNode == otherOwnerDoc)
1178              return (DOCUMENT_POSITION_FOLLOWING |
1179                      DOCUMENT_POSITION_IS_CONTAINED);
1180            else if (otherOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc)
1181              return (DOCUMENT_POSITION_PRECEDING);
1182            break;
1183          }
1184          case Node.ATTRIBUTE_NODE: {
1185            otherDepth=0;
1186            otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
1187            for (node=otherNode; node != null; node=node.getParentNode()) {
1188                otherDepth +=1;
1189                if (node == thisNode)
1190                  // The other node is a descendent of the reference
1191
// node's element
1192
return DOCUMENT_POSITION_FOLLOWING |
1193                         DOCUMENT_POSITION_IS_CONTAINED;
1194                otherAncestor = node;
1195            }
1196
1197          }
1198        }
1199 
1200        // thisAncestor and otherAncestor must be the same at this point,
1201
// otherwise, the original nodes are disconnected
1202
if (thisAncestor != otherAncestor) {
1203          int thisAncestorNum, otherAncestorNum;
1204          thisAncestorNum = ((NodeImpl)thisAncestor).getNodeNumber();
1205          otherAncestorNum = ((NodeImpl)otherAncestor).getNodeNumber();
1206          
1207          if (thisAncestorNum > otherAncestorNum)
1208            return DOCUMENT_POSITION_DISCONNECTED |
1209                   DOCUMENT_POSITION_FOLLOWING |
1210                   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
1211          else
1212            return DOCUMENT_POSITION_DISCONNECTED |
1213                   DOCUMENT_POSITION_PRECEDING |
1214                   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
1215        }
1216
1217      
1218        // Go up the parent chain of the deeper node, until we find a node
1219
// with the same depth as the shallower node
1220

1221        if (thisDepth > otherDepth) {
1222          for (int i=0; i<thisDepth - otherDepth; i++)
1223            thisNode = thisNode.getParentNode();
1224          // Check if the node we have reached is in fact "otherNode". This can
1225
// happen in the case of attributes. In this case, otherNode
1226
// "precedes" this.
1227
if (thisNode == otherNode)
1228{
1229            return DOCUMENT_POSITION_PRECEDING;
1230          }
1231        }
1232 
1233        else {
1234          for (int i=0; i<otherDepth - thisDepth; i++)
1235            otherNode = otherNode.getParentNode();
1236          // Check if the node we have reached is in fact "thisNode". This can
1237
// happen in the case of attributes. In this case, otherNode
1238
// "follows" this.
1239
if (otherNode == thisNode)
1240            return DOCUMENT_POSITION_FOLLOWING;
1241        }
1242             
1243        // We now have nodes at the same depth in the tree. Find a common
1244
// ancestor.
1245
Node JavaDoc thisNodeP, otherNodeP;
1246        for (thisNodeP=thisNode.getParentNode(),
1247                  otherNodeP=otherNode.getParentNode();
1248             thisNodeP!=otherNodeP;) {
1249             thisNode = thisNodeP;
1250             otherNode = otherNodeP;
1251             thisNodeP = thisNodeP.getParentNode();
1252             otherNodeP = otherNodeP.getParentNode();
1253        }
1254
1255        // At this point, thisNode and otherNode are direct children of
1256
// the common ancestor.
1257
// See whether thisNode or otherNode is the leftmost
1258

1259        for (Node JavaDoc current=thisNodeP.getFirstChild();
1260                  current!=null;
1261                  current=current.getNextSibling()) {
1262               if (current==otherNode) {
1263                 return DOCUMENT_POSITION_PRECEDING;
1264               }
1265               else if (current==thisNode) {
1266                 return DOCUMENT_POSITION_FOLLOWING;
1267               }
1268        }
1269        // REVISIT: shouldn't get here. Should probably throw an
1270
// exception
1271
return 0;
1272
1273    }
1274
1275    /**
1276     * This attribute returns the text content of this node and its
1277     * descendants. When it is defined to be null, setting it has no effect.
1278     * When set, any possible children this node may have are removed and
1279     * replaced by a single <code>Text</code> node containing the string
1280     * this attribute is set to. On getting, no serialization is performed,
1281     * the returned string does not contain any markup. No whitespace
1282     * normalization is performed, the returned string does not contain the
1283     * element content whitespaces . Similarly, on setting, no parsing is
1284     * performed either, the input string is taken as pure textual content.
1285     * <br>The string returned is made of the text content of this node
1286     * depending on its type, as defined below:
1287     * <table border='1'>
1288     * <tr>
1289     * <th>Node type</th>
1290     * <th>Content</th>
1291     * </tr>
1292
1293    /**
1294     * This attribute returns the text content of this node and its
1295     * descendants. When it is defined to be null, setting it has no effect.
1296     * When set, any possible children this node may have are removed and
1297     * replaced by a single <code>Text</code> node containing the string
1298     * this attribute is set to. On getting, no serialization is performed,
1299     * the returned string does not contain any markup. No whitespace
1300     * normalization is performed, the returned string does not contain the
1301     * element content whitespaces . Similarly, on setting, no parsing is
1302     * performed either, the input string is taken as pure textual content.
1303     * <br>The string returned is made of the text content of this node
1304     * depending on its type, as defined below:
1305     * <table border='1'>
1306     * <tr>
1307     * <th>Node type</th>
1308     * <th>Content</th>
1309     * </tr>
1310     * <tr>
1311     * <td valign='top' rowspan='1' colspan='1'>
1312     * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
1313     * DOCUMENT_FRAGMENT_NODE</td>
1314     * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code>
1315     * attribute value of every child node, excluding COMMENT_NODE and
1316     * PROCESSING_INSTRUCTION_NODE nodes</td>
1317     * </tr>
1318     * <tr>
1319     * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE,
1320     * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
1321     * <td valign='top' rowspan='1' colspan='1'>
1322     * <code>nodeValue</code></td>
1323     * </tr>
1324     * <tr>
1325     * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
1326     * <td valign='top' rowspan='1' colspan='1'>
1327     * null</td>
1328     * </tr>
1329     * </table>
1330     * @exception DOMException
1331     * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
1332     * @exception DOMException
1333     * DOMSTRING_SIZE_ERR: Raised when it would return more characters than
1334     * fit in a <code>DOMString</code> variable on the implementation
1335     * platform.
1336     * @since DOM Level 3
1337     */

1338    public String JavaDoc getTextContent() throws DOMException JavaDoc {
1339        return getNodeValue(); // overriden in some subclasses
1340
}
1341
1342    // internal method taking a StringBuffer in parameter
1343
void getTextContent(StringBuffer JavaDoc buf) throws DOMException JavaDoc {
1344        String JavaDoc content = getNodeValue();
1345        if (content != null) {
1346            buf.append(content);
1347        }
1348    }
1349
1350    /**
1351     * This attribute returns the text content of this node and its
1352     * descendants. When it is defined to be null, setting it has no effect.
1353     * When set, any possible children this node may have are removed and
1354     * replaced by a single <code>Text</code> node containing the string
1355     * this attribute is set to. On getting, no serialization is performed,
1356     * the returned string does not contain any markup. No whitespace
1357     * normalization is performed, the returned string does not contain the
1358     * element content whitespaces . Similarly, on setting, no parsing is
1359     * performed either, the input string is taken as pure textual content.
1360     * <br>The string returned is made of the text content of this node
1361     * depending on its type, as defined below:
1362     * <table border='1'>
1363     * <tr>
1364     * <th>Node type</th>
1365     * <th>Content</th>
1366     * </tr>
1367     * <tr>
1368     * <td valign='top' rowspan='1' colspan='1'>
1369     * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
1370     * DOCUMENT_FRAGMENT_NODE</td>
1371     * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code>
1372     * attribute value of every child node, excluding COMMENT_NODE and
1373     * PROCESSING_INSTRUCTION_NODE nodes</td>
1374     * </tr>
1375     * <tr>
1376     * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE,
1377     * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
1378     * <td valign='top' rowspan='1' colspan='1'>
1379     * <code>nodeValue</code></td>
1380     * </tr>
1381     * <tr>
1382     * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
1383     * <td valign='top' rowspan='1' colspan='1'>
1384     * null</td>
1385     * </tr>
1386     * </table>
1387     * @exception DOMException
1388     * NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
1389     * @exception DOMException
1390     * DOMSTRING_SIZE_ERR: Raised when it would return more characters than
1391     * fit in a <code>DOMString</code> variable on the implementation
1392     * platform.
1393     * @since DOM Level 3
1394     */

1395    public void setTextContent(String JavaDoc textContent)
1396        throws DOMException JavaDoc {
1397        setNodeValue(textContent);
1398    }
1399
1400    /**
1401     * Returns whether this node is the same node as the given one.
1402     * <br>This method provides a way to determine whether two
1403     * <code>Node</code> references returned by the implementation reference
1404     * the same object. When two <code>Node</code> references are references
1405     * to the same object, even if through a proxy, the references may be
1406     * used completely interchangably, such that all attributes have the
1407     * same values and calling the same DOM method on either reference
1408     * always has exactly the same effect.
1409     * @param other The node to test against.
1410     * @return Returns <code>true</code> if the nodes are the same,
1411     * <code>false</code> otherwise.
1412     * @since DOM Level 3
1413     */

1414    public boolean isSameNode(Node JavaDoc other) {
1415        // we do not use any wrapper so the answer is obvious
1416
return this == other;
1417    }
1418
1419
1420     
1421
1422    /**
1423     * DOM Level 3: Experimental
1424     * This method checks if the specified <code>namespaceURI</code> is the
1425     * default namespace or not.
1426     * @param namespaceURI The namespace URI to look for.
1427     * @return <code>true</code> if the specified <code>namespaceURI</code>
1428     * is the default namespace, <code>false</code> otherwise.
1429     * @since DOM Level 3
1430     */

1431    public boolean isDefaultNamespace(String JavaDoc namespaceURI){
1432        // REVISIT: remove casts when DOM L3 becomes REC.
1433
short type = this.getNodeType();
1434        switch (type) {
1435        case Node.ELEMENT_NODE: {
1436            String JavaDoc namespace = this.getNamespaceURI();
1437            String JavaDoc prefix = this.getPrefix();
1438            
1439            // REVISIT: is it possible that prefix is empty string?
1440
if (prefix == null || prefix.length() == 0) {
1441                if (namespaceURI == null) {
1442                    return (namespace == namespaceURI);
1443                }
1444                return namespaceURI.equals(namespace);
1445            }
1446            if (this.hasAttributes()) {
1447                ElementImpl elem = (ElementImpl)this;
1448                NodeImpl attr = (NodeImpl)elem.getAttributeNodeNS("http://www.w3.org/2000/xmlns/", "xmlns");
1449                if (attr != null) {
1450                    String JavaDoc value = attr.getNodeValue();
1451                    if (namespaceURI == null) {
1452                        return (namespace == value);
1453                    }
1454                    return namespaceURI.equals(value);
1455                }
1456            }
1457
1458            NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
1459            if (ancestor != null) {
1460                return ancestor.isDefaultNamespace(namespaceURI);
1461            }
1462            return false;
1463        }
1464        case Node.DOCUMENT_NODE:{
1465                return((NodeImpl)((Document JavaDoc)this).getDocumentElement()).isDefaultNamespace(namespaceURI);
1466            }
1467
1468        case Node.ENTITY_NODE :
1469        case Node.NOTATION_NODE:
1470        case Node.DOCUMENT_FRAGMENT_NODE:
1471        case Node.DOCUMENT_TYPE_NODE:
1472            // type is unknown
1473
return false;
1474        case Node.ATTRIBUTE_NODE:{
1475                if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
1476                    return ownerNode.isDefaultNamespace(namespaceURI);
1477
1478                }
1479                return false;
1480            }
1481        default:{
1482                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
1483                if (ancestor != null) {
1484                    return ancestor.isDefaultNamespace(namespaceURI);
1485                }
1486                return false;
1487            }
1488
1489        }
1490
1491
1492    }
1493
1494
1495    /**
1496     *
1497     * DOM Level 3 - Experimental:
1498     * Look up the prefix associated to the given namespace URI, starting from this node.
1499     *
1500     * @param namespaceURI
1501     * @return the prefix for the namespace
1502     */

1503    public String JavaDoc lookupPrefix(String JavaDoc namespaceURI){
1504        
1505        // REVISIT: When Namespaces 1.1 comes out this may not be true
1506
// Prefix can't be bound to null namespace
1507
if (namespaceURI == null) {
1508            return null;
1509        }
1510
1511        short type = this.getNodeType();
1512
1513        switch (type) {
1514        case Node.ELEMENT_NODE: {
1515
1516                String JavaDoc namespace = this.getNamespaceURI(); // to flip out children
1517
return lookupNamespacePrefix(namespaceURI, (ElementImpl)this);
1518            }
1519        case Node.DOCUMENT_NODE:{
1520                return((NodeImpl)((Document JavaDoc)this).getDocumentElement()).lookupPrefix(namespaceURI);
1521            }
1522
1523        case Node.ENTITY_NODE :
1524        case Node.NOTATION_NODE:
1525        case Node.DOCUMENT_FRAGMENT_NODE:
1526        case Node.DOCUMENT_TYPE_NODE:
1527            // type is unknown
1528
return null;
1529        case Node.ATTRIBUTE_NODE:{
1530                if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
1531                    return ownerNode.lookupPrefix(namespaceURI);
1532
1533                }
1534                return null;
1535            }
1536        default:{
1537                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
1538                if (ancestor != null) {
1539                    return ancestor.lookupPrefix(namespaceURI);
1540                }
1541                return null;
1542            }
1543
1544        }
1545    }
1546    /**
1547     * DOM Level 3 - Experimental:
1548     * Look up the namespace URI associated to the given prefix, starting from this node.
1549     * Use lookupNamespaceURI(null) to lookup the default namespace
1550     *
1551     * @param namespaceURI
1552     * @return th URI for the namespace
1553     * @since DOM Level 3
1554     */

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

1734    public boolean isEqualNode(Node JavaDoc arg) {
1735        if (arg == this) {
1736            return true;
1737        }
1738        if (arg.getNodeType() != getNodeType()) {
1739            return false;
1740        }
1741        // in theory nodeName can't be null but better be careful
1742
// who knows what other implementations may be doing?...
1743
if (getNodeName() == null) {
1744            if (arg.getNodeName() != null) {
1745                return false;
1746            }
1747        }
1748        else if (!getNodeName().equals(arg.getNodeName())) {
1749            return false;
1750        }
1751
1752        if (getLocalName() == null) {
1753            if (arg.getLocalName() != null) {
1754                return false;
1755            }
1756        }
1757        else if (!getLocalName().equals(arg.getLocalName())) {
1758            return false;
1759        }
1760
1761        if (getNamespaceURI() == null) {
1762            if (arg.getNamespaceURI() != null) {
1763                return false;
1764            }
1765        }
1766        else if (!getNamespaceURI().equals(arg.getNamespaceURI())) {
1767            return false;
1768        }
1769
1770        if (getPrefix() == null) {
1771            if (arg.getPrefix() != null) {
1772                return false;
1773            }
1774        }
1775        else if (!getPrefix().equals(arg.getPrefix())) {
1776            return false;
1777        }
1778
1779        if (getNodeValue() == null) {
1780            if (arg.getNodeValue() != null) {
1781                return false;
1782            }
1783        }
1784        else if (!getNodeValue().equals(arg.getNodeValue())) {
1785            return false;
1786        }
1787
1788
1789        return true;
1790    }
1791
1792    /**
1793     * @since DOM Level 3
1794     */

1795    public Object JavaDoc getFeature(String JavaDoc feature, String JavaDoc version) {
1796        // we don't have any alternate node, either this node does the job
1797
// or we don't have anything that does
1798
return isSupported(feature, version) ? this : null;
1799    }
1800
1801    /**
1802     * Associate an object to a key on this node. The object can later be
1803     * retrieved from this node by calling <code>getUserData</code> with the
1804     * same key.
1805     * @param key The key to associate the object to.
1806     * @param data The object to associate to the given key, or
1807     * <code>null</code> to remove any existing association to that key.
1808     * @param handler The handler to associate to that key, or
1809     * <code>null</code>.
1810     * @return Returns the <code>DOMObject</code> previously associated to
1811     * the given key on this node, or <code>null</code> if there was none.
1812     * @since DOM Level 3
1813     */

1814    public Object JavaDoc setUserData(String JavaDoc key,
1815                              Object JavaDoc data,
1816                              UserDataHandler JavaDoc handler) {
1817        return ownerDocument().setUserData(this, key, data, handler);
1818    }
1819
1820    /**
1821     * Retrieves the object associated to a key on a this node. The object
1822     * must first have been set to this node by calling
1823     * <code>setUserData</code> with the same key.
1824     * @param key The key the object is associated to.
1825     * @return Returns the <code>DOMObject</code> associated to the given key
1826     * on this node, or <code>null</code> if there was none.
1827     * @since DOM Level 3
1828     */

1829    public Object JavaDoc getUserData(String JavaDoc key) {
1830        return ownerDocument().getUserData(this, key);
1831    }
1832
1833    /**
1834    */

1835    protected Hashtable JavaDoc getUserDataRecord(){
1836        return ownerDocument().getUserDataRecord(this);
1837    }
1838
1839    //
1840
// Public methods
1841
//
1842

1843    /**
1844     * NON-DOM: PR-DOM-Level-1-19980818 mentions readonly nodes in conjunction
1845     * with Entities, but provides no API to support this.
1846     * <P>
1847     * Most DOM users should not touch this method. Its anticpated use
1848     * is during construction of EntityRefernces, where it will be used to
1849     * lock the contents replicated from Entity so they can't be casually
1850     * altered. It _could_ be published as a DOM extension, if desired.
1851     * <P>
1852     * Note: since we never have any children deep is meaningless here,
1853     * ParentNode overrides this behavior.
1854     * @see ParentNode
1855     *
1856     * @param readOnly True or false as desired.
1857     * @param deep If true, children are also toggled. Note that this will
1858     * not change the state of an EntityReference or its children,
1859     * which are always read-only.
1860     */

1861    public void setReadOnly(boolean readOnly, boolean deep) {
1862
1863        if (needsSyncData()) {
1864            synchronizeData();
1865        }
1866        isReadOnly(readOnly);
1867
1868    } // setReadOnly(boolean,boolean)
1869

1870    /**
1871     * NON-DOM: Returns true if this node is read-only. This is a
1872     * shallow check.
1873     */

1874    public boolean getReadOnly() {
1875
1876        if (needsSyncData()) {
1877            synchronizeData();
1878        }
1879        return isReadOnly();
1880
1881    } // getReadOnly():boolean
1882

1883    /**
1884     * NON-DOM: As an alternative to subclassing the DOM, this implementation
1885     * has been extended with the ability to attach an object to each node.
1886     * (If you need multiple objects, you can attach a collection such as a
1887     * vector or hashtable, then attach your application information to that.)
1888     * <p><b>Important Note:</b> You are responsible for removing references
1889     * to your data on nodes that are no longer used. Failure to do so will
1890     * prevent the nodes, your data is attached to, to be garbage collected
1891     * until the whole document is.
1892     *
1893     * @param data the object to store or null to remove any existing reference
1894     */

1895    public void setUserData(Object JavaDoc data) {
1896        ownerDocument().setUserData(this, data);
1897    }
1898
1899    /**
1900     * NON-DOM:
1901     * Returns the user data associated to this node.
1902     */

1903    public Object JavaDoc getUserData() {
1904        return ownerDocument().getUserData(this);
1905    }
1906
1907    //
1908
// Protected methods
1909
//
1910

1911    /**
1912     * Denotes that this node has changed.
1913     */

1914    protected void changed() {
1915        // we do not actually store this information on every node, we only
1916
// have a global indicator on the Document. Doing otherwise cost us too
1917
// much for little gain.
1918
ownerDocument().changed();
1919    }
1920
1921    /**
1922     * Returns the number of changes to this node.
1923     */

1924    protected int changes() {
1925        // we do not actually store this information on every node, we only
1926
// have a global indicator on the Document. Doing otherwise cost us too
1927
// much for little gain.
1928
return ownerDocument().changes();
1929    }
1930
1931    /**
1932     * Override this method in subclass to hook in efficient
1933     * internal data structure.
1934     */

1935    protected void synchronizeData() {
1936        // By default just change the flag to avoid calling this method again
1937
needsSyncData(false);
1938    }
1939
1940    /**
1941     * For non-child nodes, the node which "points" to this node.
1942     * For example, the owning element for an attribute
1943     */

1944    protected Node JavaDoc getContainer() {
1945       return null;
1946    }
1947
1948
1949    /*
1950     * Flags setters and getters
1951     */

1952
1953    final boolean isReadOnly() {
1954        return (flags & READONLY) != 0;
1955    }
1956
1957    final void isReadOnly(boolean value) {
1958        flags = (short) (value ? flags | READONLY : flags & ~READONLY);
1959    }
1960
1961    final boolean needsSyncData() {
1962        return (flags & SYNCDATA) != 0;
1963    }
1964
1965    final void needsSyncData(boolean value) {
1966        flags = (short) (value ? flags | SYNCDATA : flags & ~SYNCDATA);
1967    }
1968
1969    final boolean needsSyncChildren() {
1970        return (flags & SYNCCHILDREN) != 0;
1971    }
1972
1973    public final void needsSyncChildren(boolean value) {
1974        flags = (short) (value ? flags | SYNCCHILDREN : flags & ~SYNCCHILDREN);
1975    }
1976
1977    final boolean isOwned() {
1978        return (flags & OWNED) != 0;
1979    }
1980
1981    final void isOwned(boolean value) {
1982        flags = (short) (value ? flags | OWNED : flags & ~OWNED);
1983    }
1984
1985    final boolean isFirstChild() {
1986        return (flags & FIRSTCHILD) != 0;
1987    }
1988
1989    final void isFirstChild(boolean value) {
1990        flags = (short) (value ? flags | FIRSTCHILD : flags & ~FIRSTCHILD);
1991    }
1992
1993    final boolean isSpecified() {
1994        return (flags & SPECIFIED) != 0;
1995    }
1996
1997    final void isSpecified(boolean value) {
1998        flags = (short) (value ? flags | SPECIFIED : flags & ~SPECIFIED);
1999    }
2000
2001    // inconsistent name to avoid clash with public method on TextImpl
2002
final boolean internalIsIgnorableWhitespace() {
2003        return (flags & IGNORABLEWS) != 0;
2004    }
2005
2006    final void isIgnorableWhitespace(boolean value) {
2007        flags = (short) (value ? flags | IGNORABLEWS : flags & ~IGNORABLEWS);
2008    }
2009
2010    final boolean hasStringValue() {
2011        return (flags & HASSTRING) != 0;
2012    }
2013
2014    final void hasStringValue(boolean value) {
2015        flags = (short) (value ? flags | HASSTRING : flags & ~HASSTRING);
2016    }
2017
2018    final boolean isNormalized() {
2019        return (flags & NORMALIZED) != 0;
2020    }
2021
2022    final void isNormalized(boolean value) {
2023        // See if flag should propagate to parent.
2024
if (!value && isNormalized() && ownerNode != null) {
2025            ownerNode.isNormalized(false);
2026        }
2027        flags = (short) (value ? flags | NORMALIZED : flags & ~NORMALIZED);
2028    }
2029
2030    final boolean isIdAttribute() {
2031        return (flags & ID) != 0;
2032    }
2033
2034    final void isIdAttribute(boolean value) {
2035        flags = (short) (value ? flags | ID : flags & ~ID);
2036    }
2037
2038    //
2039
// Object methods
2040
//
2041

2042    /** NON-DOM method for debugging convenience. */
2043    public String JavaDoc toString() {
2044        return "["+getNodeName()+": "+getNodeValue()+"]";
2045    }
2046
2047    //
2048
// Serialization methods
2049
//
2050

2051    /** Serialize object. */
2052    private void writeObject(ObjectOutputStream JavaDoc out) throws IOException JavaDoc {
2053
2054        // synchronize data
2055
if (needsSyncData()) {
2056            synchronizeData();
2057        }
2058        // write object
2059
out.defaultWriteObject();
2060
2061    } // writeObject(ObjectOutputStream)
2062

2063} // class NodeImpl
2064
Popular Tags