Save This Page
Home » openjdk-7 » com.sun.org.apache.xerces.internal » dom » [javadoc | source]
    1   /*
    2    * reserved comment block
    3    * DO NOT REMOVE OR ALTER!
    4    */
    5    /*
    6    * Copyright 1999-2002,2004 The Apache Software Foundation.
    7    *
    8    * Licensed under the Apache License, Version 2.0 (the "License");
    9    * you may not use this file except in compliance with the License.
   10    * You may obtain a copy of the License at
   11    *
   12    *      http://www.apache.org/licenses/LICENSE-2.0
   13    *
   14    * Unless required by applicable law or agreed to in writing, software
   15    * distributed under the License is distributed on an "AS IS" BASIS,
   16    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   17    * See the License for the specific language governing permissions and
   18    * limitations under the License.
   19    */
   20   
   21   package com.sun.org.apache.xerces.internal.dom;
   22   
   23   import java.io.IOException;
   24   import java.io.ObjectOutputStream;
   25   import java.io.Serializable;
   26   import java.util.Hashtable;
   27   
   28   import org.w3c.dom.UserDataHandler;
   29   import org.w3c.dom.DOMException;
   30   import org.w3c.dom.Document;
   31   import org.w3c.dom.DocumentType;
   32   import org.w3c.dom.NamedNodeMap;
   33   import org.w3c.dom.Node;
   34   import org.w3c.dom.NodeList;
   35   import org.w3c.dom.events.Event;
   36   import org.w3c.dom.events.EventListener;
   37   import org.w3c.dom.events.EventTarget;
   38   
   39   /**
   40    * NodeImpl provides the basic structure of a DOM tree. It is never used
   41    * directly, but instead is subclassed to add type and data
   42    * information, and additional methods, appropriate to each node of
   43    * the tree. Only its subclasses should be instantiated -- and those,
   44    * with the exception of Document itself, only through a specific
   45    * Document's factory methods.
   46    * <P>
   47    * The Node interface provides shared behaviors such as siblings and
   48    * children, both for consistancy and so that the most common tree
   49    * operations may be performed without constantly having to downcast
   50    * to specific node types. When there is no obvious mapping for one of
   51    * these queries, it will respond with null.
   52    * Note that the default behavior is that children are forbidden. To
   53    * permit them, the subclass ParentNode overrides several methods.
   54    * <P>
   55    * NodeImpl also implements NodeList, so it can return itself in
   56    * response to the getChildNodes() query. This eliminiates the need
   57    * for a separate ChildNodeList object. Note that this is an
   58    * IMPLEMENTATION DETAIL; applications should _never_ assume that
   59    * this identity exists.
   60    * <P>
   61    * All nodes in a single document must originate
   62    * in that document. (Note that this is much tighter than "must be
   63    * same implementation") Nodes are all aware of their ownerDocument,
   64    * and attempts to mismatch will throw WRONG_DOCUMENT_ERR.
   65    * <P>
   66    * However, to save memory not all nodes always have a direct reference
   67    * to their ownerDocument. When a node is owned by another node it relies
   68    * on its owner to store its ownerDocument. Parent nodes always store it
   69    * though, so there is never more than one level of indirection.
   70    * And when a node doesn't have an owner, ownerNode refers to its
   71    * ownerDocument.
   72    * <p>
   73    * This class doesn't directly support mutation events, however, it still
   74    * implements the EventTarget interface and forward all related calls to the
   75    * document so that the document class do so.
   76    *
   77    * @xerces.internal
   78    *
   79    * @author Arnaud  Le Hors, IBM
   80    * @author Joe Kesselman, IBM
   81    * @since  PR-DOM-Level-1-19980818.
   82    */
   83   public abstract class NodeImpl
   84       implements Node, NodeList, EventTarget, Cloneable, Serializable{
   85   
   86       //
   87       // Constants
   88       //
   89   
   90   
   91       // TreePosition Constants.
   92       // Taken from DOM L3 Node interface.
   93       /**
   94        * The node precedes the reference node.
   95        */
   96       public static final short TREE_POSITION_PRECEDING   = 0x01;
   97       /**
   98        * The node follows the reference node.
   99        */
  100       public static final short TREE_POSITION_FOLLOWING   = 0x02;
  101       /**
  102        * The node is an ancestor of the reference node.
  103        */
  104       public static final short TREE_POSITION_ANCESTOR    = 0x04;
  105       /**
  106        * The node is a descendant of the reference node.
  107        */
  108       public static final short TREE_POSITION_DESCENDANT  = 0x08;
  109       /**
  110        * The two nodes have an equivalent position. This is the case of two
  111        * attributes that have the same <code>ownerElement</code>, and two
  112        * nodes that are the same.
  113        */
  114       public static final short TREE_POSITION_EQUIVALENT  = 0x10;
  115       /**
  116        * The two nodes are the same. Two nodes that are the same have an
  117        * equivalent position, though the reverse may not be true.
  118        */
  119       public static final short TREE_POSITION_SAME_NODE   = 0x20;
  120       /**
  121        * The two nodes are disconnected, they do not have any common ancestor.
  122        * This is the case of two nodes that are not in the same document.
  123        */
  124       public static final short TREE_POSITION_DISCONNECTED = 0x00;
  125   
  126   
  127       // DocumentPosition
  128       public static final short DOCUMENT_POSITION_DISCONNECTED = 0x01;
  129       public static final short DOCUMENT_POSITION_PRECEDING = 0x02;
  130       public static final short DOCUMENT_POSITION_FOLLOWING = 0x04;
  131       public static final short DOCUMENT_POSITION_CONTAINS = 0x08;
  132       public static final short DOCUMENT_POSITION_IS_CONTAINED = 0x10;
  133       public static final short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;
  134   
  135       /** Serialization version. */
  136       static final long serialVersionUID = -6316591992167219696L;
  137   
  138       // public
  139   
  140       /** Element definition node type. */
  141       public static final short ELEMENT_DEFINITION_NODE = 21;
  142   
  143       //
  144       // Data
  145       //
  146   
  147       // links
  148   
  149       protected NodeImpl ownerNode; // typically the parent but not always!
  150   
  151       // data
  152   
  153       protected short flags;
  154   
  155       protected final static short READONLY     = 0x1<<0;
  156       protected final static short SYNCDATA     = 0x1<<1;
  157       protected final static short SYNCCHILDREN = 0x1<<2;
  158       protected final static short OWNED        = 0x1<<3;
  159       protected final static short FIRSTCHILD   = 0x1<<4;
  160       protected final static short SPECIFIED    = 0x1<<5;
  161       protected final static short IGNORABLEWS  = 0x1<<6;
  162       protected final static short HASSTRING    = 0x1<<7;
  163       protected final static short NORMALIZED = 0x1<<8;
  164       protected final static short ID           = 0x1<<9;
  165   
  166       //
  167       // Constructors
  168       //
  169   
  170       /**
  171        * No public constructor; only subclasses of Node should be
  172        * instantiated, and those normally via a Document's factory methods
  173        * <p>
  174        * Every Node knows what Document it belongs to.
  175        */
  176       protected NodeImpl(CoreDocumentImpl ownerDocument) {
  177           // as long as we do not have any owner, ownerNode is our ownerDocument
  178           ownerNode = ownerDocument;
  179       } // <init>(CoreDocumentImpl)
  180   
  181       /** Constructor for serialization. */
  182       public NodeImpl() {}
  183   
  184       //
  185       // Node methods
  186       //
  187   
  188       /**
  189        * A short integer indicating what type of node this is. The named
  190        * constants for this value are defined in the org.w3c.dom.Node interface.
  191        */
  192       public abstract short getNodeType();
  193   
  194       /**
  195        * the name of this node.
  196        */
  197       public abstract String getNodeName();
  198   
  199       /**
  200        * Returns the node value.
  201        * @throws DOMException(DOMSTRING_SIZE_ERR)
  202        */
  203       public String getNodeValue()
  204           throws DOMException {
  205           return null;            // overridden in some subclasses
  206       }
  207   
  208       /**
  209        * Sets the node value.
  210        * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR)
  211        */
  212       public void setNodeValue(String x)
  213           throws DOMException {
  214           // Default behavior is to do nothing, overridden in some subclasses
  215       }
  216   
  217       /**
  218        * Adds a child node to the end of the list of children for this node.
  219        * Convenience shorthand for insertBefore(newChild,null).
  220        * @see #insertBefore(Node, Node)
  221        * <P>
  222        * By default we do not accept any children, ParentNode overrides this.
  223        * @see ParentNode
  224        *
  225        * @return newChild, in its new state (relocated, or emptied in the case of
  226        * DocumentNode.)
  227        *
  228        * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
  229        * type that shouldn't be a child of this node.
  230        *
  231        * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
  232        * different owner document than we do.
  233        *
  234        * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
  235        * read-only.
  236        */
  237       public Node appendChild(Node newChild) throws DOMException {
  238           return insertBefore(newChild, null);
  239       }
  240   
  241       /**
  242        * Returns a duplicate of a given node. You can consider this a
  243        * generic "copy constructor" for nodes. The newly returned object should
  244        * be completely independent of the source object's subtree, so changes
  245        * in one after the clone has been made will not affect the other.
  246        * <P>
  247        * Note: since we never have any children deep is meaningless here,
  248        * ParentNode overrides this behavior.
  249        * @see ParentNode
  250        *
  251        * <p>
  252        * Example: Cloning a Text node will copy both the node and the text it
  253        * contains.
  254        * <p>
  255        * Example: Cloning something that has children -- Element or Attr, for
  256        * example -- will _not_ clone those children unless a "deep clone"
  257        * has been requested. A shallow clone of an Attr node will yield an
  258        * empty Attr of the same name.
  259        * <p>
  260        * NOTE: Clones will always be read/write, even if the node being cloned
  261        * is read-only, to permit applications using only the DOM API to obtain
  262        * editable copies of locked portions of the tree.
  263        */
  264       public Node cloneNode(boolean deep) {
  265   
  266           if (needsSyncData()) {
  267               synchronizeData();
  268           }
  269   
  270           NodeImpl newnode;
  271           try {
  272               newnode = (NodeImpl)clone();
  273           }
  274           catch (CloneNotSupportedException e) {
  275               // if we get here we have an error in our program we may as well
  276               // be vocal about it, so that people can take appropriate action.
  277               throw new RuntimeException("**Internal Error**" + e);
  278           }
  279   
  280           // Need to break the association w/ original kids
  281           newnode.ownerNode      = ownerDocument();
  282           newnode.isOwned(false);
  283   
  284           // By default we make all clones readwrite,
  285           // this is overriden in readonly subclasses
  286           newnode.isReadOnly(false);
  287   
  288           ownerDocument().callUserDataHandlers(this, newnode,
  289                                                UserDataHandler.NODE_CLONED);
  290   
  291           return newnode;
  292   
  293       } // cloneNode(boolean):Node
  294   
  295       /**
  296        * Find the Document that this Node belongs to (the document in
  297        * whose context the Node was created). The Node may or may not
  298        * currently be part of that Document's actual contents.
  299        */
  300       public Document getOwnerDocument() {
  301           // if we have an owner simply forward the request
  302           // otherwise ownerNode is our ownerDocument
  303           if (isOwned()) {
  304               return ownerNode.ownerDocument();
  305           } else {
  306               return (Document) ownerNode;
  307           }
  308       }
  309   
  310       /**
  311        * same as above but returns internal type and this one is not overridden
  312        * by CoreDocumentImpl to return null
  313        */
  314       CoreDocumentImpl ownerDocument() {
  315           // if we have an owner simply forward the request
  316           // otherwise ownerNode is our ownerDocument
  317           if (isOwned()) {
  318               return ownerNode.ownerDocument();
  319           } else {
  320               return (CoreDocumentImpl) ownerNode;
  321           }
  322       }
  323   
  324       /**
  325        * NON-DOM
  326        * set the ownerDocument of this node
  327        */
  328       void setOwnerDocument(CoreDocumentImpl doc) {
  329           if (needsSyncData()) {
  330               synchronizeData();
  331           }
  332           // if we have an owner we rely on it to have it right
  333           // otherwise ownerNode is our ownerDocument
  334           if (!isOwned()) {
  335               ownerNode = doc;
  336           }
  337       }
  338   
  339       /**
  340        * Returns the node number
  341        */
  342       protected int getNodeNumber() {
  343           int nodeNumber;
  344           CoreDocumentImpl cd = (CoreDocumentImpl)(this.getOwnerDocument());
  345           nodeNumber = cd.getNodeNumber(this);
  346           return nodeNumber;
  347       }
  348   
  349       /**
  350        * Obtain the DOM-tree parent of this node, or null if it is not
  351        * currently active in the DOM tree (perhaps because it has just been
  352        * created or removed). Note that Document, DocumentFragment, and
  353        * Attribute will never have parents.
  354        */
  355       public Node getParentNode() {
  356           return null;            // overriden by ChildNode
  357       }
  358   
  359       /*
  360        * same as above but returns internal type
  361        */
  362       NodeImpl parentNode() {
  363           return null;
  364       }
  365   
  366       /** The next child of this node's parent, or null if none */
  367       public Node getNextSibling() {
  368           return null;            // default behavior, overriden in ChildNode
  369       }
  370   
  371       /** The previous child of this node's parent, or null if none */
  372       public Node getPreviousSibling() {
  373           return null;            // default behavior, overriden in ChildNode
  374       }
  375   
  376       ChildNode previousSibling() {
  377           return null;            // default behavior, overriden in ChildNode
  378       }
  379   
  380       /**
  381        * Return the collection of attributes associated with this node,
  382        * or null if none. At this writing, Element is the only type of node
  383        * which will ever have attributes.
  384        *
  385        * @see ElementImpl
  386        */
  387       public NamedNodeMap getAttributes() {
  388           return null; // overridden in ElementImpl
  389       }
  390   
  391       /**
  392        *  Returns whether this node (if it is an element) has any attributes.
  393        * @return <code>true</code> if this node has any attributes,
  394        *   <code>false</code> otherwise.
  395        * @since DOM Level 2
  396        * @see ElementImpl
  397        */
  398       public boolean hasAttributes() {
  399           return false;           // overridden in ElementImpl
  400       }
  401   
  402       /**
  403        * Test whether this node has any children. Convenience shorthand
  404        * for (Node.getFirstChild()!=null)
  405        * <P>
  406        * By default we do not have any children, ParentNode overrides this.
  407        * @see ParentNode
  408        */
  409       public boolean hasChildNodes() {
  410           return false;
  411       }
  412   
  413       /**
  414        * Obtain a NodeList enumerating all children of this node. If there
  415        * are none, an (initially) empty NodeList is returned.
  416        * <p>
  417        * NodeLists are "live"; as children are added/removed the NodeList
  418        * will immediately reflect those changes. Also, the NodeList refers
  419        * to the actual nodes, so changes to those nodes made via the DOM tree
  420        * will be reflected in the NodeList and vice versa.
  421        * <p>
  422        * In this implementation, Nodes implement the NodeList interface and
  423        * provide their own getChildNodes() support. Other DOMs may solve this
  424        * differently.
  425        */
  426       public NodeList getChildNodes() {
  427           return this;
  428       }
  429   
  430       /** The first child of this Node, or null if none.
  431        * <P>
  432        * By default we do not have any children, ParentNode overrides this.
  433        * @see ParentNode
  434        */
  435       public Node getFirstChild() {
  436           return null;
  437       }
  438   
  439       /** The first child of this Node, or null if none.
  440        * <P>
  441        * By default we do not have any children, ParentNode overrides this.
  442        * @see ParentNode
  443        */
  444       public Node getLastChild() {
  445           return null;
  446       }
  447   
  448       /**
  449        * Move one or more node(s) to our list of children. Note that this
  450        * implicitly removes them from their previous parent.
  451        * <P>
  452        * By default we do not accept any children, ParentNode overrides this.
  453        * @see ParentNode
  454        *
  455        * @param newChild The Node to be moved to our subtree. As a
  456        * convenience feature, inserting a DocumentNode will instead insert
  457        * all its children.
  458        *
  459        * @param refChild Current child which newChild should be placed
  460        * immediately before. If refChild is null, the insertion occurs
  461        * after all existing Nodes, like appendChild().
  462        *
  463        * @return newChild, in its new state (relocated, or emptied in the case of
  464        * DocumentNode.)
  465        *
  466        * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
  467        * type that shouldn't be a child of this node, or if newChild is an
  468        * ancestor of this node.
  469        *
  470        * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
  471        * different owner document than we do.
  472        *
  473        * @throws DOMException(NOT_FOUND_ERR) if refChild is not a child of
  474        * this node.
  475        *
  476        * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
  477        * read-only.
  478        */
  479       public Node insertBefore(Node newChild, Node refChild)
  480           throws DOMException {
  481           throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
  482                 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
  483                    "HIERARCHY_REQUEST_ERR", null));
  484       }
  485   
  486       /**
  487        * Remove a child from this Node. The removed child's subtree
  488        * remains intact so it may be re-inserted elsewhere.
  489        * <P>
  490        * By default we do not have any children, ParentNode overrides this.
  491        * @see ParentNode
  492        *
  493        * @return oldChild, in its new state (removed).
  494        *
  495        * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
  496        * this node.
  497        *
  498        * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
  499        * read-only.
  500        */
  501       public Node removeChild(Node oldChild)
  502                   throws DOMException {
  503           throw new DOMException(DOMException.NOT_FOUND_ERR,
  504                 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
  505                    "NOT_FOUND_ERR", null));
  506       }
  507   
  508       /**
  509        * Make newChild occupy the location that oldChild used to
  510        * have. Note that newChild will first be removed from its previous
  511        * parent, if any. Equivalent to inserting newChild before oldChild,
  512        * then removing oldChild.
  513        * <P>
  514        * By default we do not have any children, ParentNode overrides this.
  515        * @see ParentNode
  516        *
  517        * @return oldChild, in its new state (removed).
  518        *
  519        * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
  520        * type that shouldn't be a child of this node, or if newChild is
  521        * one of our ancestors.
  522        *
  523        * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
  524        * different owner document than we do.
  525        *
  526        * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
  527        * this node.
  528        *
  529        * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
  530        * read-only.
  531        */
  532       public Node replaceChild(Node newChild, Node oldChild)
  533           throws DOMException {
  534           throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
  535                 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
  536                    "HIERARCHY_REQUEST_ERR", null));
  537       }
  538   
  539       //
  540       // NodeList methods
  541       //
  542   
  543       /**
  544        * NodeList method: Count the immediate children of this node
  545        * <P>
  546        * By default we do not have any children, ParentNode overrides this.
  547        * @see ParentNode
  548        *
  549        * @return int
  550        */
  551       public int getLength() {
  552           return 0;
  553       }
  554   
  555       /**
  556        * NodeList method: Return the Nth immediate child of this node, or
  557        * null if the index is out of bounds.
  558        * <P>
  559        * By default we do not have any children, ParentNode overrides this.
  560        * @see ParentNode
  561        *
  562        * @return org.w3c.dom.Node
  563        * @param Index int
  564        */
  565       public Node item(int index) {
  566           return null;
  567       }
  568   
  569       //
  570       // DOM2: methods, getters, setters
  571       //
  572   
  573       /**
  574        * Puts all <code>Text</code> nodes in the full depth of the sub-tree
  575        * underneath this <code>Node</code>, including attribute nodes, into a
  576        * "normal" form where only markup (e.g., tags, comments, processing
  577        * instructions, CDATA sections, and entity references) separates
  578        * <code>Text</code> nodes, i.e., there are no adjacent <code>Text</code>
  579        * nodes.  This can be used to ensure that the DOM view of a document is
  580        * the same as if it were saved and re-loaded, and is useful when
  581        * operations (such as XPointer lookups) that depend on a particular
  582        * document tree structure are to be used.In cases where the document
  583        * contains <code>CDATASections</code>, the normalize operation alone may
  584        * not be sufficient, since XPointers do not differentiate between
  585        * <code>Text</code> nodes and <code>CDATASection</code> nodes.
  586        * <p>
  587        * Note that this implementation simply calls normalize() on this Node's
  588        * children. It is up to implementors or Node to override normalize()
  589        * to take action.
  590        */
  591       public void normalize() {
  592           /* by default we do not have any children,
  593              ParentNode overrides this behavior */
  594       }
  595   
  596       /**
  597        * Introduced in DOM Level 2. <p>
  598        * Tests whether the DOM implementation implements a specific feature and
  599        * that feature is supported by this node.
  600        * @param feature The package name of the feature to test. This is the same
  601        * name as what can be passed to the method hasFeature on
  602        * DOMImplementation.
  603        * @param version This is the version number of the package name to
  604        * test. In Level 2, version 1, this is the string "2.0". If the version is
  605        * not specified, supporting any version of the feature will cause the
  606        * method to return true.
  607        * @return boolean Returns true if this node defines a subtree within which
  608        * the specified feature is supported, false otherwise.
  609        * @since WD-DOM-Level-2-19990923
  610        */
  611       public boolean isSupported(String feature, String version)
  612       {
  613           return ownerDocument().getImplementation().hasFeature(feature,
  614                                                                 version);
  615       }
  616   
  617       /**
  618        * Introduced in DOM Level 2. <p>
  619        *
  620        * The namespace URI of this node, or null if it is unspecified. When this
  621        * node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE, this is
  622        * always null and setting it has no effect. <p>
  623        *
  624        * This is not a computed value that is the result of a namespace lookup
  625        * based on an examination of the namespace declarations in scope. It is
  626        * merely the namespace URI given at creation time.<p>
  627        *
  628        * For nodes created with a DOM Level 1 method, such as createElement
  629        * from the Document interface, this is null.
  630        * @since WD-DOM-Level-2-19990923
  631        * @see AttrNSImpl
  632        * @see ElementNSImpl
  633        */
  634       public String getNamespaceURI()
  635       {
  636           return null;
  637       }
  638   
  639       /**
  640        * Introduced in DOM Level 2. <p>
  641        *
  642        * The namespace prefix of this node, or null if it is unspecified. When
  643        * this node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE this
  644        * is always null and setting it has no effect.<p>
  645        *
  646        * For nodes created with a DOM Level 1 method, such as createElement
  647        * from the Document interface, this is null. <p>
  648        *
  649        * @since WD-DOM-Level-2-19990923
  650        * @see AttrNSImpl
  651        * @see ElementNSImpl
  652        */
  653       public String getPrefix()
  654       {
  655           return null;
  656       }
  657   
  658       /**
  659        *  Introduced in DOM Level 2. <p>
  660        *
  661        *  The namespace prefix of this node, or null if it is unspecified. When
  662        *  this node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE
  663        *  this is always null and setting it has no effect.<p>
  664        *
  665        *  For nodes created with a DOM Level 1 method, such as createElement from
  666        *  the Document interface, this is null.<p>
  667        *
  668        *  Note that setting this attribute changes the nodeName attribute, which
  669        *  holds the qualified name, as well as the tagName and name attributes of
  670        *  the Element and Attr interfaces, when applicable.<p>
  671        *
  672        * @throws INVALID_CHARACTER_ERR Raised if the specified
  673        *  prefix contains an invalid character.
  674        *
  675        * @since WD-DOM-Level-2-19990923
  676        * @see AttrNSImpl
  677        * @see ElementNSImpl
  678        */
  679       public void setPrefix(String prefix)
  680           throws DOMException
  681       {
  682           throw new DOMException(DOMException.NAMESPACE_ERR,
  683                 DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
  684                    "NAMESPACE_ERR", null));
  685       }
  686   
  687       /**
  688        * Introduced in DOM Level 2. <p>
  689        *
  690        * Returns the local part of the qualified name of this node.
  691        * For nodes created with a DOM Level 1 method, such as createElement
  692        * from the Document interface, and for nodes of any type other than
  693        * ELEMENT_NODE and ATTRIBUTE_NODE this is the same as the nodeName
  694        * attribute.
  695        * @since WD-DOM-Level-2-19990923
  696        * @see AttrNSImpl
  697        * @see ElementNSImpl
  698        */
  699       public String             getLocalName()
  700       {
  701           return null;
  702       }
  703   
  704       //
  705       // EventTarget support
  706       //
  707   
  708       public void addEventListener(String type, EventListener listener,
  709                                    boolean useCapture) {
  710           // simply forward to Document
  711           ownerDocument().addEventListener(this, type, listener, useCapture);
  712       }
  713   
  714       public void removeEventListener(String type, EventListener listener,
  715                                       boolean useCapture) {
  716           // simply forward to Document
  717           ownerDocument().removeEventListener(this, type, listener, useCapture);
  718       }
  719   
  720       public boolean dispatchEvent(Event event) {
  721           // simply forward to Document
  722           return ownerDocument().dispatchEvent(this, event);
  723       }
  724   
  725       //
  726       // Public DOM Level 3 methods
  727       //
  728   
  729       /**
  730        * The absolute base URI of this node or <code>null</code> if undefined.
  731        * This value is computed according to . However, when the
  732        * <code>Document</code> supports the feature "HTML" , the base URI is
  733        * computed using first the value of the href attribute of the HTML BASE
  734        * element if any, and the value of the <code>documentURI</code>
  735        * attribute from the <code>Document</code> interface otherwise.
  736        * <br> When the node is an <code>Element</code>, a <code>Document</code>
  737        * or a a <code>ProcessingInstruction</code>, this attribute represents
  738        * the properties [base URI] defined in . When the node is a
  739        * <code>Notation</code>, an <code>Entity</code>, or an
  740        * <code>EntityReference</code>, this attribute represents the
  741        * properties [declaration base URI] in the . How will this be affected
  742        * by resolution of relative namespace URIs issue?It's not.Should this
  743        * only be on Document, Element, ProcessingInstruction, Entity, and
  744        * Notation nodes, according to the infoset? If not, what is it equal to
  745        * on other nodes? Null? An empty string? I think it should be the
  746        * parent's.No.Should this be read-only and computed or and actual
  747        * read-write attribute?Read-only and computed (F2F 19 Jun 2000 and
  748        * teleconference 30 May 2001).If the base HTML element is not yet
  749        * attached to a document, does the insert change the Document.baseURI?
  750        * Yes. (F2F 26 Sep 2001)
  751        * @since DOM Level 3
  752        */
  753       public String getBaseURI() {
  754           return null;
  755       }
  756   
  757       /**
  758        * Compares a node with this node with regard to their position in the
  759        * tree and according to the document order. This order can be extended
  760        * by module that define additional types of nodes.
  761        * @param other The node to compare against this node.
  762        * @return Returns how the given node is positioned relatively to this
  763        *   node.
  764        * @since DOM Level 3
  765        * @deprecated
  766        */
  767       public short compareTreePosition(Node other) {
  768           // Questions of clarification for this method - to be answered by the
  769           // DOM WG.   Current assumptions listed - LM
  770           //
  771           // 1. How do ENTITY nodes compare?
  772           //    Current assumption: TREE_POSITION_DISCONNECTED, as ENTITY nodes
  773           //    aren't really 'in the tree'
  774           //
  775           // 2. How do NOTATION nodes compare?
  776           //    Current assumption: TREE_POSITION_DISCONNECTED, as NOTATION nodes
  777           //    aren't really 'in the tree'
  778           //
  779           // 3. Are TREE_POSITION_ANCESTOR and TREE_POSITION_DESCENDANT
  780           //    only relevant for nodes that are "part of the document tree"?
  781           //     <outer>
  782           //         <inner  myattr="true"/>
  783           //     </outer>
  784           //    Is the element node "outer" considered an ancestor of "myattr"?
  785           //    Current assumption: No.
  786           //
  787           // 4. How do children of ATTRIBUTE nodes compare (with eachother, or
  788           //    with children of other attribute nodes with the same element)
  789           //    Current assumption: Children of ATTRIBUTE nodes are treated as if
  790           //    they they are the attribute node itself, unless the 2 nodes
  791           //    are both children of the same attribute.
  792           //
  793           // 5. How does an ENTITY_REFERENCE node compare with it's children?
  794           //    Given the DOM, it should precede its children as an ancestor.
  795           //    Given "document order",  does it represent the same position?
  796           //    Current assumption: An ENTITY_REFERENCE node is an ancestor of its
  797           //    children.
  798           //
  799           // 6. How do children of a DocumentFragment compare?
  800           //    Current assumption: If both nodes are part of the same document
  801           //    fragment, there are compared as if they were part of a document.
  802   
  803   
  804           // If the nodes are the same...
  805           if (this==other)
  806             return (TREE_POSITION_SAME_NODE | TREE_POSITION_EQUIVALENT);
  807   
  808           // If either node is of type ENTITY or NOTATION, compare as disconnected
  809           short thisType = this.getNodeType();
  810           short otherType = other.getNodeType();
  811   
  812           // If either node is of type ENTITY or NOTATION, compare as disconnected
  813           if (thisType == Node.ENTITY_NODE ||
  814               thisType == Node.NOTATION_NODE ||
  815               otherType == Node.ENTITY_NODE ||
  816               otherType == Node.NOTATION_NODE ) {
  817             return TREE_POSITION_DISCONNECTED;
  818           }
  819   
  820           // Find the ancestor of each node, and the distance each node is from
  821           // its ancestor.
  822           // During this traversal, look for ancestor/descendent relationships
  823           // between the 2 nodes in question.
  824           // We do this now, so that we get this info correct for attribute nodes
  825           // and their children.
  826   
  827           Node node;
  828           Node thisAncestor = this;
  829           Node otherAncestor = other;
  830           int thisDepth=0;
  831           int otherDepth=0;
  832           for (node=this; node != null; node = node.getParentNode()) {
  833               thisDepth +=1;
  834               if (node == other)
  835                 // The other node is an ancestor of this one.
  836                 return (TREE_POSITION_ANCESTOR | TREE_POSITION_PRECEDING);
  837               thisAncestor = node;
  838           }
  839   
  840           for (node=other; node!=null; node=node.getParentNode()) {
  841               otherDepth +=1;
  842               if (node == this)
  843                 // The other node is a descendent of the reference node.
  844                 return (TREE_POSITION_DESCENDANT | TREE_POSITION_FOLLOWING);
  845               otherAncestor = node;
  846           }
  847   
  848   
  849           Node thisNode = this;
  850           Node otherNode = other;
  851   
  852           int thisAncestorType = thisAncestor.getNodeType();
  853           int otherAncestorType = otherAncestor.getNodeType();
  854   
  855           // if the ancestor is an attribute, get owning element.
  856           // we are now interested in the owner to determine position.
  857   
  858           if (thisAncestorType == Node.ATTRIBUTE_NODE)  {
  859              thisNode = ((AttrImpl)thisAncestor).getOwnerElement();
  860           }
  861           if (otherAncestorType == Node.ATTRIBUTE_NODE) {
  862              otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
  863           }
  864   
  865           // Before proceeding, we should check if both ancestor nodes turned
  866           // out to be attributes for the same element
  867           if (thisAncestorType == Node.ATTRIBUTE_NODE &&
  868               otherAncestorType == Node.ATTRIBUTE_NODE &&
  869               thisNode==otherNode)
  870               return TREE_POSITION_EQUIVALENT;
  871   
  872           // Now, find the ancestor of the owning element, if the original
  873           // ancestor was an attribute
  874   
  875           // Note:  the following 2 loops are quite close to the ones above.
  876           // May want to common them up.  LM.
  877           if (thisAncestorType == Node.ATTRIBUTE_NODE) {
  878               thisDepth=0;
  879               for (node=thisNode; node != null; node=node.getParentNode()) {
  880                   thisDepth +=1;
  881                   if (node == otherNode)
  882                     // The other node is an ancestor of the owning element
  883                     {
  884                     return TREE_POSITION_PRECEDING;
  885                     }
  886                   thisAncestor = node;
  887               }
  888           }
  889   
  890           // Now, find the ancestor of the owning element, if the original
  891           // ancestor was an attribute
  892           if (otherAncestorType == Node.ATTRIBUTE_NODE) {
  893               otherDepth=0;
  894               for (node=otherNode; node != null; node=node.getParentNode()) {
  895                   otherDepth +=1;
  896                   if (node == thisNode)
  897                     // The other node is a descendent of the reference
  898                     // node's element
  899                     return TREE_POSITION_FOLLOWING;
  900                   otherAncestor = node;
  901               }
  902           }
  903   
  904           // thisAncestor and otherAncestor must be the same at this point,
  905           // otherwise, we are not in the same tree or document fragment
  906           if (thisAncestor != otherAncestor)
  907             return TREE_POSITION_DISCONNECTED;
  908   
  909   
  910           // Go up the parent chain of the deeper node, until we find a node
  911           // with the same depth as the shallower node
  912   
  913           if (thisDepth > otherDepth) {
  914             for (int i=0; i<thisDepth - otherDepth; i++)
  915               thisNode = thisNode.getParentNode();
  916             // Check if the node we have reached is in fact "otherNode". This can
  917             // happen in the case of attributes.  In this case, otherNode
  918             // "precedes" this.
  919             if (thisNode == otherNode)
  920               return TREE_POSITION_PRECEDING;
  921           }
  922   
  923           else {
  924             for (int i=0; i<otherDepth - thisDepth; i++)
  925               otherNode = otherNode.getParentNode();
  926             // Check if the node we have reached is in fact "thisNode".  This can
  927             // happen in the case of attributes.  In this case, otherNode
  928             // "follows" this.
  929             if (otherNode == thisNode)
  930               return TREE_POSITION_FOLLOWING;
  931           }
  932   
  933           // We now have nodes at the same depth in the tree.  Find a common
  934           // ancestor.
  935           Node thisNodeP, otherNodeP;
  936           for (thisNodeP=thisNode.getParentNode(),
  937                     otherNodeP=otherNode.getParentNode();
  938                thisNodeP!=otherNodeP;) {
  939                thisNode = thisNodeP;
  940                otherNode = otherNodeP;
  941                thisNodeP = thisNodeP.getParentNode();
  942                otherNodeP = otherNodeP.getParentNode();
  943           }
  944   
  945           // At this point, thisNode and otherNode are direct children of
  946           // the common ancestor.
  947           // See whether thisNode or otherNode is the leftmost
  948   
  949           for (Node current=thisNodeP.getFirstChild();
  950                     current!=null;
  951                     current=current.getNextSibling()) {
  952                  if (current==otherNode) {
  953                    return TREE_POSITION_PRECEDING;
  954                  }
  955                  else if (current==thisNode) {
  956                    return TREE_POSITION_FOLLOWING;
  957                  }
  958           }
  959           // REVISIT:  shouldn't get here.   Should probably throw an
  960           // exception
  961           return 0;
  962   
  963       }
  964       /**
  965        * Compares a node with this node with regard to their position in the
  966        * document.
  967        * @param other The node to compare against this node.
  968        * @return Returns how the given node is positioned relatively to this
  969        *   node.
  970        * @since DOM Level 3
  971        */
  972       public short compareDocumentPosition(Node other) throws DOMException {
  973   
  974           // If the nodes are the same, no flags should be set
  975           if (this==other)
  976             return 0;
  977   
  978           // check if other is from a different implementation
  979           try {
  980               NodeImpl node = (NodeImpl) other;
  981           } catch (ClassCastException e) {
  982               // other comes from a different implementation
  983               String msg = DOMMessageFormatter.formatMessage(
  984                  DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
  985               throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
  986           }
  987   
  988           Document thisOwnerDoc, otherOwnerDoc;
  989           // get the respective Document owners.
  990           if (this.getNodeType() == Node.DOCUMENT_NODE)
  991             thisOwnerDoc = (Document)this;
  992           else
  993             thisOwnerDoc = this.getOwnerDocument();
  994           if (other.getNodeType() == Node.DOCUMENT_NODE)
  995             otherOwnerDoc = (Document)other;
  996           else
  997             otherOwnerDoc = other.getOwnerDocument();
  998   
  999           // If from different documents, we know they are disconnected.
 1000           // and have an implementation dependent order
 1001           if (thisOwnerDoc != otherOwnerDoc &&
 1002               thisOwnerDoc !=null &&
 1003               otherOwnerDoc !=null)
 1004    {
 1005             int otherDocNum = ((CoreDocumentImpl)otherOwnerDoc).getNodeNumber();
 1006             int thisDocNum = ((CoreDocumentImpl)thisOwnerDoc).getNodeNumber();
 1007             if (otherDocNum > thisDocNum)
 1008               return DOCUMENT_POSITION_DISCONNECTED |
 1009                      DOCUMENT_POSITION_FOLLOWING |
 1010                      DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
 1011             else
 1012               return DOCUMENT_POSITION_DISCONNECTED |
 1013                      DOCUMENT_POSITION_PRECEDING |
 1014                      DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
 1015   
 1016           }
 1017   
 1018           // Find the ancestor of each node, and the distance each node is from
 1019           // its ancestor.
 1020           // During this traversal, look for ancestor/descendent relationships
 1021           // between the 2 nodes in question.
 1022           // We do this now, so that we get this info correct for attribute nodes
 1023           // and their children.
 1024   
 1025           Node node;
 1026           Node thisAncestor = this;
 1027           Node otherAncestor = other;
 1028   
 1029           int thisDepth=0;
 1030           int otherDepth=0;
 1031           for (node=this; node != null; node = node.getParentNode()) {
 1032               thisDepth +=1;
 1033               if (node == other)
 1034                 // The other node is an ancestor of this one.
 1035                 return (DOCUMENT_POSITION_CONTAINS |
 1036                         DOCUMENT_POSITION_PRECEDING);
 1037               thisAncestor = node;
 1038           }
 1039   
 1040           for (node=other; node!=null; node=node.getParentNode()) {
 1041               otherDepth +=1;
 1042               if (node == this)
 1043                 // The other node is a descendent of the reference node.
 1044                 return (DOCUMENT_POSITION_IS_CONTAINED |
 1045                         DOCUMENT_POSITION_FOLLOWING);
 1046               otherAncestor = node;
 1047           }
 1048   
 1049   
 1050   
 1051           int thisAncestorType = thisAncestor.getNodeType();
 1052           int otherAncestorType = otherAncestor.getNodeType();
 1053           Node thisNode = this;
 1054           Node otherNode = other;
 1055   
 1056           // Special casing for ENTITY, NOTATION, DOCTYPE and ATTRIBUTES
 1057           // LM:  should rewrite this.
 1058           switch (thisAncestorType) {
 1059             case Node.NOTATION_NODE:
 1060             case Node.ENTITY_NODE: {
 1061               DocumentType container = thisOwnerDoc.getDoctype();
 1062               if (container == otherAncestor) return
 1063                      (DOCUMENT_POSITION_CONTAINS | DOCUMENT_POSITION_PRECEDING);
 1064               switch (otherAncestorType) {
 1065                 case Node.NOTATION_NODE:
 1066                 case Node.ENTITY_NODE:  {
 1067                   if (thisAncestorType != otherAncestorType)
 1068                    // the nodes are of different types
 1069                    return ((thisAncestorType>otherAncestorType) ?
 1070                       DOCUMENT_POSITION_PRECEDING:DOCUMENT_POSITION_FOLLOWING);
 1071                   else {
 1072                    // the nodes are of the same type.  Find order.
 1073                    if (thisAncestorType == Node.NOTATION_NODE)
 1074   
 1075                        if (((NamedNodeMapImpl)container.getNotations()).precedes(otherAncestor,thisAncestor))
 1076                          return (DOCUMENT_POSITION_PRECEDING |
 1077                                  DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
 1078                        else
 1079                          return (DOCUMENT_POSITION_FOLLOWING |
 1080                                  DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
 1081                    else
 1082                        if (((NamedNodeMapImpl)container.getEntities()).precedes(otherAncestor,thisAncestor))
 1083                          return (DOCUMENT_POSITION_PRECEDING |
 1084                                  DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
 1085                        else
 1086                          return (DOCUMENT_POSITION_FOLLOWING |
 1087                                  DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
 1088                   }
 1089                 }
 1090               }
 1091               thisNode = thisAncestor = thisOwnerDoc;
 1092               break;
 1093             }
 1094             case Node.DOCUMENT_TYPE_NODE: {
 1095               if (otherNode == thisOwnerDoc)
 1096                 return (DOCUMENT_POSITION_PRECEDING |
 1097                         DOCUMENT_POSITION_CONTAINS);
 1098               else if (thisOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc)
 1099                 return (DOCUMENT_POSITION_FOLLOWING);
 1100               break;
 1101             }
 1102             case Node.ATTRIBUTE_NODE: {
 1103               thisNode = ((AttrImpl)thisAncestor).getOwnerElement();
 1104               if (otherAncestorType==Node.ATTRIBUTE_NODE) {
 1105                 otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
 1106                 if (otherNode == thisNode) {
 1107                   if (((NamedNodeMapImpl)thisNode.getAttributes()).precedes(other,this))
 1108                     return (DOCUMENT_POSITION_PRECEDING |
 1109                             DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
 1110                   else
 1111                     return (DOCUMENT_POSITION_FOLLOWING |
 1112                             DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
 1113                 }
 1114               }
 1115   
 1116               // Now, find the ancestor of the element
 1117               thisDepth=0;
 1118               for (node=thisNode; node != null; node=node.getParentNode()) {
 1119                   thisDepth +=1;
 1120                   if (node == otherNode)
 1121                     {
 1122                     // The other node is an ancestor of the owning element
 1123                     return (DOCUMENT_POSITION_CONTAINS |
 1124                             DOCUMENT_POSITION_PRECEDING);
 1125                     }
 1126                   thisAncestor = node;
 1127               }
 1128             }
 1129           }
 1130           switch (otherAncestorType) {
 1131             case Node.NOTATION_NODE:
 1132             case Node.ENTITY_NODE: {
 1133             DocumentType container = thisOwnerDoc.getDoctype();
 1134               if (container == this) return (DOCUMENT_POSITION_IS_CONTAINED |
 1135                                             DOCUMENT_POSITION_FOLLOWING);
 1136               otherNode = otherAncestor = thisOwnerDoc;
 1137               break;
 1138             }
 1139             case Node.DOCUMENT_TYPE_NODE: {
 1140               if (thisNode == otherOwnerDoc)
 1141                 return (DOCUMENT_POSITION_FOLLOWING |
 1142                         DOCUMENT_POSITION_IS_CONTAINED);
 1143               else if (otherOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc)
 1144                 return (DOCUMENT_POSITION_PRECEDING);
 1145               break;
 1146             }
 1147             case Node.ATTRIBUTE_NODE: {
 1148               otherDepth=0;
 1149               otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
 1150               for (node=otherNode; node != null; node=node.getParentNode()) {
 1151                   otherDepth +=1;
 1152                   if (node == thisNode)
 1153                     // The other node is a descendent of the reference
 1154                     // node's element
 1155                     return DOCUMENT_POSITION_FOLLOWING |
 1156                            DOCUMENT_POSITION_IS_CONTAINED;
 1157                   otherAncestor = node;
 1158               }
 1159   
 1160             }
 1161           }
 1162   
 1163           // thisAncestor and otherAncestor must be the same at this point,
 1164           // otherwise, the original nodes are disconnected
 1165           if (thisAncestor != otherAncestor) {
 1166             int thisAncestorNum, otherAncestorNum;
 1167             thisAncestorNum = ((NodeImpl)thisAncestor).getNodeNumber();
 1168             otherAncestorNum = ((NodeImpl)otherAncestor).getNodeNumber();
 1169   
 1170             if (thisAncestorNum > otherAncestorNum)
 1171               return DOCUMENT_POSITION_DISCONNECTED |
 1172                      DOCUMENT_POSITION_FOLLOWING |
 1173                      DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
 1174             else
 1175               return DOCUMENT_POSITION_DISCONNECTED |
 1176                      DOCUMENT_POSITION_PRECEDING |
 1177                      DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
 1178           }
 1179   
 1180   
 1181           // Go up the parent chain of the deeper node, until we find a node
 1182           // with the same depth as the shallower node
 1183   
 1184           if (thisDepth > otherDepth) {
 1185             for (int i=0; i<thisDepth - otherDepth; i++)
 1186               thisNode = thisNode.getParentNode();
 1187             // Check if the node we have reached is in fact "otherNode". This can
 1188             // happen in the case of attributes.  In this case, otherNode
 1189             // "precedes" this.
 1190             if (thisNode == otherNode)
 1191   {
 1192               return DOCUMENT_POSITION_PRECEDING;
 1193             }
 1194           }
 1195   
 1196           else {
 1197             for (int i=0; i<otherDepth - thisDepth; i++)
 1198               otherNode = otherNode.getParentNode();
 1199             // Check if the node we have reached is in fact "thisNode".  This can
 1200             // happen in the case of attributes.  In this case, otherNode
 1201             // "follows" this.
 1202             if (otherNode == thisNode)
 1203               return DOCUMENT_POSITION_FOLLOWING;
 1204           }
 1205   
 1206           // We now have nodes at the same depth in the tree.  Find a common
 1207           // ancestor.
 1208           Node thisNodeP, otherNodeP;
 1209           for (thisNodeP=thisNode.getParentNode(),
 1210                     otherNodeP=otherNode.getParentNode();
 1211                thisNodeP!=otherNodeP;) {
 1212                thisNode = thisNodeP;
 1213                otherNode = otherNodeP;
 1214                thisNodeP = thisNodeP.getParentNode();
 1215                otherNodeP = otherNodeP.getParentNode();
 1216           }
 1217   
 1218           // At this point, thisNode and otherNode are direct children of
 1219           // the common ancestor.
 1220           // See whether thisNode or otherNode is the leftmost
 1221   
 1222           for (Node current=thisNodeP.getFirstChild();
 1223                     current!=null;
 1224                     current=current.getNextSibling()) {
 1225                  if (current==otherNode) {
 1226                    return DOCUMENT_POSITION_PRECEDING;
 1227                  }
 1228                  else if (current==thisNode) {
 1229                    return DOCUMENT_POSITION_FOLLOWING;
 1230                  }
 1231           }
 1232           // REVISIT:  shouldn't get here.   Should probably throw an
 1233           // exception
 1234           return 0;
 1235   
 1236       }
 1237   
 1238       /**
 1239        * This attribute returns the text content of this node and its
 1240        * descendants. When it is defined to be null, setting it has no effect.
 1241        * When set, any possible children this node may have are removed and
 1242        * replaced by a single <code>Text</code> node containing the string
 1243        * this attribute is set to. On getting, no serialization is performed,
 1244        * the returned string does not contain any markup. No whitespace
 1245        * normalization is performed, the returned string does not contain the
 1246        * element content whitespaces . Similarly, on setting, no parsing is
 1247        * performed either, the input string is taken as pure textual content.
 1248        * <br>The string returned is made of the text content of this node
 1249        * depending on its type, as defined below:
 1250        * <table border='1'>
 1251        * <tr>
 1252        * <th>Node type</th>
 1253        * <th>Content</th>
 1254        * </tr>
 1255   
 1256       /**
 1257        * This attribute returns the text content of this node and its
 1258        * descendants. When it is defined to be null, setting it has no effect.
 1259        * When set, any possible children this node may have are removed and
 1260        * replaced by a single <code>Text</code> node containing the string
 1261        * this attribute is set to. On getting, no serialization is performed,
 1262        * the returned string does not contain any markup. No whitespace
 1263        * normalization is performed, the returned string does not contain the
 1264        * element content whitespaces . Similarly, on setting, no parsing is
 1265        * performed either, the input string is taken as pure textual content.
 1266        * <br>The string returned is made of the text content of this node
 1267        * depending on its type, as defined below:
 1268        * <table border='1'>
 1269        * <tr>
 1270        * <th>Node type</th>
 1271        * <th>Content</th>
 1272        * </tr>
 1273        * <tr>
 1274        * <td valign='top' rowspan='1' colspan='1'>
 1275        * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
 1276        * DOCUMENT_FRAGMENT_NODE</td>
 1277        * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code>
 1278        * attribute value of every child node, excluding COMMENT_NODE and
 1279        * PROCESSING_INSTRUCTION_NODE nodes</td>
 1280        * </tr>
 1281        * <tr>
 1282        * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE,
 1283        * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
 1284        * <td valign='top' rowspan='1' colspan='1'>
 1285        * <code>nodeValue</code></td>
 1286        * </tr>
 1287        * <tr>
 1288        * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
 1289        * <td valign='top' rowspan='1' colspan='1'>
 1290        * null</td>
 1291        * </tr>
 1292        * </table>
 1293        * @exception DOMException
 1294        *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
 1295        * @exception DOMException
 1296        *   DOMSTRING_SIZE_ERR: Raised when it would return more characters than
 1297        *   fit in a <code>DOMString</code> variable on the implementation
 1298        *   platform.
 1299        * @since DOM Level 3
 1300        */
 1301       public String getTextContent() throws DOMException {
 1302           return getNodeValue();  // overriden in some subclasses
 1303       }
 1304   
 1305       // internal method taking a StringBuffer in parameter
 1306       void getTextContent(StringBuffer buf) throws DOMException {
 1307           String content = getNodeValue();
 1308           if (content != null) {
 1309               buf.append(content);
 1310           }
 1311       }
 1312   
 1313       /**
 1314        * This attribute returns the text content of this node and its
 1315        * descendants. When it is defined to be null, setting it has no effect.
 1316        * When set, any possible children this node may have are removed and
 1317        * replaced by a single <code>Text</code> node containing the string
 1318        * this attribute is set to. On getting, no serialization is performed,
 1319        * the returned string does not contain any markup. No whitespace
 1320        * normalization is performed, the returned string does not contain the
 1321        * element content whitespaces . Similarly, on setting, no parsing is
 1322        * performed either, the input string is taken as pure textual content.
 1323        * <br>The string returned is made of the text content of this node
 1324        * depending on its type, as defined below:
 1325        * <table border='1'>
 1326        * <tr>
 1327        * <th>Node type</th>
 1328        * <th>Content</th>
 1329        * </tr>
 1330        * <tr>
 1331        * <td valign='top' rowspan='1' colspan='1'>
 1332        * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
 1333        * DOCUMENT_FRAGMENT_NODE</td>
 1334        * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code>
 1335        * attribute value of every child node, excluding COMMENT_NODE and
 1336        * PROCESSING_INSTRUCTION_NODE nodes</td>
 1337        * </tr>
 1338        * <tr>
 1339        * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE,
 1340        * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
 1341        * <td valign='top' rowspan='1' colspan='1'>
 1342        * <code>nodeValue</code></td>
 1343        * </tr>
 1344        * <tr>
 1345        * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
 1346        * <td valign='top' rowspan='1' colspan='1'>
 1347        * null</td>
 1348        * </tr>
 1349        * </table>
 1350        * @exception DOMException
 1351        *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
 1352        * @exception DOMException
 1353        *   DOMSTRING_SIZE_ERR: Raised when it would return more characters than
 1354        *   fit in a <code>DOMString</code> variable on the implementation
 1355        *   platform.
 1356        * @since DOM Level 3
 1357        */
 1358       public void setTextContent(String textContent)
 1359           throws DOMException {
 1360           setNodeValue(textContent);
 1361       }
 1362   
 1363       /**
 1364        * Returns whether this node is the same node as the given one.
 1365        * <br>This method provides a way to determine whether two
 1366        * <code>Node</code> references returned by the implementation reference
 1367        * the same object. When two <code>Node</code> references are references
 1368        * to the same object, even if through a proxy, the references may be
 1369        * used completely interchangably, such that all attributes have the
 1370        * same values and calling the same DOM method on either reference
 1371        * always has exactly the same effect.
 1372        * @param other The node to test against.
 1373        * @return Returns <code>true</code> if the nodes are the same,
 1374        *   <code>false</code> otherwise.
 1375        * @since DOM Level 3
 1376        */
 1377       public boolean isSameNode(Node other) {
 1378           // we do not use any wrapper so the answer is obvious
 1379           return this == other;
 1380       }
 1381   
 1382   
 1383   
 1384   
 1385       /**
 1386        *  DOM Level 3: Experimental
 1387        *  This method checks if the specified <code>namespaceURI</code> is the
 1388        *  default namespace or not.
 1389        *  @param namespaceURI The namespace URI to look for.
 1390        *  @return  <code>true</code> if the specified <code>namespaceURI</code>
 1391        *   is the default namespace, <code>false</code> otherwise.
 1392        * @since DOM Level 3
 1393        */
 1394       public boolean isDefaultNamespace(String namespaceURI){
 1395           // REVISIT: remove casts when DOM L3 becomes REC.
 1396           short type = this.getNodeType();
 1397           switch (type) {
 1398           case Node.ELEMENT_NODE: {
 1399               String namespace = this.getNamespaceURI();
 1400               String prefix = this.getPrefix();
 1401   
 1402               // REVISIT: is it possible that prefix is empty string?
 1403               if (prefix == null || prefix.length() == 0) {
 1404                   if (namespaceURI == null) {
 1405                       return (namespace == namespaceURI);
 1406                   }
 1407                   return namespaceURI.equals(namespace);
 1408               }
 1409               if (this.hasAttributes()) {
 1410                   ElementImpl elem = (ElementImpl)this;
 1411                   NodeImpl attr = (NodeImpl)elem.getAttributeNodeNS("http://www.w3.org/2000/xmlns/", "xmlns");
 1412                   if (attr != null) {
 1413                       String value = attr.getNodeValue();
 1414                       if (namespaceURI == null) {
 1415                           return (namespace == value);
 1416                       }
 1417                       return namespaceURI.equals(value);
 1418                   }
 1419               }
 1420   
 1421               NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
 1422               if (ancestor != null) {
 1423                   return ancestor.isDefaultNamespace(namespaceURI);
 1424               }
 1425               return false;
 1426           }
 1427           case Node.DOCUMENT_NODE:{
 1428                   return((NodeImpl)((Document)this).getDocumentElement()).isDefaultNamespace(namespaceURI);
 1429               }
 1430   
 1431           case Node.ENTITY_NODE :
 1432           case Node.NOTATION_NODE:
 1433           case Node.DOCUMENT_FRAGMENT_NODE:
 1434           case Node.DOCUMENT_TYPE_NODE:
 1435               // type is unknown
 1436               return false;
 1437           case Node.ATTRIBUTE_NODE:{
 1438                   if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
 1439                       return ownerNode.isDefaultNamespace(namespaceURI);
 1440   
 1441                   }
 1442                   return false;
 1443               }
 1444           default:{
 1445                   NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
 1446                   if (ancestor != null) {
 1447                       return ancestor.isDefaultNamespace(namespaceURI);
 1448                   }
 1449                   return false;
 1450               }
 1451   
 1452           }
 1453   
 1454   
 1455       }
 1456   
 1457   
 1458       /**
 1459        *
 1460        * DOM Level 3 - Experimental:
 1461        * Look up the prefix associated to the given namespace URI, starting from this node.
 1462        *
 1463        * @param namespaceURI
 1464        * @return the prefix for the namespace
 1465        */
 1466       public String lookupPrefix(String namespaceURI){
 1467   
 1468           // REVISIT: When Namespaces 1.1 comes out this may not be true
 1469           // Prefix can't be bound to null namespace
 1470           if (namespaceURI == null) {
 1471               return null;
 1472           }
 1473   
 1474           short type = this.getNodeType();
 1475   
 1476           switch (type) {
 1477           case Node.ELEMENT_NODE: {
 1478   
 1479                   String namespace = this.getNamespaceURI(); // to flip out children
 1480                   return lookupNamespacePrefix(namespaceURI, (ElementImpl)this);
 1481               }
 1482           case Node.DOCUMENT_NODE:{
 1483                   return((NodeImpl)((Document)this).getDocumentElement()).lookupPrefix(namespaceURI);
 1484               }
 1485   
 1486           case Node.ENTITY_NODE :
 1487           case Node.NOTATION_NODE:
 1488           case Node.DOCUMENT_FRAGMENT_NODE:
 1489           case Node.DOCUMENT_TYPE_NODE:
 1490               // type is unknown
 1491               return null;
 1492           case Node.ATTRIBUTE_NODE:{
 1493                   if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
 1494                       return ownerNode.lookupPrefix(namespaceURI);
 1495   
 1496                   }
 1497                   return null;
 1498               }
 1499           default:{
 1500                   NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
 1501                   if (ancestor != null) {
 1502                       return ancestor.lookupPrefix(namespaceURI);
 1503                   }
 1504                   return null;
 1505               }
 1506   
 1507           }
 1508       }
 1509       /**
 1510        * DOM Level 3 - Experimental:
 1511        * Look up the namespace URI associated to the given prefix, starting from this node.
 1512        * Use lookupNamespaceURI(null) to lookup the default namespace
 1513        *
 1514        * @param namespaceURI
 1515        * @return th URI for the namespace
 1516        * @since DOM Level 3
 1517        */
 1518       public String lookupNamespaceURI(String specifiedPrefix) {
 1519           short type = this.getNodeType();
 1520           switch (type) {
 1521           case Node.ELEMENT_NODE : {
 1522   
 1523                   String namespace = this.getNamespaceURI();
 1524                   String prefix = this.getPrefix();
 1525                   if (namespace !=null) {
 1526                       // REVISIT: is it possible that prefix is empty string?
 1527                       if (specifiedPrefix== null && prefix==specifiedPrefix) {
 1528                           // looking for default namespace
 1529                           return namespace;
 1530                       } else if (prefix != null && prefix.equals(specifiedPrefix)) {
 1531                           // non default namespace
 1532                           return namespace;
 1533                       }
 1534                   }
 1535                   if (this.hasAttributes()) {
 1536                       NamedNodeMap map = this.getAttributes();
 1537                       int length = map.getLength();
 1538                       for (int i=0;i<length;i++) {
 1539                           Node attr = map.item(i);
 1540                           String attrPrefix = attr.getPrefix();
 1541                           String value = attr.getNodeValue();
 1542                           namespace = attr.getNamespaceURI();
 1543                           if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) {
 1544                               // at this point we are dealing with DOM Level 2 nodes only
 1545                               if (specifiedPrefix == null &&
 1546                                   attr.getNodeName().equals("xmlns")) {
 1547                                   // default namespace
 1548                                   return value;
 1549                               } else if (attrPrefix !=null &&
 1550                                          attrPrefix.equals("xmlns") &&
 1551                                          attr.getLocalName().equals(specifiedPrefix)) {
 1552                                   // non default namespace
 1553                                   return value;
 1554                               }
 1555                           }
 1556                       }
 1557                   }
 1558                   NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
 1559                   if (ancestor != null) {
 1560                       return ancestor.lookupNamespaceURI(specifiedPrefix);
 1561                   }
 1562   
 1563                   return null;
 1564   
 1565   
 1566               }
 1567           case Node.DOCUMENT_NODE : {
 1568                   return((NodeImpl)((Document)this).getDocumentElement()).lookupNamespaceURI(specifiedPrefix);
 1569               }
 1570           case Node.ENTITY_NODE :
 1571           case Node.NOTATION_NODE:
 1572           case Node.DOCUMENT_FRAGMENT_NODE:
 1573           case Node.DOCUMENT_TYPE_NODE:
 1574               // type is unknown
 1575               return null;
 1576           case Node.ATTRIBUTE_NODE:{
 1577                   if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
 1578                       return ownerNode.lookupNamespaceURI(specifiedPrefix);
 1579   
 1580                   }
 1581                   return null;
 1582               }
 1583           default:{
 1584                   NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
 1585                   if (ancestor != null) {
 1586                       return ancestor.lookupNamespaceURI(specifiedPrefix);
 1587                   }
 1588                   return null;
 1589               }
 1590   
 1591           }
 1592       }
 1593   
 1594   
 1595       Node getElementAncestor (Node currentNode){
 1596           Node parent = currentNode.getParentNode();
 1597           if (parent != null) {
 1598               short type = parent.getNodeType();
 1599               if (type == Node.ELEMENT_NODE) {
 1600                   return parent;
 1601               }
 1602               return getElementAncestor(parent);
 1603           }
 1604           return null;
 1605       }
 1606   
 1607       String lookupNamespacePrefix(String namespaceURI, ElementImpl el){
 1608           String namespace = this.getNamespaceURI();
 1609           // REVISIT: if no prefix is available is it null or empty string, or
 1610           //          could be both?
 1611           String prefix = this.getPrefix();
 1612   
 1613           if (namespace!=null && namespace.equals(namespaceURI)) {
 1614               if (prefix != null) {
 1615                   String foundNamespace =  el.lookupNamespaceURI(prefix);
 1616                   if (foundNamespace !=null && foundNamespace.equals(namespaceURI)) {
 1617                       return prefix;
 1618                   }
 1619   
 1620               }
 1621           }
 1622           if (this.hasAttributes()) {
 1623               NamedNodeMap map = this.getAttributes();
 1624               int length = map.getLength();
 1625               for (int i=0;i<length;i++) {
 1626                   Node attr = map.item(i);
 1627                   String attrPrefix = attr.getPrefix();
 1628                   String value = attr.getNodeValue();
 1629                   namespace = attr.getNamespaceURI();
 1630                   if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) {
 1631                       // DOM Level 2 nodes
 1632                       if (((attr.getNodeName().equals("xmlns")) ||
 1633                            (attrPrefix !=null && attrPrefix.equals("xmlns")) &&
 1634                            value.equals(namespaceURI))) {
 1635   
 1636                           String localname= attr.getLocalName();
 1637                           String foundNamespace = el.lookupNamespaceURI(localname);
 1638                           if (foundNamespace !=null && foundNamespace.equals(namespaceURI)) {
 1639                               return localname;
 1640                           }
 1641                       }
 1642   
 1643   
 1644                   }
 1645               }
 1646           }
 1647           NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
 1648   
 1649           if (ancestor != null) {
 1650               return ancestor.lookupNamespacePrefix(namespaceURI, el);
 1651           }
 1652           return null;
 1653       }
 1654   
 1655       /**
 1656        * Tests whether two nodes are equal.
 1657        * <br>This method tests for equality of nodes, not sameness (i.e.,
 1658        * whether the two nodes are references to the same object) which can be
 1659        * tested with <code>Node.isSameNode</code>. All nodes that are the same
 1660        * will also be equal, though the reverse may not be true.
 1661        * <br>Two nodes are equal if and only if the following conditions are
 1662        * satisfied: The two nodes are of the same type.The following string
 1663        * attributes are equal: <code>nodeName</code>, <code>localName</code>,
 1664        * <code>namespaceURI</code>, <code>prefix</code>, <code>nodeValue</code>
 1665        * , <code>baseURI</code>. This is: they are both <code>null</code>, or
 1666        * they have the same length and are character for character identical.
 1667        * The <code>attributes</code> <code>NamedNodeMaps</code> are equal.
 1668        * This is: they are both <code>null</code>, or they have the same
 1669        * length and for each node that exists in one map there is a node that
 1670        * exists in the other map and is equal, although not necessarily at the
 1671        * same index.The <code>childNodes</code> <code>NodeLists</code> are
 1672        * equal. This is: they are both <code>null</code>, or they have the
 1673        * same length and contain equal nodes at the same index. This is true
 1674        * for <code>Attr</code> nodes as for any other type of node. Note that
 1675        * normalization can affect equality; to avoid this, nodes should be
 1676        * normalized before being compared.
 1677        * <br>For two <code>DocumentType</code> nodes to be equal, the following
 1678        * conditions must also be satisfied: The following string attributes
 1679        * are equal: <code>publicId</code>, <code>systemId</code>,
 1680        * <code>internalSubset</code>.The <code>entities</code>
 1681        * <code>NamedNodeMaps</code> are equal.The <code>notations</code>
 1682        * <code>NamedNodeMaps</code> are equal.
 1683        * <br>On the other hand, the following do not affect equality: the
 1684        * <code>ownerDocument</code> attribute, the <code>specified</code>
 1685        * attribute for <code>Attr</code> nodes, the
 1686        * <code>isWhitespaceInElementContent</code> attribute for
 1687        * <code>Text</code> nodes, as well as any user data or event listeners
 1688        * registered on the nodes.
 1689        * @param arg The node to compare equality with.
 1690        * @param deep If <code>true</code>, recursively compare the subtrees; if
 1691        *   <code>false</code>, compare only the nodes themselves (and its
 1692        *   attributes, if it is an <code>Element</code>).
 1693        * @return If the nodes, and possibly subtrees are equal,
 1694        *   <code>true</code> otherwise <code>false</code>.
 1695        * @since DOM Level 3
 1696        */
 1697       public boolean isEqualNode(Node arg) {
 1698           if (arg == this) {
 1699               return true;
 1700           }
 1701           if (arg.getNodeType() != getNodeType()) {
 1702               return false;
 1703           }
 1704           // in theory nodeName can't be null but better be careful
 1705           // who knows what other implementations may be doing?...
 1706           if (getNodeName() == null) {
 1707               if (arg.getNodeName() != null) {
 1708                   return false;
 1709               }
 1710           }
 1711           else if (!getNodeName().equals(arg.getNodeName())) {
 1712               return false;
 1713           }
 1714   
 1715           if (getLocalName() == null) {
 1716               if (arg.getLocalName() != null) {
 1717                   return false;
 1718               }
 1719           }
 1720           else if (!getLocalName().equals(arg.getLocalName())) {
 1721               return false;
 1722           }
 1723   
 1724           if (getNamespaceURI() == null) {
 1725               if (arg.getNamespaceURI() != null) {
 1726                   return false;
 1727               }
 1728           }
 1729           else if (!getNamespaceURI().equals(arg.getNamespaceURI())) {
 1730               return false;
 1731           }
 1732   
 1733           if (getPrefix() == null) {
 1734               if (arg.getPrefix() != null) {
 1735                   return false;
 1736               }
 1737           }
 1738           else if (!getPrefix().equals(arg.getPrefix())) {
 1739               return false;
 1740           }
 1741   
 1742           if (getNodeValue() == null) {
 1743               if (arg.getNodeValue() != null) {
 1744                   return false;
 1745               }
 1746           }
 1747           else if (!getNodeValue().equals(arg.getNodeValue())) {
 1748               return false;
 1749           }
 1750   
 1751   
 1752           return true;
 1753       }
 1754   
 1755       /**
 1756        * @since DOM Level 3
 1757        */
 1758       public Object getFeature(String feature, String version) {
 1759           // we don't have any alternate node, either this node does the job
 1760           // or we don't have anything that does
 1761           return isSupported(feature, version) ? this : null;
 1762       }
 1763   
 1764       /**
 1765        * Associate an object to a key on this node. The object can later be
 1766        * retrieved from this node by calling <code>getUserData</code> with the
 1767        * same key.
 1768        * @param key The key to associate the object to.
 1769        * @param data The object to associate to the given key, or
 1770        *   <code>null</code> to remove any existing association to that key.
 1771        * @param handler The handler to associate to that key, or
 1772        *   <code>null</code>.
 1773        * @return Returns the <code>DOMObject</code> previously associated to
 1774        *   the given key on this node, or <code>null</code> if there was none.
 1775        * @since DOM Level 3
 1776        */
 1777       public Object setUserData(String key,
 1778                                 Object data,
 1779                                 UserDataHandler handler) {
 1780           return ownerDocument().setUserData(this, key, data, handler);
 1781       }
 1782   
 1783       /**
 1784        * Retrieves the object associated to a key on a this node. The object
 1785        * must first have been set to this node by calling
 1786        * <code>setUserData</code> with the same key.
 1787        * @param key The key the object is associated to.
 1788        * @return Returns the <code>DOMObject</code> associated to the given key
 1789        *   on this node, or <code>null</code> if there was none.
 1790        * @since DOM Level 3
 1791        */
 1792       public Object getUserData(String key) {
 1793           return ownerDocument().getUserData(this, key);
 1794       }
 1795   
 1796           protected Hashtable getUserDataRecord(){
 1797           return ownerDocument().getUserDataRecord(this);
 1798           }
 1799   
 1800       //
 1801       // Public methods
 1802       //
 1803   
 1804       /**
 1805        * NON-DOM: PR-DOM-Level-1-19980818 mentions readonly nodes in conjunction
 1806        * with Entities, but provides no API to support this.
 1807        * <P>
 1808        * Most DOM users should not touch this method. Its anticpated use
 1809        * is during construction of EntityRefernces, where it will be used to
 1810        * lock the contents replicated from Entity so they can't be casually
 1811        * altered. It _could_ be published as a DOM extension, if desired.
 1812        * <P>
 1813        * Note: since we never have any children deep is meaningless here,
 1814        * ParentNode overrides this behavior.
 1815        * @see ParentNode
 1816        *
 1817        * @param readOnly True or false as desired.
 1818        * @param deep If true, children are also toggled. Note that this will
 1819        *  not change the state of an EntityReference or its children,
 1820        *  which are always read-only.
 1821        */
 1822       public void setReadOnly(boolean readOnly, boolean deep) {
 1823   
 1824           if (needsSyncData()) {
 1825               synchronizeData();
 1826           }
 1827           isReadOnly(readOnly);
 1828   
 1829       } // setReadOnly(boolean,boolean)
 1830   
 1831       /**
 1832        * NON-DOM: Returns true if this node is read-only. This is a
 1833        * shallow check.
 1834        */
 1835       public boolean getReadOnly() {
 1836   
 1837           if (needsSyncData()) {
 1838               synchronizeData();
 1839           }
 1840           return isReadOnly();
 1841   
 1842       } // getReadOnly():boolean
 1843   
 1844       /**
 1845        * NON-DOM: As an alternative to subclassing the DOM, this implementation
 1846        * has been extended with the ability to attach an object to each node.
 1847        * (If you need multiple objects, you can attach a collection such as a
 1848        * vector or hashtable, then attach your application information to that.)
 1849        * <p><b>Important Note:</b> You are responsible for removing references
 1850        * to your data on nodes that are no longer used. Failure to do so will
 1851        * prevent the nodes, your data is attached to, to be garbage collected
 1852        * until the whole document is.
 1853        *
 1854        * @param data the object to store or null to remove any existing reference
 1855        */
 1856       public void setUserData(Object data) {
 1857           ownerDocument().setUserData(this, data);
 1858       }
 1859   
 1860       /**
 1861        * NON-DOM:
 1862        * Returns the user data associated to this node.
 1863        */
 1864       public Object getUserData() {
 1865           return ownerDocument().getUserData(this);
 1866       }
 1867   
 1868       //
 1869       // Protected methods
 1870       //
 1871   
 1872       /**
 1873        * Denotes that this node has changed.
 1874        */
 1875       protected void changed() {
 1876           // we do not actually store this information on every node, we only
 1877           // have a global indicator on the Document. Doing otherwise cost us too
 1878           // much for little gain.
 1879           ownerDocument().changed();
 1880       }
 1881   
 1882       /**
 1883        * Returns the number of changes to this node.
 1884        */
 1885       protected int changes() {
 1886           // we do not actually store this information on every node, we only
 1887           // have a global indicator on the Document. Doing otherwise cost us too
 1888           // much for little gain.
 1889           return ownerDocument().changes();
 1890       }
 1891   
 1892       /**
 1893        * Override this method in subclass to hook in efficient
 1894        * internal data structure.
 1895        */
 1896       protected void synchronizeData() {
 1897           // By default just change the flag to avoid calling this method again
 1898           needsSyncData(false);
 1899       }
 1900   
 1901       /**
 1902        * For non-child nodes, the node which "points" to this node.
 1903        * For example, the owning element for an attribute
 1904        */
 1905       protected Node getContainer() {
 1906          return null;
 1907       }
 1908   
 1909   
 1910       /*
 1911        * Flags setters and getters
 1912        */
 1913   
 1914       final boolean isReadOnly() {
 1915           return (flags & READONLY) != 0;
 1916       }
 1917   
 1918       final void isReadOnly(boolean value) {
 1919           flags = (short) (value ? flags | READONLY : flags & ~READONLY);
 1920       }
 1921   
 1922       final boolean needsSyncData() {
 1923           return (flags & SYNCDATA) != 0;
 1924       }
 1925   
 1926       final void needsSyncData(boolean value) {
 1927           flags = (short) (value ? flags | SYNCDATA : flags & ~SYNCDATA);
 1928       }
 1929   
 1930       final boolean needsSyncChildren() {
 1931           return (flags & SYNCCHILDREN) != 0;
 1932       }
 1933   
 1934       public final void needsSyncChildren(boolean value) {
 1935           flags = (short) (value ? flags | SYNCCHILDREN : flags & ~SYNCCHILDREN);
 1936       }
 1937   
 1938       final boolean isOwned() {
 1939           return (flags & OWNED) != 0;
 1940       }
 1941   
 1942       final void isOwned(boolean value) {
 1943           flags = (short) (value ? flags | OWNED : flags & ~OWNED);
 1944       }
 1945   
 1946       final boolean isFirstChild() {
 1947           return (flags & FIRSTCHILD) != 0;
 1948       }
 1949   
 1950       final void isFirstChild(boolean value) {
 1951           flags = (short) (value ? flags | FIRSTCHILD : flags & ~FIRSTCHILD);
 1952       }
 1953   
 1954       final boolean isSpecified() {
 1955           return (flags & SPECIFIED) != 0;
 1956       }
 1957   
 1958       final void isSpecified(boolean value) {
 1959           flags = (short) (value ? flags | SPECIFIED : flags & ~SPECIFIED);
 1960       }
 1961   
 1962       // inconsistent name to avoid clash with public method on TextImpl
 1963       final boolean internalIsIgnorableWhitespace() {
 1964           return (flags & IGNORABLEWS) != 0;
 1965       }
 1966   
 1967       final void isIgnorableWhitespace(boolean value) {
 1968           flags = (short) (value ? flags | IGNORABLEWS : flags & ~IGNORABLEWS);
 1969       }
 1970   
 1971       final boolean hasStringValue() {
 1972           return (flags & HASSTRING) != 0;
 1973       }
 1974   
 1975       final void hasStringValue(boolean value) {
 1976           flags = (short) (value ? flags | HASSTRING : flags & ~HASSTRING);
 1977       }
 1978   
 1979       final boolean isNormalized() {
 1980           return (flags & NORMALIZED) != 0;
 1981       }
 1982   
 1983       final void isNormalized(boolean value) {
 1984           // See if flag should propagate to parent.
 1985           if (!value && isNormalized() && ownerNode != null) {
 1986               ownerNode.isNormalized(false);
 1987           }
 1988           flags = (short) (value ?  flags | NORMALIZED : flags & ~NORMALIZED);
 1989       }
 1990   
 1991       final boolean isIdAttribute() {
 1992           return (flags & ID) != 0;
 1993       }
 1994   
 1995       final void isIdAttribute(boolean value) {
 1996           flags = (short) (value ? flags | ID : flags & ~ID);
 1997       }
 1998   
 1999       //
 2000       // Object methods
 2001       //
 2002   
 2003       /** NON-DOM method for debugging convenience. */
 2004       public String toString() {
 2005           return "["+getNodeName()+": "+getNodeValue()+"]";
 2006       }
 2007   
 2008       //
 2009       // Serialization methods
 2010       //
 2011   
 2012       /** Serialize object. */
 2013       private void writeObject(ObjectOutputStream out) throws IOException {
 2014   
 2015           // synchronize data
 2016           if (needsSyncData()) {
 2017               synchronizeData();
 2018           }
 2019           // write object
 2020           out.defaultWriteObject();
 2021   
 2022       } // writeObject(ObjectOutputStream)
 2023   
 2024   } // class NodeImpl

Save This Page
Home » openjdk-7 » com.sun.org.apache.xerces.internal » dom » [javadoc | source]