/*
 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
 */
 /*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.sun.org.apache.xerces.internal.dom;

import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Map;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.UserDataHandler;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;

/**
 * NodeImpl provides the basic structure of a DOM tree. It is never used
 * directly, but instead is subclassed to add type and data
 * information, and additional methods, appropriate to each node of
 * the tree. Only its subclasses should be instantiated -- and those,
 * with the exception of Document itself, only through a specific
 * Document's factory methods.
 * <P>
 * The Node interface provides shared behaviors such as siblings and
 * children, both for consistancy and so that the most common tree
 * operations may be performed without constantly having to downcast
 * to specific node types. When there is no obvious mapping for one of
 * these queries, it will respond with null.
 * Note that the default behavior is that children are forbidden. To
 * permit them, the subclass ParentNode overrides several methods.
 * <P>
 * NodeImpl also implements NodeList, so it can return itself in
 * response to the getChildNodes() query. This eliminiates the need
 * for a separate ChildNodeList object. Note that this is an
 * IMPLEMENTATION DETAIL; applications should _never_ assume that
 * this identity exists.
 * <P>
 * All nodes in a single document must originate
 * in that document. (Note that this is much tighter than "must be
 * same implementation") Nodes are all aware of their ownerDocument,
 * and attempts to mismatch will throw WRONG_DOCUMENT_ERR.
 * <P>
 * However, to save memory not all nodes always have a direct reference
 * to their ownerDocument. When a node is owned by another node it relies
 * on its owner to store its ownerDocument. Parent nodes always store it
 * though, so there is never more than one level of indirection.
 * And when a node doesn't have an owner, ownerNode refers to its
 * ownerDocument.
 * <p>
 * This class doesn't directly support mutation events, however, it still
 * implements the EventTarget interface and forward all related calls to the
 * document so that the document class do so.
 *
 * @xerces.internal
 *
 * @author Arnaud  Le Hors, IBM
 * @author Joe Kesselman, IBM
 * @since  PR-DOM-Level-1-19980818.
 */
public abstract class NodeImpl
    implements Node, NodeList, EventTarget, Cloneable, Serializable{

    //
    // Constants
    //


    // TreePosition Constants.
    // Taken from DOM L3 Node interface.
    /**
     * The node precedes the reference node.
     */
    public static final short TREE_POSITION_PRECEDING   = 0x01;
    /**
     * The node follows the reference node.
     */
    public static final short TREE_POSITION_FOLLOWING   = 0x02;
    /**
     * The node is an ancestor of the reference node.
     */
    public static final short TREE_POSITION_ANCESTOR    = 0x04;
    /**
     * The node is a descendant of the reference node.
     */
    public static final short TREE_POSITION_DESCENDANT  = 0x08;
    /**
     * The two nodes have an equivalent position. This is the case of two
     * attributes that have the same <code>ownerElement</code>, and two
     * nodes that are the same.
     */
    public static final short TREE_POSITION_EQUIVALENT  = 0x10;
    /**
     * The two nodes are the same. Two nodes that are the same have an
     * equivalent position, though the reverse may not be true.
     */
    public static final short TREE_POSITION_SAME_NODE   = 0x20;
    /**
     * The two nodes are disconnected, they do not have any common ancestor.
     * This is the case of two nodes that are not in the same document.
     */
    public static final short TREE_POSITION_DISCONNECTED = 0x00;


    // DocumentPosition
    public static final short DOCUMENT_POSITION_DISCONNECTED = 0x01;
    public static final short DOCUMENT_POSITION_PRECEDING = 0x02;
    public static final short DOCUMENT_POSITION_FOLLOWING = 0x04;
    public static final short DOCUMENT_POSITION_CONTAINS = 0x08;
    public static final short DOCUMENT_POSITION_IS_CONTAINED = 0x10;
    public static final short DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC = 0x20;

    /** Serialization version. */
    static final long serialVersionUID = -6316591992167219696L;

    // public

    /** Element definition node type. */
    public static final short ELEMENT_DEFINITION_NODE = 21;

    //
    // Data
    //

    // links

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

    // data

    protected short flags;

    protected final static short READONLY     = 0x1<<0;
    protected final static short SYNCDATA     = 0x1<<1;
    protected final static short SYNCCHILDREN = 0x1<<2;
    protected final static short OWNED        = 0x1<<3;
    protected final static short FIRSTCHILD   = 0x1<<4;
    protected final static short SPECIFIED    = 0x1<<5;
    protected final static short IGNORABLEWS  = 0x1<<6;
    protected final static short HASSTRING    = 0x1<<7;
    protected final static short NORMALIZED = 0x1<<8;
    protected final static short ID           = 0x1<<9;

    //
    // Constructors
    //

    /**
     * No public constructor; only subclasses of Node should be
     * instantiated, and those normally via a Document's factory methods
     * <p>
     * Every Node knows what Document it belongs to.
     */
    protected NodeImpl(CoreDocumentImpl ownerDocument) {
        // as long as we do not have any owner, ownerNode is our ownerDocument
        ownerNode = ownerDocument;
    } // <init>(CoreDocumentImpl)

    /** Constructor for serialization. */
    public NodeImpl() {}

    //
    // Node methods
    //

    /**
     * A short integer indicating what type of node this is. The named
     * constants for this value are defined in the org.w3c.dom.Node interface.
     */
    public abstract short getNodeType();

    /**
     * the name of this node.
     */
    public abstract String getNodeName();

    /**
     * Returns the node value.
     * @throws DOMException(DOMSTRING_SIZE_ERR)
     */
    public String getNodeValue()
        throws DOMException {
        return null;            // overridden in some subclasses
    }

    /**
     * Sets the node value.
     * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR)
     */
    public void setNodeValue(String x)
        throws DOMException {
        // Default behavior is to do nothing, overridden in some subclasses
    }

    /**
     * Adds a child node to the end of the list of children for this node.
     * Convenience shorthand for insertBefore(newChild,null).
     * @see #insertBefore(Node, Node)
     * <P>
     * By default we do not accept any children, ParentNode overrides this.
     * @see ParentNode
     *
     * @return newChild, in its new state (relocated, or emptied in the case of
     * DocumentNode.)
     *
     * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
     * type that shouldn't be a child of this node.
     *
     * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
     * different owner document than we do.
     *
     * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
     * read-only.
     */
    public Node appendChild(Node newChild) throws DOMException {
        return insertBefore(newChild, null);
    }

    /**
     * Returns a duplicate of a given node. You can consider this a
     * generic "copy constructor" for nodes. The newly returned object should
     * be completely independent of the source object's subtree, so changes
     * in one after the clone has been made will not affect the other.
     * <P>
     * Note: since we never have any children deep is meaningless here,
     * ParentNode overrides this behavior.
     * @see ParentNode
     *
     * <p>
     * Example: Cloning a Text node will copy both the node and the text it
     * contains.
     * <p>
     * Example: Cloning something that has children -- Element or Attr, for
     * example -- will _not_ clone those children unless a "deep clone"
     * has been requested. A shallow clone of an Attr node will yield an
     * empty Attr of the same name.
     * <p>
     * NOTE: Clones will always be read/write, even if the node being cloned
     * is read-only, to permit applications using only the DOM API to obtain
     * editable copies of locked portions of the tree.
     */
    public Node cloneNode(boolean deep) {

        if (needsSyncData()) {
            synchronizeData();
        }

        NodeImpl newnode;
        try {
            newnode = (NodeImpl)clone();
        }
        catch (CloneNotSupportedException e) {
            // if we get here we have an error in our program we may as well
            // be vocal about it, so that people can take appropriate action.
            throw new RuntimeException("**Internal Error**" + e);
        }

        // Need to break the association w/ original kids
        newnode.ownerNode      = ownerDocument();
        newnode.isOwned(false);

        // By default we make all clones readwrite,
        // this is overriden in readonly subclasses
        newnode.isReadOnly(false);

        ownerDocument().callUserDataHandlers(this, newnode,
                                             UserDataHandler.NODE_CLONED);

        return newnode;

    } // cloneNode(boolean):Node

    /**
     * Find the Document that this Node belongs to (the document in
     * whose context the Node was created). The Node may or may not
     * currently be part of that Document's actual contents.
     */
    public Document getOwnerDocument() {
        // if we have an owner simply forward the request
        // otherwise ownerNode is our ownerDocument
        if (isOwned()) {
            return ownerNode.ownerDocument();
        } else {
            return (Document) ownerNode;
        }
    }

    /**
     * same as above but returns internal type and this one is not overridden
     * by CoreDocumentImpl to return null
     */
    CoreDocumentImpl ownerDocument() {
        // if we have an owner simply forward the request
        // otherwise ownerNode is our ownerDocument
        if (isOwned()) {
            return ownerNode.ownerDocument();
        } else {
            return (CoreDocumentImpl) ownerNode;
        }
    }

    /**
     * NON-DOM
     * set the ownerDocument of this node
     */
    void setOwnerDocument(CoreDocumentImpl doc) {
        if (needsSyncData()) {
            synchronizeData();
        }
        // if we have an owner we rely on it to have it right
        // otherwise ownerNode is our ownerDocument
        if (!isOwned()) {
            ownerNode = doc;
        }
    }

    /**
     * Returns the node number
     */
    protected int getNodeNumber() {
        int nodeNumber;
        CoreDocumentImpl cd = (CoreDocumentImpl)(this.getOwnerDocument());
        nodeNumber = cd.getNodeNumber(this);
        return nodeNumber;
    }

    /**
     * Obtain the DOM-tree parent of this node, or null if it is not
     * currently active in the DOM tree (perhaps because it has just been
     * created or removed). Note that Document, DocumentFragment, and
     * Attribute will never have parents.
     */
    public Node getParentNode() {
        return null;            // overriden by ChildNode
    }

    /*
     * same as above but returns internal type
     */
    NodeImpl parentNode() {
        return null;
    }

    /** The next child of this node's parent, or null if none */
    public Node getNextSibling() {
        return null;            // default behavior, overriden in ChildNode
    }

    /** The previous child of this node's parent, or null if none */
    public Node getPreviousSibling() {
        return null;            // default behavior, overriden in ChildNode
    }

    ChildNode previousSibling() {
        return null;            // default behavior, overriden in ChildNode
    }

    /**
     * Return the collection of attributes associated with this node,
     * or null if none. At this writing, Element is the only type of node
     * which will ever have attributes.
     *
     * @see ElementImpl
     */
    public NamedNodeMap getAttributes() {
        return null; // overridden in ElementImpl
    }

    /**
     *  Returns whether this node (if it is an element) has any attributes.
     * @return <code>true</code> if this node has any attributes,
     *   <code>false</code> otherwise.
     * @since DOM Level 2
     * @see ElementImpl
     */
    public boolean hasAttributes() {
        return false;           // overridden in ElementImpl
    }

    /**
     * Test whether this node has any children. Convenience shorthand
     * for (Node.getFirstChild()!=null)
     * <P>
     * By default we do not have any children, ParentNode overrides this.
     * @see ParentNode
     */
    public boolean hasChildNodes() {
        return false;
    }

    /**
     * Obtain a NodeList enumerating all children of this node. If there
     * are none, an (initially) empty NodeList is returned.
     * <p>
     * NodeLists are "live"; as children are added/removed the NodeList
     * will immediately reflect those changes. Also, the NodeList refers
     * to the actual nodes, so changes to those nodes made via the DOM tree
     * will be reflected in the NodeList and vice versa.
     * <p>
     * In this implementation, Nodes implement the NodeList interface and
     * provide their own getChildNodes() support. Other DOMs may solve this
     * differently.
     */
    public NodeList getChildNodes() {
        return this;
    }

    /** The first child of this Node, or null if none.
     * <P>
     * By default we do not have any children, ParentNode overrides this.
     * @see ParentNode
     */
    public Node getFirstChild() {
        return null;
    }

    /** The first child of this Node, or null if none.
     * <P>
     * By default we do not have any children, ParentNode overrides this.
     * @see ParentNode
     */
    public Node getLastChild() {
        return null;
    }

    /**
     * Move one or more node(s) to our list of children. Note that this
     * implicitly removes them from their previous parent.
     * <P>
     * By default we do not accept any children, ParentNode overrides this.
     * @see ParentNode
     *
     * @param newChild The Node to be moved to our subtree. As a
     * convenience feature, inserting a DocumentNode will instead insert
     * all its children.
     *
     * @param refChild Current child which newChild should be placed
     * immediately before. If refChild is null, the insertion occurs
     * after all existing Nodes, like appendChild().
     *
     * @return newChild, in its new state (relocated, or emptied in the case of
     * DocumentNode.)
     *
     * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
     * type that shouldn't be a child of this node, or if newChild is an
     * ancestor of this node.
     *
     * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
     * different owner document than we do.
     *
     * @throws DOMException(NOT_FOUND_ERR) if refChild is not a child of
     * this node.
     *
     * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
     * read-only.
     */
    public Node insertBefore(Node newChild, Node refChild)
        throws DOMException {
        throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
              DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
                 "HIERARCHY_REQUEST_ERR", null));
    }

    /**
     * Remove a child from this Node. The removed child's subtree
     * remains intact so it may be re-inserted elsewhere.
     * <P>
     * By default we do not have any children, ParentNode overrides this.
     * @see ParentNode
     *
     * @return oldChild, in its new state (removed).
     *
     * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
     * this node.
     *
     * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
     * read-only.
     */
    public Node removeChild(Node oldChild)
                throws DOMException {
        throw new DOMException(DOMException.NOT_FOUND_ERR,
              DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
                 "NOT_FOUND_ERR", null));
    }

    /**
     * Make newChild occupy the location that oldChild used to
     * have. Note that newChild will first be removed from its previous
     * parent, if any. Equivalent to inserting newChild before oldChild,
     * then removing oldChild.
     * <P>
     * By default we do not have any children, ParentNode overrides this.
     * @see ParentNode
     *
     * @return oldChild, in its new state (removed).
     *
     * @throws DOMException(HIERARCHY_REQUEST_ERR) if newChild is of a
     * type that shouldn't be a child of this node, or if newChild is
     * one of our ancestors.
     *
     * @throws DOMException(WRONG_DOCUMENT_ERR) if newChild has a
     * different owner document than we do.
     *
     * @throws DOMException(NOT_FOUND_ERR) if oldChild is not a child of
     * this node.
     *
     * @throws DOMException(NO_MODIFICATION_ALLOWED_ERR) if this node is
     * read-only.
     */
    public Node replaceChild(Node newChild, Node oldChild)
        throws DOMException {
        throw new DOMException(DOMException.HIERARCHY_REQUEST_ERR,
              DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
                 "HIERARCHY_REQUEST_ERR", null));
    }

    //
    // NodeList methods
    //

    /**
     * NodeList method: Count the immediate children of this node
     * <P>
     * By default we do not have any children, ParentNode overrides this.
     * @see ParentNode
     *
     * @return int
     */
    public int getLength() {
        return 0;
    }

    /**
     * NodeList method: Return the Nth immediate child of this node, or
     * null if the index is out of bounds.
     * <P>
     * By default we do not have any children, ParentNode overrides this.
     * @see ParentNode
     *
     * @return org.w3c.dom.Node
     * @param Index int
     */
    public Node item(int index) {
        return null;
    }

    //
    // DOM2: methods, getters, setters
    //

    /**
     * Puts all <code>Text</code> nodes in the full depth of the sub-tree
     * underneath this <code>Node</code>, including attribute nodes, into a
     * "normal" form where only markup (e.g., tags, comments, processing
     * instructions, CDATA sections, and entity references) separates
     * <code>Text</code> nodes, i.e., there are no adjacent <code>Text</code>
     * nodes.  This can be used to ensure that the DOM view of a document is
     * the same as if it were saved and re-loaded, and is useful when
     * operations (such as XPointer lookups) that depend on a particular
     * document tree structure are to be used.In cases where the document
     * contains <code>CDATASections</code>, the normalize operation alone may
     * not be sufficient, since XPointers do not differentiate between
     * <code>Text</code> nodes and <code>CDATASection</code> nodes.
     * <p>
     * Note that this implementation simply calls normalize() on this Node's
     * children. It is up to implementors or Node to override normalize()
     * to take action.
     */
    public void normalize() {
        /* by default we do not have any children,
           ParentNode overrides this behavior */
    }

    /**
     * Introduced in DOM Level 2. <p>
     * Tests whether the DOM implementation implements a specific feature and
     * that feature is supported by this node.
     * @param feature The package name of the feature to test. This is the same
     * name as what can be passed to the method hasFeature on
     * DOMImplementation.
     * @param version This is the version number of the package name to
     * test. In Level 2, version 1, this is the string "2.0". If the version is
     * not specified, supporting any version of the feature will cause the
     * method to return true.
     * @return boolean Returns true if this node defines a subtree within which
     * the specified feature is supported, false otherwise.
     * @since WD-DOM-Level-2-19990923
     */
    public boolean isSupported(String feature, String version)
    {
        return ownerDocument().getImplementation().hasFeature(feature,
                                                              version);
    }

    /**
     * Introduced in DOM Level 2. <p>
     *
     * The namespace URI of this node, or null if it is unspecified. When this
     * node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE, this is
     * always null and setting it has no effect. <p>
     *
     * This is not a computed value that is the result of a namespace lookup
     * based on an examination of the namespace declarations in scope. It is
     * merely the namespace URI given at creation time.<p>
     *
     * For nodes created with a DOM Level 1 method, such as createElement
     * from the Document interface, this is null.
     * @since WD-DOM-Level-2-19990923
     * @see AttrNSImpl
     * @see ElementNSImpl
     */
    public String getNamespaceURI()
    {
        return null;
    }

    /**
     * Introduced in DOM Level 2. <p>
     *
     * The namespace prefix of this node, or null if it is unspecified. When
     * this node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE this
     * is always null and setting it has no effect.<p>
     *
     * For nodes created with a DOM Level 1 method, such as createElement
     * from the Document interface, this is null. <p>
     *
     * @since WD-DOM-Level-2-19990923
     * @see AttrNSImpl
     * @see ElementNSImpl
     */
    public String getPrefix()
    {
        return null;
    }

    /**
     *  Introduced in DOM Level 2. <p>
     *
     *  The namespace prefix of this node, or null if it is unspecified. When
     *  this node is of any type other than ELEMENT_NODE and ATTRIBUTE_NODE
     *  this is always null and setting it has no effect.<p>
     *
     *  For nodes created with a DOM Level 1 method, such as createElement from
     *  the Document interface, this is null.<p>
     *
     *  Note that setting this attribute changes the nodeName attribute, which
     *  holds the qualified name, as well as the tagName and name attributes of
     *  the Element and Attr interfaces, when applicable.<p>
     *
     * @throws INVALID_CHARACTER_ERR Raised if the specified
     *  prefix contains an invalid character.
     *
     * @since WD-DOM-Level-2-19990923
     * @see AttrNSImpl
     * @see ElementNSImpl
     */
    public void setPrefix(String prefix)
        throws DOMException
    {
        throw new DOMException(DOMException.NAMESPACE_ERR,
              DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN,
                 "NAMESPACE_ERR", null));
    }

    /**
     * Introduced in DOM Level 2. <p>
     *
     * Returns the local part of the qualified name of this node.
     * For nodes created with a DOM Level 1 method, such as createElement
     * from the Document interface, and for nodes of any type other than
     * ELEMENT_NODE and ATTRIBUTE_NODE this is the same as the nodeName
     * attribute.
     * @since WD-DOM-Level-2-19990923
     * @see AttrNSImpl
     * @see ElementNSImpl
     */
    public String             getLocalName()
    {
        return null;
    }

    //
    // EventTarget support
    //

    public void addEventListener(String type, EventListener listener,
                                 boolean useCapture) {
        // simply forward to Document
        ownerDocument().addEventListener(this, type, listener, useCapture);
    }

    public void removeEventListener(String type, EventListener listener,
                                    boolean useCapture) {
        // simply forward to Document
        ownerDocument().removeEventListener(this, type, listener, useCapture);
    }

    public boolean dispatchEvent(Event event) {
        // simply forward to Document
        return ownerDocument().dispatchEvent(this, event);
    }

    //
    // Public DOM Level 3 methods
    //

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

    /**
     * Compares a node with this node with regard to their position in the
     * tree and according to the document order. This order can be extended
     * by module that define additional types of nodes.
     * @param other The node to compare against this node.
     * @return Returns how the given node is positioned relatively to this
     *   node.
     * @since DOM Level 3
     * @deprecated
     */
    public short compareTreePosition(Node other) {
        // Questions of clarification for this method - to be answered by the
        // DOM WG.   Current assumptions listed - LM
        //
        // 1. How do ENTITY nodes compare?
        //    Current assumption: TREE_POSITION_DISCONNECTED, as ENTITY nodes
        //    aren't really 'in the tree'
        //
        // 2. How do NOTATION nodes compare?
        //    Current assumption: TREE_POSITION_DISCONNECTED, as NOTATION nodes
        //    aren't really 'in the tree'
        //
        // 3. Are TREE_POSITION_ANCESTOR and TREE_POSITION_DESCENDANT
        //    only relevant for nodes that are "part of the document tree"?
        //     <outer>
        //         <inner  myattr="true"/>
        //     </outer>
        //    Is the element node "outer" considered an ancestor of "myattr"?
        //    Current assumption: No.
        //
        // 4. How do children of ATTRIBUTE nodes compare (with eachother, or
        //    with children of other attribute nodes with the same element)
        //    Current assumption: Children of ATTRIBUTE nodes are treated as if
        //    they they are the attribute node itself, unless the 2 nodes
        //    are both children of the same attribute.
        //
        // 5. How does an ENTITY_REFERENCE node compare with it's children?
        //    Given the DOM, it should precede its children as an ancestor.
        //    Given "document order",  does it represent the same position?
        //    Current assumption: An ENTITY_REFERENCE node is an ancestor of its
        //    children.
        //
        // 6. How do children of a DocumentFragment compare?
        //    Current assumption: If both nodes are part of the same document
        //    fragment, there are compared as if they were part of a document.


        // If the nodes are the same...
        if (this==other)
          return (TREE_POSITION_SAME_NODE | TREE_POSITION_EQUIVALENT);

        // If either node is of type ENTITY or NOTATION, compare as disconnected
        short thisType = this.getNodeType();
        short otherType = other.getNodeType();

        // If either node is of type ENTITY or NOTATION, compare as disconnected
        if (thisType == Node.ENTITY_NODE ||
            thisType == Node.NOTATION_NODE ||
            otherType == Node.ENTITY_NODE ||
            otherType == Node.NOTATION_NODE ) {
          return TREE_POSITION_DISCONNECTED;
        }

        // Find the ancestor of each node, and the distance each node is from
        // its ancestor.
        // During this traversal, look for ancestor/descendent relationships
        // between the 2 nodes in question.
        // We do this now, so that we get this info correct for attribute nodes
        // and their children.

        Node node;
        Node thisAncestor = this;
        Node otherAncestor = other;
        int thisDepth=0;
        int otherDepth=0;
        for (node=this; node != null; node = node.getParentNode()) {
            thisDepth +=1;
            if (node == other)
              // The other node is an ancestor of this one.
              return (TREE_POSITION_ANCESTOR | TREE_POSITION_PRECEDING);
            thisAncestor = node;
        }

        for (node=other; node!=null; node=node.getParentNode()) {
            otherDepth +=1;
            if (node == this)
              // The other node is a descendent of the reference node.
              return (TREE_POSITION_DESCENDANT | TREE_POSITION_FOLLOWING);
            otherAncestor = node;
        }


        Node thisNode = this;
        Node otherNode = other;

        int thisAncestorType = thisAncestor.getNodeType();
        int otherAncestorType = otherAncestor.getNodeType();

        // if the ancestor is an attribute, get owning element.
        // we are now interested in the owner to determine position.

        if (thisAncestorType == Node.ATTRIBUTE_NODE)  {
           thisNode = ((AttrImpl)thisAncestor).getOwnerElement();
        }
        if (otherAncestorType == Node.ATTRIBUTE_NODE) {
           otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
        }

        // Before proceeding, we should check if both ancestor nodes turned
        // out to be attributes for the same element
        if (thisAncestorType == Node.ATTRIBUTE_NODE &&
            otherAncestorType == Node.ATTRIBUTE_NODE &&
            thisNode==otherNode)
            return TREE_POSITION_EQUIVALENT;

        // Now, find the ancestor of the owning element, if the original
        // ancestor was an attribute

        // Note:  the following 2 loops are quite close to the ones above.
        // May want to common them up.  LM.
        if (thisAncestorType == Node.ATTRIBUTE_NODE) {
            thisDepth=0;
            for (node=thisNode; node != null; node=node.getParentNode()) {
                thisDepth +=1;
                if (node == otherNode)
                  // The other node is an ancestor of the owning element
                  {
                  return TREE_POSITION_PRECEDING;
                  }
                thisAncestor = node;
            }
        }

        // Now, find the ancestor of the owning element, if the original
        // ancestor was an attribute
        if (otherAncestorType == Node.ATTRIBUTE_NODE) {
            otherDepth=0;
            for (node=otherNode; node != null; node=node.getParentNode()) {
                otherDepth +=1;
                if (node == thisNode)
                  // The other node is a descendent of the reference
                  // node's element
                  return TREE_POSITION_FOLLOWING;
                otherAncestor = node;
            }
        }

        // thisAncestor and otherAncestor must be the same at this point,
        // otherwise, we are not in the same tree or document fragment
        if (thisAncestor != otherAncestor)
          return TREE_POSITION_DISCONNECTED;


        // Go up the parent chain of the deeper node, until we find a node
        // with the same depth as the shallower node

        if (thisDepth > otherDepth) {
          for (int i=0; i<thisDepth - otherDepth; i++)
            thisNode = thisNode.getParentNode();
          // Check if the node we have reached is in fact "otherNode". This can
          // happen in the case of attributes.  In this case, otherNode
          // "precedes" this.
          if (thisNode == otherNode)
            return TREE_POSITION_PRECEDING;
        }

        else {
          for (int i=0; i<otherDepth - thisDepth; i++)
            otherNode = otherNode.getParentNode();
          // Check if the node we have reached is in fact "thisNode".  This can
          // happen in the case of attributes.  In this case, otherNode
          // "follows" this.
          if (otherNode == thisNode)
            return TREE_POSITION_FOLLOWING;
        }

        // We now have nodes at the same depth in the tree.  Find a common
        // ancestor.
        Node thisNodeP, otherNodeP;
        for (thisNodeP=thisNode.getParentNode(),
                  otherNodeP=otherNode.getParentNode();
             thisNodeP!=otherNodeP;) {
             thisNode = thisNodeP;
             otherNode = otherNodeP;
             thisNodeP = thisNodeP.getParentNode();
             otherNodeP = otherNodeP.getParentNode();
        }

        // At this point, thisNode and otherNode are direct children of
        // the common ancestor.
        // See whether thisNode or otherNode is the leftmost

        for (Node current=thisNodeP.getFirstChild();
                  current!=null;
                  current=current.getNextSibling()) {
               if (current==otherNode) {
                 return TREE_POSITION_PRECEDING;
               }
               else if (current==thisNode) {
                 return TREE_POSITION_FOLLOWING;
               }
        }
        // REVISIT:  shouldn't get here.   Should probably throw an
        // exception
        return 0;

    }
    /**
     * Compares a node with this node with regard to their position in the
     * document.
     * @param other The node to compare against this node.
     * @return Returns how the given node is positioned relatively to this
     *   node.
     * @since DOM Level 3
     */
    public short compareDocumentPosition(Node other) throws DOMException {

        // If the nodes are the same, no flags should be set
        if (this==other)
          return 0;

        // check if other is from a different implementation
        try {
            NodeImpl node = (NodeImpl) other;
        } catch (ClassCastException e) {
            // other comes from a different implementation
            String msg = DOMMessageFormatter.formatMessage(
               DOMMessageFormatter.DOM_DOMAIN, "NOT_SUPPORTED_ERR", null);
            throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
        }

        Document thisOwnerDoc, otherOwnerDoc;
        // get the respective Document owners.
        if (this.getNodeType() == Node.DOCUMENT_NODE)
          thisOwnerDoc = (Document)this;
        else
          thisOwnerDoc = this.getOwnerDocument();
        if (other.getNodeType() == Node.DOCUMENT_NODE)
          otherOwnerDoc = (Document)other;
        else
          otherOwnerDoc = other.getOwnerDocument();

        // If from different documents, we know they are disconnected.
        // and have an implementation dependent order
        if (thisOwnerDoc != otherOwnerDoc &&
            thisOwnerDoc !=null &&
            otherOwnerDoc !=null)
 {
          int otherDocNum = ((CoreDocumentImpl)otherOwnerDoc).getNodeNumber();
          int thisDocNum = ((CoreDocumentImpl)thisOwnerDoc).getNodeNumber();
          if (otherDocNum > thisDocNum)
            return DOCUMENT_POSITION_DISCONNECTED |
                   DOCUMENT_POSITION_FOLLOWING |
                   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
          else
            return DOCUMENT_POSITION_DISCONNECTED |
                   DOCUMENT_POSITION_PRECEDING |
                   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;

        }

        // Find the ancestor of each node, and the distance each node is from
        // its ancestor.
        // During this traversal, look for ancestor/descendent relationships
        // between the 2 nodes in question.
        // We do this now, so that we get this info correct for attribute nodes
        // and their children.

        Node node;
        Node thisAncestor = this;
        Node otherAncestor = other;

        int thisDepth=0;
        int otherDepth=0;
        for (node=this; node != null; node = node.getParentNode()) {
            thisDepth +=1;
            if (node == other)
              // The other node is an ancestor of this one.
              return (DOCUMENT_POSITION_CONTAINS |
                      DOCUMENT_POSITION_PRECEDING);
            thisAncestor = node;
        }

        for (node=other; node!=null; node=node.getParentNode()) {
            otherDepth +=1;
            if (node == this)
              // The other node is a descendent of the reference node.
              return (DOCUMENT_POSITION_IS_CONTAINED |
                      DOCUMENT_POSITION_FOLLOWING);
            otherAncestor = node;
        }



        int thisAncestorType = thisAncestor.getNodeType();
        int otherAncestorType = otherAncestor.getNodeType();
        Node thisNode = this;
        Node otherNode = other;

        // Special casing for ENTITY, NOTATION, DOCTYPE and ATTRIBUTES
        // LM:  should rewrite this.
        switch (thisAncestorType) {
          case Node.NOTATION_NODE:
          case Node.ENTITY_NODE: {
            DocumentType container = thisOwnerDoc.getDoctype();
            if (container == otherAncestor) return
                   (DOCUMENT_POSITION_CONTAINS | DOCUMENT_POSITION_PRECEDING);
            switch (otherAncestorType) {
              case Node.NOTATION_NODE:
              case Node.ENTITY_NODE:  {
                if (thisAncestorType != otherAncestorType)
                 // the nodes are of different types
                 return ((thisAncestorType>otherAncestorType) ?
                    DOCUMENT_POSITION_PRECEDING:DOCUMENT_POSITION_FOLLOWING);
                else {
                 // the nodes are of the same type.  Find order.
                 if (thisAncestorType == Node.NOTATION_NODE)

                     if (((NamedNodeMapImpl)container.getNotations()).precedes(otherAncestor,thisAncestor))
                       return (DOCUMENT_POSITION_PRECEDING |
                               DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
                     else
                       return (DOCUMENT_POSITION_FOLLOWING |
                               DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
                 else
                     if (((NamedNodeMapImpl)container.getEntities()).precedes(otherAncestor,thisAncestor))
                       return (DOCUMENT_POSITION_PRECEDING |
                               DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
                     else
                       return (DOCUMENT_POSITION_FOLLOWING |
                               DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
                }
              }
            }
            thisNode = thisAncestor = thisOwnerDoc;
            break;
          }
          case Node.DOCUMENT_TYPE_NODE: {
            if (otherNode == thisOwnerDoc)
              return (DOCUMENT_POSITION_PRECEDING |
                      DOCUMENT_POSITION_CONTAINS);
            else if (thisOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc)
              return (DOCUMENT_POSITION_FOLLOWING);
            break;
          }
          case Node.ATTRIBUTE_NODE: {
            thisNode = ((AttrImpl)thisAncestor).getOwnerElement();
            if (otherAncestorType==Node.ATTRIBUTE_NODE) {
              otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
              if (otherNode == thisNode) {
                if (((NamedNodeMapImpl)thisNode.getAttributes()).precedes(other,this))
                  return (DOCUMENT_POSITION_PRECEDING |
                          DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
                else
                  return (DOCUMENT_POSITION_FOLLOWING |
                          DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC);
              }
            }

            // Now, find the ancestor of the element
            thisDepth=0;
            for (node=thisNode; node != null; node=node.getParentNode()) {
                thisDepth +=1;
                if (node == otherNode)
                  {
                  // The other node is an ancestor of the owning element
                  return (DOCUMENT_POSITION_CONTAINS |
                          DOCUMENT_POSITION_PRECEDING);
                  }
                thisAncestor = node;
            }
          }
        }
        switch (otherAncestorType) {
          case Node.NOTATION_NODE:
          case Node.ENTITY_NODE: {
          DocumentType container = thisOwnerDoc.getDoctype();
            if (container == this) return (DOCUMENT_POSITION_IS_CONTAINED |
                                          DOCUMENT_POSITION_FOLLOWING);
            otherNode = otherAncestor = thisOwnerDoc;
            break;
          }
          case Node.DOCUMENT_TYPE_NODE: {
            if (thisNode == otherOwnerDoc)
              return (DOCUMENT_POSITION_FOLLOWING |
                      DOCUMENT_POSITION_IS_CONTAINED);
            else if (otherOwnerDoc!=null && thisOwnerDoc==otherOwnerDoc)
              return (DOCUMENT_POSITION_PRECEDING);
            break;
          }
          case Node.ATTRIBUTE_NODE: {
            otherDepth=0;
            otherNode = ((AttrImpl)otherAncestor).getOwnerElement();
            for (node=otherNode; node != null; node=node.getParentNode()) {
                otherDepth +=1;
                if (node == thisNode)
                  // The other node is a descendent of the reference
                  // node's element
                  return DOCUMENT_POSITION_FOLLOWING |
                         DOCUMENT_POSITION_IS_CONTAINED;
                otherAncestor = node;
            }

          }
        }

        // thisAncestor and otherAncestor must be the same at this point,
        // otherwise, the original nodes are disconnected
        if (thisAncestor != otherAncestor) {
          int thisAncestorNum, otherAncestorNum;
          thisAncestorNum = ((NodeImpl)thisAncestor).getNodeNumber();
          otherAncestorNum = ((NodeImpl)otherAncestor).getNodeNumber();

          if (thisAncestorNum > otherAncestorNum)
            return DOCUMENT_POSITION_DISCONNECTED |
                   DOCUMENT_POSITION_FOLLOWING |
                   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
          else
            return DOCUMENT_POSITION_DISCONNECTED |
                   DOCUMENT_POSITION_PRECEDING |
                   DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC;
        }


        // Go up the parent chain of the deeper node, until we find a node
        // with the same depth as the shallower node

        if (thisDepth > otherDepth) {
          for (int i=0; i<thisDepth - otherDepth; i++)
            thisNode = thisNode.getParentNode();
          // Check if the node we have reached is in fact "otherNode". This can
          // happen in the case of attributes.  In this case, otherNode
          // "precedes" this.
          if (thisNode == otherNode)
{
            return DOCUMENT_POSITION_PRECEDING;
          }
        }

        else {
          for (int i=0; i<otherDepth - thisDepth; i++)
            otherNode = otherNode.getParentNode();
          // Check if the node we have reached is in fact "thisNode".  This can
          // happen in the case of attributes.  In this case, otherNode
          // "follows" this.
          if (otherNode == thisNode)
            return DOCUMENT_POSITION_FOLLOWING;
        }

        // We now have nodes at the same depth in the tree.  Find a common
        // ancestor.
        Node thisNodeP, otherNodeP;
        for (thisNodeP=thisNode.getParentNode(),
                  otherNodeP=otherNode.getParentNode();
             thisNodeP!=otherNodeP;) {
             thisNode = thisNodeP;
             otherNode = otherNodeP;
             thisNodeP = thisNodeP.getParentNode();
             otherNodeP = otherNodeP.getParentNode();
        }

        // At this point, thisNode and otherNode are direct children of
        // the common ancestor.
        // See whether thisNode or otherNode is the leftmost

        for (Node current=thisNodeP.getFirstChild();
                  current!=null;
                  current=current.getNextSibling()) {
               if (current==otherNode) {
                 return DOCUMENT_POSITION_PRECEDING;
               }
               else if (current==thisNode) {
                 return DOCUMENT_POSITION_FOLLOWING;
               }
        }
        // REVISIT:  shouldn't get here.   Should probably throw an
        // exception
        return 0;

    }

    /**
     * This attribute returns the text content of this node and its
     * descendants. When it is defined to be null, setting it has no effect.
     * When set, any possible children this node may have are removed and
     * replaced by a single <code>Text</code> node containing the string
     * this attribute is set to. On getting, no serialization is performed,
     * the returned string does not contain any markup. No whitespace
     * normalization is performed, the returned string does not contain the
     * element content whitespaces . Similarly, on setting, no parsing is
     * performed either, the input string is taken as pure textual content.
     * <br>The string returned is made of the text content of this node
     * depending on its type, as defined below:
     * <table border='1'>
     * <tr>
     * <th>Node type</th>
     * <th>Content</th>
     * </tr>

    /**
     * This attribute returns the text content of this node and its
     * descendants. When it is defined to be null, setting it has no effect.
     * When set, any possible children this node may have are removed and
     * replaced by a single <code>Text</code> node containing the string
     * this attribute is set to. On getting, no serialization is performed,
     * the returned string does not contain any markup. No whitespace
     * normalization is performed, the returned string does not contain the
     * element content whitespaces . Similarly, on setting, no parsing is
     * performed either, the input string is taken as pure textual content.
     * <br>The string returned is made of the text content of this node
     * depending on its type, as defined below:
     * <table border='1'>
     * <tr>
     * <th>Node type</th>
     * <th>Content</th>
     * </tr>
     * <tr>
     * <td valign='top' rowspan='1' colspan='1'>
     * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
     * DOCUMENT_FRAGMENT_NODE</td>
     * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code>
     * attribute value of every child node, excluding COMMENT_NODE and
     * PROCESSING_INSTRUCTION_NODE nodes</td>
     * </tr>
     * <tr>
     * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE,
     * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
     * <td valign='top' rowspan='1' colspan='1'>
     * <code>nodeValue</code></td>
     * </tr>
     * <tr>
     * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
     * <td valign='top' rowspan='1' colspan='1'>
     * null</td>
     * </tr>
     * </table>
     * @exception DOMException
     *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
     * @exception DOMException
     *   DOMSTRING_SIZE_ERR: Raised when it would return more characters than
     *   fit in a <code>DOMString</code> variable on the implementation
     *   platform.
     * @since DOM Level 3
     */
    public String getTextContent() throws DOMException {
        return getNodeValue();  // overriden in some subclasses
    }

    // internal method taking a StringBuffer in parameter
    void getTextContent(StringBuffer buf) throws DOMException {
        String content = getNodeValue();
        if (content != null) {
            buf.append(content);
        }
    }

    /**
     * This attribute returns the text content of this node and its
     * descendants. When it is defined to be null, setting it has no effect.
     * When set, any possible children this node may have are removed and
     * replaced by a single <code>Text</code> node containing the string
     * this attribute is set to. On getting, no serialization is performed,
     * the returned string does not contain any markup. No whitespace
     * normalization is performed, the returned string does not contain the
     * element content whitespaces . Similarly, on setting, no parsing is
     * performed either, the input string is taken as pure textual content.
     * <br>The string returned is made of the text content of this node
     * depending on its type, as defined below:
     * <table border='1'>
     * <tr>
     * <th>Node type</th>
     * <th>Content</th>
     * </tr>
     * <tr>
     * <td valign='top' rowspan='1' colspan='1'>
     * ELEMENT_NODE, ENTITY_NODE, ENTITY_REFERENCE_NODE,
     * DOCUMENT_FRAGMENT_NODE</td>
     * <td valign='top' rowspan='1' colspan='1'>concatenation of the <code>textContent</code>
     * attribute value of every child node, excluding COMMENT_NODE and
     * PROCESSING_INSTRUCTION_NODE nodes</td>
     * </tr>
     * <tr>
     * <td valign='top' rowspan='1' colspan='1'>ATTRIBUTE_NODE, TEXT_NODE,
     * CDATA_SECTION_NODE, COMMENT_NODE, PROCESSING_INSTRUCTION_NODE</td>
     * <td valign='top' rowspan='1' colspan='1'>
     * <code>nodeValue</code></td>
     * </tr>
     * <tr>
     * <td valign='top' rowspan='1' colspan='1'>DOCUMENT_NODE, DOCUMENT_TYPE_NODE, NOTATION_NODE</td>
     * <td valign='top' rowspan='1' colspan='1'>
     * null</td>
     * </tr>
     * </table>
     * @exception DOMException
     *   NO_MODIFICATION_ALLOWED_ERR: Raised when the node is readonly.
     * @exception DOMException
     *   DOMSTRING_SIZE_ERR: Raised when it would return more characters than
     *   fit in a <code>DOMString</code> variable on the implementation
     *   platform.
     * @since DOM Level 3
     */
    public void setTextContent(String textContent)
        throws DOMException {
        setNodeValue(textContent);
    }

    /**
     * Returns whether this node is the same node as the given one.
     * <br>This method provides a way to determine whether two
     * <code>Node</code> references returned by the implementation reference
     * the same object. When two <code>Node</code> references are references
     * to the same object, even if through a proxy, the references may be
     * used completely interchangably, such that all attributes have the
     * same values and calling the same DOM method on either reference
     * always has exactly the same effect.
     * @param other The node to test against.
     * @return Returns <code>true</code> if the nodes are the same,
     *   <code>false</code> otherwise.
     * @since DOM Level 3
     */
    public boolean isSameNode(Node other) {
        // we do not use any wrapper so the answer is obvious
        return this == other;
    }




    /**
     *  DOM Level 3: Experimental
     *  This method checks if the specified <code>namespaceURI</code> is the
     *  default namespace or not.
     *  @param namespaceURI The namespace URI to look for.
     *  @return  <code>true</code> if the specified <code>namespaceURI</code>
     *   is the default namespace, <code>false</code> otherwise.
     * @since DOM Level 3
     */
    public boolean isDefaultNamespace(String namespaceURI){
        // REVISIT: remove casts when DOM L3 becomes REC.
        short type = this.getNodeType();
        switch (type) {
        case Node.ELEMENT_NODE: {
            String namespace = this.getNamespaceURI();
            String prefix = this.getPrefix();

            // REVISIT: is it possible that prefix is empty string?
            if (prefix == null || prefix.length() == 0) {
                if (namespaceURI == null) {
                    return (namespace == namespaceURI);
                }
                return namespaceURI.equals(namespace);
            }
            if (this.hasAttributes()) {
                ElementImpl elem = (ElementImpl)this;
                NodeImpl attr = (NodeImpl)elem.getAttributeNodeNS("http://www.w3.org/2000/xmlns/", "xmlns");
                if (attr != null) {
                    String value = attr.getNodeValue();
                    if (namespaceURI == null) {
                        return (namespace == value);
                    }
                    return namespaceURI.equals(value);
                }
            }

            NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
            if (ancestor != null) {
                return ancestor.isDefaultNamespace(namespaceURI);
            }
            return false;
        }
        case Node.DOCUMENT_NODE:{
                return((NodeImpl)((Document)this).getDocumentElement()).isDefaultNamespace(namespaceURI);
            }

        case Node.ENTITY_NODE :
        case Node.NOTATION_NODE:
        case Node.DOCUMENT_FRAGMENT_NODE:
        case Node.DOCUMENT_TYPE_NODE:
            // type is unknown
            return false;
        case Node.ATTRIBUTE_NODE:{
                if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
                    return ownerNode.isDefaultNamespace(namespaceURI);

                }
                return false;
            }
        default:{
                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
                if (ancestor != null) {
                    return ancestor.isDefaultNamespace(namespaceURI);
                }
                return false;
            }

        }


    }


    /**
     *
     * DOM Level 3 - Experimental:
     * Look up the prefix associated to the given namespace URI, starting from this node.
     *
     * @param namespaceURI
     * @return the prefix for the namespace
     */
    public String lookupPrefix(String namespaceURI){

        // REVISIT: When Namespaces 1.1 comes out this may not be true
        // Prefix can't be bound to null namespace
        if (namespaceURI == null) {
            return null;
        }

        short type = this.getNodeType();

        switch (type) {
        case Node.ELEMENT_NODE: {

                String namespace = this.getNamespaceURI(); // to flip out children
                return lookupNamespacePrefix(namespaceURI, (ElementImpl)this);
            }
        case Node.DOCUMENT_NODE:{
                return((NodeImpl)((Document)this).getDocumentElement()).lookupPrefix(namespaceURI);
            }

        case Node.ENTITY_NODE :
        case Node.NOTATION_NODE:
        case Node.DOCUMENT_FRAGMENT_NODE:
        case Node.DOCUMENT_TYPE_NODE:
            // type is unknown
            return null;
        case Node.ATTRIBUTE_NODE:{
                if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
                    return ownerNode.lookupPrefix(namespaceURI);

                }
                return null;
            }
        default:{
                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
                if (ancestor != null) {
                    return ancestor.lookupPrefix(namespaceURI);
                }
                return null;
            }

        }
    }
    /**
     * DOM Level 3 - Experimental:
     * Look up the namespace URI associated to the given prefix, starting from this node.
     * Use lookupNamespaceURI(null) to lookup the default namespace
     *
     * @param namespaceURI
     * @return th URI for the namespace
     * @since DOM Level 3
     */
    public String lookupNamespaceURI(String specifiedPrefix) {
        short type = this.getNodeType();
        switch (type) {
        case Node.ELEMENT_NODE : {

                String namespace = this.getNamespaceURI();
                String prefix = this.getPrefix();
                if (namespace !=null) {
                    // REVISIT: is it possible that prefix is empty string?
                    if (specifiedPrefix== null && prefix==specifiedPrefix) {
                        // looking for default namespace
                        return namespace;
                    } else if (prefix != null && prefix.equals(specifiedPrefix)) {
                        // non default namespace
                        return namespace;
                    }
                }
                if (this.hasAttributes()) {
                    NamedNodeMap map = this.getAttributes();
                    int length = map.getLength();
                    for (int i=0;i<length;i++) {
                        Node attr = map.item(i);
                        String attrPrefix = attr.getPrefix();
                        String value = attr.getNodeValue();
                        namespace = attr.getNamespaceURI();
                        if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) {
                            // at this point we are dealing with DOM Level 2 nodes only
                            if (specifiedPrefix == null &&
                                attr.getNodeName().equals("xmlns")) {
                                // default namespace
                                return value;
                            } else if (attrPrefix !=null &&
                                       attrPrefix.equals("xmlns") &&
                                       attr.getLocalName().equals(specifiedPrefix)) {
                                // non default namespace
                                return value;
                            }
                        }
                    }
                }
                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
                if (ancestor != null) {
                    return ancestor.lookupNamespaceURI(specifiedPrefix);
                }

                return null;


            }
        case Node.DOCUMENT_NODE : {
                return((NodeImpl)((Document)this).getDocumentElement()).lookupNamespaceURI(specifiedPrefix);
            }
        case Node.ENTITY_NODE :
        case Node.NOTATION_NODE:
        case Node.DOCUMENT_FRAGMENT_NODE:
        case Node.DOCUMENT_TYPE_NODE:
            // type is unknown
            return null;
        case Node.ATTRIBUTE_NODE:{
                if (this.ownerNode.getNodeType() == Node.ELEMENT_NODE) {
                    return ownerNode.lookupNamespaceURI(specifiedPrefix);

                }
                return null;
            }
        default:{
                NodeImpl ancestor = (NodeImpl)getElementAncestor(this);
                if (ancestor != null) {
                    return ancestor.lookupNamespaceURI(specifiedPrefix);
                }
                return null;
            }

        }
    }


    Node getElementAncestor (Node currentNode){
        Node parent = currentNode.getParentNode();
        if (parent != null) {
            short type = parent.getNodeType();
            if (type == Node.ELEMENT_NODE) {
                return parent;
            }
            return getElementAncestor(parent);
        }
        return null;
    }

    String lookupNamespacePrefix(String namespaceURI, ElementImpl el){
        String namespace = this.getNamespaceURI();
        // REVISIT: if no prefix is available is it null or empty string, or
        //          could be both?
        String prefix = this.getPrefix();

        if (namespace!=null && namespace.equals(namespaceURI)) {
            if (prefix != null) {
                String foundNamespace =  el.lookupNamespaceURI(prefix);
                if (foundNamespace !=null && foundNamespace.equals(namespaceURI)) {
                    return prefix;
                }

            }
        }
        if (this.hasAttributes()) {
            NamedNodeMap map = this.getAttributes();
            int length = map.getLength();
            for (int i=0;i<length;i++) {
                Node attr = map.item(i);
                String attrPrefix = attr.getPrefix();
                String value = attr.getNodeValue();
                namespace = attr.getNamespaceURI();
                if (namespace !=null && namespace.equals("http://www.w3.org/2000/xmlns/")) {
                    // DOM Level 2 nodes
                    if (((attr.getNodeName().equals("xmlns")) ||
                         (attrPrefix !=null && attrPrefix.equals("xmlns")) &&
                         value.equals(namespaceURI))) {

                        String localname= attr.getLocalName();
                        String foundNamespace = el.lookupNamespaceURI(localname);
                        if (foundNamespace !=null && foundNamespace.equals(namespaceURI)) {
                            return localname;
                        }
                    }


                }
            }
        }
        NodeImpl ancestor = (NodeImpl)getElementAncestor(this);

        if (ancestor != null) {
            return ancestor.lookupNamespacePrefix(namespaceURI, el);
        }
        return null;
    }

    /**
     * Tests whether two nodes are equal.
     * <br>This method tests for equality of nodes, not sameness (i.e.,
     * whether the two nodes are references to the same object) which can be
     * tested with <code>Node.isSameNode</code>. All nodes that are the same
     * will also be equal, though the reverse may not be true.
     * <br>Two nodes are equal if and only if the following conditions are
     * satisfied: The two nodes are of the same type.The following string
     * attributes are equal: <code>nodeName</code>, <code>localName</code>,
     * <code>namespaceURI</code>, <code>prefix</code>, <code>nodeValue</code>
     * , <code>baseURI</code>. This is: they are both <code>null</code>, or
     * they have the same length and are character for character identical.
     * The <code>attributes</code> <code>NamedNodeMaps</code> are equal.
     * This is: they are both <code>null</code>, or they have the same
     * length and for each node that exists in one map there is a node that
     * exists in the other map and is equal, although not necessarily at the
     * same index.The <code>childNodes</code> <code>NodeLists</code> are
     * equal. This is: they are both <code>null</code>, or they have the
     * same length and contain equal nodes at the same index. This is true
     * for <code>Attr</code> nodes as for any other type of node. Note that
     * normalization can affect equality; to avoid this, nodes should be
     * normalized before being compared.
     * <br>For two <code>DocumentType</code> nodes to be equal, the following
     * conditions must also be satisfied: The following string attributes
     * are equal: <code>publicId</code>, <code>systemId</code>,
     * <code>internalSubset</code>.The <code>entities</code>
     * <code>NamedNodeMaps</code> are equal.The <code>notations</code>
     * <code>NamedNodeMaps</code> are equal.
     * <br>On the other hand, the following do not affect equality: the
     * <code>ownerDocument</code> attribute, the <code>specified</code>
     * attribute for <code>Attr</code> nodes, the
     * <code>isWhitespaceInElementContent</code> attribute for
     * <code>Text</code> nodes, as well as any user data or event listeners
     * registered on the nodes.
     * @param arg The node to compare equality with.
     * @param deep If <code>true</code>, recursively compare the subtrees; if
     *   <code>false</code>, compare only the nodes themselves (and its
     *   attributes, if it is an <code>Element</code>).
     * @return If the nodes, and possibly subtrees are equal,
     *   <code>true</code> otherwise <code>false</code>.
     * @since DOM Level 3
     */
    public boolean isEqualNode(Node arg) {
        if (arg == this) {
            return true;
        }
        if (arg.getNodeType() != getNodeType()) {
            return false;
        }
        // in theory nodeName can't be null but better be careful
        // who knows what other implementations may be doing?...
        if (getNodeName() == null) {
            if (arg.getNodeName() != null) {
                return false;
            }
        }
        else if (!getNodeName().equals(arg.getNodeName())) {
            return false;
        }

        if (getLocalName() == null) {
            if (arg.getLocalName() != null) {
                return false;
            }
        }
        else if (!getLocalName().equals(arg.getLocalName())) {
            return false;
        }

        if (getNamespaceURI() == null) {
            if (arg.getNamespaceURI() != null) {
                return false;
            }
        }
        else if (!getNamespaceURI().equals(arg.getNamespaceURI())) {
            return false;
        }

        if (getPrefix() == null) {
            if (arg.getPrefix() != null) {
                return false;
            }
        }
        else if (!getPrefix().equals(arg.getPrefix())) {
            return false;
        }

        if (getNodeValue() == null) {
            if (arg.getNodeValue() != null) {
                return false;
            }
        }
        else if (!getNodeValue().equals(arg.getNodeValue())) {
            return false;
        }


        return true;
    }

    /**
     * @since DOM Level 3
     */
    public Object getFeature(String feature, String version) {
        // we don't have any alternate node, either this node does the job
        // or we don't have anything that does
        return isSupported(feature, version) ? this : null;
    }

    /**
     * Associate an object to a key on this node. The object can later be
     * retrieved from this node by calling <code>getUserData</code> with the
     * same key.
     * @param key The key to associate the object to.
     * @param data The object to associate to the given key, or
     *   <code>null</code> to remove any existing association to that key.
     * @param handler The handler to associate to that key, or
     *   <code>null</code>.
     * @return Returns the <code>DOMObject</code> previously associated to
     *   the given key on this node, or <code>null</code> if there was none.
     * @since DOM Level 3
     */
    public Object setUserData(String key,
                              Object data,
                              UserDataHandler handler) {
        return ownerDocument().setUserData(this, key, data, handler);
    }

    /**
     * Retrieves the object associated to a key on a this node. The object
     * must first have been set to this node by calling
     * <code>setUserData</code> with the same key.
     * @param key The key the object is associated to.
     * @return Returns the <code>DOMObject</code> associated to the given key
     *   on this node, or <code>null</code> if there was none.
     * @since DOM Level 3
     */
    public Object getUserData(String key) {
        return ownerDocument().getUserData(this, key);
    }

    protected Map<String, ParentNode.UserDataRecord> getUserDataRecord(){
        return ownerDocument().getUserDataRecord(this);
        }

    //
    // Public methods
    //

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

        if (needsSyncData()) {
            synchronizeData();
        }
        isReadOnly(readOnly);

    } // setReadOnly(boolean,boolean)

    /**
     * NON-DOM: Returns true if this node is read-only. This is a
     * shallow check.
     */
    public boolean getReadOnly() {

        if (needsSyncData()) {
            synchronizeData();
        }
        return isReadOnly();

    } // getReadOnly():boolean

    /**
     * NON-DOM: As an alternative to subclassing the DOM, this implementation
     * has been extended with the ability to attach an object to each node.
     * (If you need multiple objects, you can attach a collection such as a
     * List or Map, then attach your application information to that.)
     * <p><b>Important Note:</b> You are responsible for removing references
     * to your data on nodes that are no longer used. Failure to do so will
     * prevent the nodes, your data is attached to, to be garbage collected
     * until the whole document is.
     *
     * @param data the object to store or null to remove any existing reference
     */
    public void setUserData(Object data) {
        ownerDocument().setUserData(this, data);
    }

    /**
     * NON-DOM:
     * Returns the user data associated to this node.
     */
    public Object getUserData() {
        return ownerDocument().getUserData(this);
    }

    //
    // Protected methods
    //

    /**
     * Denotes that this node has changed.
     */
    protected void changed() {
        // we do not actually store this information on every node, we only
        // have a global indicator on the Document. Doing otherwise cost us too
        // much for little gain.
        ownerDocument().changed();
    }

    /**
     * Returns the number of changes to this node.
     */
    protected int changes() {
        // we do not actually store this information on every node, we only
        // have a global indicator on the Document. Doing otherwise cost us too
        // much for little gain.
        return ownerDocument().changes();
    }

    /**
     * Override this method in subclass to hook in efficient
     * internal data structure.
     */
    protected void synchronizeData() {
        // By default just change the flag to avoid calling this method again
        needsSyncData(false);
    }

    /**
     * For non-child nodes, the node which "points" to this node.
     * For example, the owning element for an attribute
     */
    protected Node getContainer() {
       return null;
    }


    /*
     * Flags setters and getters
     */

    final boolean isReadOnly() {
        return (flags & READONLY) != 0;
    }

    final void isReadOnly(boolean value) {
        flags = (short) (value ? flags | READONLY : flags & ~READONLY);
    }

    final boolean needsSyncData() {
        return (flags & SYNCDATA) != 0;
    }

    final void needsSyncData(boolean value) {
        flags = (short) (value ? flags | SYNCDATA : flags & ~SYNCDATA);
    }

    final boolean needsSyncChildren() {
        return (flags & SYNCCHILDREN) != 0;
    }

    public final void needsSyncChildren(boolean value) {
        flags = (short) (value ? flags | SYNCCHILDREN : flags & ~SYNCCHILDREN);
    }

    final boolean isOwned() {
        return (flags & OWNED) != 0;
    }

    final void isOwned(boolean value) {
        flags = (short) (value ? flags | OWNED : flags & ~OWNED);
    }

    final boolean isFirstChild() {
        return (flags & FIRSTCHILD) != 0;
    }

    final void isFirstChild(boolean value) {
        flags = (short) (value ? flags | FIRSTCHILD : flags & ~FIRSTCHILD);
    }

    final boolean isSpecified() {
        return (flags & SPECIFIED) != 0;
    }

    final void isSpecified(boolean value) {
        flags = (short) (value ? flags | SPECIFIED : flags & ~SPECIFIED);
    }

    // inconsistent name to avoid clash with public method on TextImpl
    final boolean internalIsIgnorableWhitespace() {
        return (flags & IGNORABLEWS) != 0;
    }

    final void isIgnorableWhitespace(boolean value) {
        flags = (short) (value ? flags | IGNORABLEWS : flags & ~IGNORABLEWS);
    }

    final boolean hasStringValue() {
        return (flags & HASSTRING) != 0;
    }

    final void hasStringValue(boolean value) {
        flags = (short) (value ? flags | HASSTRING : flags & ~HASSTRING);
    }

    final boolean isNormalized() {
        return (flags & NORMALIZED) != 0;
    }

    final void isNormalized(boolean value) {
        // See if flag should propagate to parent.
        if (!value && isNormalized() && ownerNode != null) {
            ownerNode.isNormalized(false);
        }
        flags = (short) (value ?  flags | NORMALIZED : flags & ~NORMALIZED);
    }

    final boolean isIdAttribute() {
        return (flags & ID) != 0;
    }

    final void isIdAttribute(boolean value) {
        flags = (short) (value ? flags | ID : flags & ~ID);
    }

    //
    // Object methods
    //

    /** NON-DOM method for debugging convenience. */
    public String toString() {
        return "["+getNodeName()+": "+getNodeValue()+"]";
    }

    //
    // Serialization methods
    //

    /** Serialize object. */
    private void writeObject(ObjectOutputStream out) throws IOException {

        // synchronize data
        if (needsSyncData()) {
            synchronizeData();
        }
        // write object
        out.defaultWriteObject();

    } // writeObject(ObjectOutputStream)

} // class NodeImpl
