/* DomNode.java --
   Copyright (C) 1999,2000,2001,2004 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package gnu.xml.dom;

import gnu.java.lang.CPStringBuilder;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;

import org.w3c.dom.Document;
import org.w3c.dom.DOMException;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.w3c.dom.UserDataHandler;
import org.w3c.dom.events.DocumentEvent;
import org.w3c.dom.events.Event;
import org.w3c.dom.events.EventException;
import org.w3c.dom.events.EventListener;
import org.w3c.dom.events.EventTarget;
import org.w3c.dom.events.MutationEvent;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.traversal.NodeIterator;

/**
 * <p> "Node", "EventTarget", and "DocumentEvent" implementation.
 * This provides most of the core DOM functionality; only more
 * specialized features are provided by subclasses.  Those subclasses may
 * have some particular constraints they must implement, by overriding
 * methods defined here.  Such constraints are noted here in the method
 * documentation. </p>
 *
 * <p> Note that you can create events with type names prefixed with "USER-",
 * and pass them through this DOM.  This lets you use the DOM event scheme
 * for application specific purposes, although you must use a predefined event
 * structure (such as MutationEvent) to pass data along with those events.
 * Test for existence of this feature with the "USER-Events" DOM feature
 * name.</p>
 *
 * <p> Other kinds of events you can send include the "html" events,
 * like "load", "unload", "abort", "error", and "blur"; and the mutation
 * events.  If this DOM has been compiled with mutation event support
 * enabled, it will send mutation events when you change parts of the
 * tree; otherwise you may create and send such events yourself, but
 * they won't be generated by the DOM itself. </p>
 *
 * <p> Note that there is a namespace-aware name comparison method,
 * <em>nameAndTypeEquals</em>, which compares the names (and types) of
 * two nodes in conformance with the "Namespaces in XML" specification.
 * While mostly intended for use with elements and attributes, this should
 * also be helpful for ProcessingInstruction nodes and some others which
 * do not have namespace URIs.
 *
 * @author David Brownell
 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
 */
public abstract class DomNode
  implements Node, NodeList, EventTarget, DocumentEvent, Cloneable, Comparable
{

  // package private
  //final static String xmlNamespace = "http://www.w3.org/XML/1998/namespace";
  //final static String xmlnsURI = "http://www.w3.org/2000/xmlns/";

  // tunable
  //    NKIDS_* affects arrays of children (which grow)
  // (currently) fixed size:
  //    ANCESTORS_* is for event capture/bubbling, # ancestors
  //    NOTIFICATIONS_* is for per-node event delivery, # events
  private static final int NKIDS_DELTA = 8;
  private static final int ANCESTORS_INIT = 20;
  private static final int NOTIFICATIONS_INIT = 10;

  // tunable: enable mutation events or not?  Enabling it costs about
  // 10-15% in DOM construction time, last time it was measured.

  // package private !!!
  static final boolean reportMutations = true;

  // locking protocol changeable only within this class
  private static final Object lockNode = new Object();

  // NON-FINAL class data

  // Optimize event dispatch by not allocating memory each time
  private static boolean dispatchDataLock;
  private static DomNode[] ancestors = new DomNode[ANCESTORS_INIT];
  private static ListenerRecord[] notificationSet
    = new ListenerRecord[NOTIFICATIONS_INIT];

  // Ditto for the (most common) event object itself!
  private static boolean eventDataLock;
  private static DomEvent.DomMutationEvent mutationEvent
    = new DomEvent.DomMutationEvent(null);

  //
  // PER-INSTANCE DATA
  //

  DomDocument owner;
  DomNode parent; // parent node;
  DomNode previous; // previous sibling node
  DomNode next; // next sibling node
  DomNode first; // first child node
  DomNode last; // last child node
  int index; // index of this node in its parent's children
  int depth; // depth of the node in the document
  int length; // number of children
  final short nodeType;

  // Bleech ... "package private" so a builder can populate entity refs.
  // writable during construction.  DOM spec is nasty.
  boolean readonly;

  // event registrations
  private HashSet listeners;
  private int nListeners;

  // DOM Level 3 userData dictionary.
  private HashMap userData;
  private HashMap userDataHandlers;

  //
  // Some of the methods here are declared 'final' because
  // knowledge about their implementation is built into this
  // class -- for both integrity and performance.
  //

  /**
   * Reduces space utilization for this node.
   */
  public void compact()
  {
  }

  /**
   * Constructs a node and associates it with its owner.  Only
   * Document and DocumentType nodes may be created with no owner,
   * and DocumentType nodes get an owner as soon as they are
   * associated with a document.
   */
  protected DomNode(short nodeType, DomDocument owner)
  {
    this.nodeType = nodeType;

    if (owner == null)
      {
        // DOM calls never go down this path
        if (nodeType != DOCUMENT_NODE && nodeType != DOCUMENT_TYPE_NODE)
          {
            throw new IllegalArgumentException ("no owner!");
          }
      }
    this.owner = owner;
    this.listeners = new HashSet();
  }


  /**
   * <b>DOM L1</b>
   * Returns null; Element subclasses must override this method.
   */
  public NamedNodeMap getAttributes()
  {
    return null;
  }

  /**
   * <b>DOM L2></b>
   * Returns true iff this is an element node with attributes.
   */
  public boolean hasAttributes()
  {
    return false;
  }

  /**
   * <b>DOM L1</b>
   * Returns a list, possibly empty, of the children of this node.
   * In this implementation, to conserve memory, nodes are the same
   * as their list of children.  This can have ramifications for
   * subclasses, which may need to provide their own getLength method
   * for reasons unrelated to the NodeList method of the same name.
   */
  public NodeList getChildNodes()
  {
    return this;
  }

  /**
   * <b>DOM L1</b>
   * Returns the first child of this node, or null if there are none.
   */
  public Node getFirstChild()
  {
    return first;
  }

  /**
   * <b>DOM L1</b>
   * Returns the last child of this node, or null if there are none.
   */
  public Node getLastChild()
  {
    return last;
  }

  /**
   * <b>DOM L1</b>
   * Returns true if this node has children.
   */
  public boolean hasChildNodes()
  {
    return length != 0;
  }


  /**
   * Exposes the internal "readonly" flag.  In DOM, children of
   * entities and entity references are readonly, as are the
   * objects associated with DocumentType objets.
   */
  public final boolean isReadonly()
  {
    return readonly;
  }

  /**
   * Sets the internal "readonly" flag so this subtree can't be changed.
   * Subclasses need to override this method for any associated content
   * that's not a child node, such as an element's attributes or the
   * (few) declarations associated with a DocumentType.
   */
  public void makeReadonly()
  {
    readonly = true;
    for (DomNode child = first; child != null; child = child.next)
      {
        child.makeReadonly();
      }
  }

  /**
   * Used to adopt a node to a new document.
   */
  void setOwner(DomDocument doc)
  {
    this.owner = doc;
    for (DomNode ctx = first; ctx != null; ctx = ctx.next)
      {
        ctx.setOwner(doc);
      }
  }

  // just checks the node for inclusion -- may be called many
  // times (docfrag) before anything is allowed to change
  private void checkMisc(DomNode child)
  {
    if (readonly && !owner.building)
      {
        throw new DomDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
                                  null, this, 0);
      }
    for (DomNode ctx = this; ctx != null; ctx = ctx.parent)
      {
        if (child == ctx)
          {
            throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR,
                                      "can't make ancestor into a child",
                                      this, 0);
          }
      }

    DomDocument owner = (nodeType == DOCUMENT_NODE) ? (DomDocument) this :
      this.owner;
    DomDocument childOwner = child.owner;
    short childNodeType = child.nodeType;

    if (childOwner != owner)
      {
        // new in DOM L2, this case -- patch it up later, in reparent()
        if (!(childNodeType == DOCUMENT_TYPE_NODE && childOwner == null))
          {
            throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR,
                                      null, child, 0);
          }
      }

    // enforce various structural constraints
    switch (nodeType)
      {
      case DOCUMENT_NODE:
        switch (childNodeType)
          {
          case ELEMENT_NODE:
          case PROCESSING_INSTRUCTION_NODE:
          case COMMENT_NODE:
          case DOCUMENT_TYPE_NODE:
            return;
          }
        break;

      case ATTRIBUTE_NODE:
        switch (childNodeType)
          {
          case TEXT_NODE:
          case ENTITY_REFERENCE_NODE:
            return;
          }
        break;

      case DOCUMENT_FRAGMENT_NODE:
      case ENTITY_REFERENCE_NODE:
      case ELEMENT_NODE:
      case ENTITY_NODE:
        switch (childNodeType)
          {
          case ELEMENT_NODE:
          case TEXT_NODE:
          case COMMENT_NODE:
          case PROCESSING_INSTRUCTION_NODE:
          case CDATA_SECTION_NODE:
          case ENTITY_REFERENCE_NODE:
            return;
          }
        break;
      case DOCUMENT_TYPE_NODE:
        if (!owner.building)
          break;
        switch (childNodeType)
          {
          case COMMENT_NODE:
          case PROCESSING_INSTRUCTION_NODE:
            return;
          }
        break;
      }
    if (owner.checkingWellformedness)
      {
        throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR,
                                  "can't append " +
                                  nodeTypeToString(childNodeType) +
                                  " to node of type " +
                                  nodeTypeToString(nodeType),
                                  this, 0);
      }
  }

  // Here's hoping a good optimizer will detect the case when the
  // next several methods are never called, and won't allocate
  // object code space of any kind.  (Case:  not reporting any
  // mutation events.  We can also remove some static variables
  // listed above.)

  private void insertionEvent(DomEvent.DomMutationEvent event,
                              DomNode target)
  {
    if (owner == null || owner.building)
      {
        return;
      }
    boolean doFree = false;

    if (event == null)
      {
        event = getMutationEvent();
      }
    if (event != null)
      {
        doFree = true;
      }
    else
      {
        event = new DomEvent.DomMutationEvent(null);
      }
    event.initMutationEvent("DOMNodeInserted",
                            true /* bubbles */, false /* nocancel */,
                            this /* related */, null, null, null, (short) 0);
    target.dispatchEvent(event);

    // XXX should really visit every descendant of 'target'
    // and sent a DOMNodeInsertedIntoDocument event to it...
    // bleech, there's no way to keep that acceptably fast.

    if (doFree)
      {
        event.target = null;
        event.relatedNode = null;
        event.currentNode = null;
        eventDataLock = false;
      } // else we created work for the GC
  }

  private void removalEvent(DomEvent.DomMutationEvent event,
                            DomNode target)
  {
    if (owner == null || owner.building)
      {
        return;
      }
    boolean doFree = false;

    if (event == null)
      {
        event = getMutationEvent();
      }
    if (event != null)
      {
        doFree = true;
      }
    else
      {
        event = new DomEvent.DomMutationEvent(null);
      }
    event.initMutationEvent("DOMNodeRemoved",
                            true /* bubbles */, false /* nocancel */,
                            this /* related */, null, null, null, (short) 0);
    target.dispatchEvent(event);

    // XXX should really visit every descendant of 'target'
    // and sent a DOMNodeRemovedFromDocument event to it...
    // bleech, there's no way to keep that acceptably fast.

    event.target = null;
    event.relatedNode = null;
    event.currentNode = null;
    if (doFree)
      {
        eventDataLock = false;
      }
    // else we created more work for the GC
  }

  //
  // Avoid creating lots of memory management work, by using a simple
  // allocation strategy for the mutation event objects that get used
  // at least once per tree modification.  We can't use stack allocation,
  // so we do the next simplest thing -- more or less, static allocation.
  // Concurrent notifications should be rare, anyway.
  //
  // Returns the preallocated object, which needs to be carefully freed,
  // or null to indicate the caller needs to allocate their own.
  //
  static private DomEvent.DomMutationEvent getMutationEvent()
  {
    synchronized (lockNode)
      {
        if (eventDataLock)
          {
            return null;
          }
        eventDataLock = true;
        return mutationEvent;
      }
  }

  // NOTE:  this is manually inlined in the insertion
  // and removal event methods above; change in sync.
  static private void freeMutationEvent()
  {
    // clear fields to enable GC
    mutationEvent.clear();
    eventDataLock = false;
  }

  void setDepth(int depth)
  {
    this.depth = depth;
    for (DomNode ctx = first; ctx != null; ctx = ctx.next)
      {
        ctx.setDepth(depth + 1);
      }
  }

  /**
   * <b>DOM L1</b>
   * Appends the specified node to this node's list of children.
   * Document subclasses must override this to enforce the restrictions
   * that there be only one element and document type child.
   *
   * <p> Causes a DOMNodeInserted mutation event to be reported.
   * Will first cause a DOMNodeRemoved event to be reported if the
   * parameter already has a parent.  If the new child is a document
   * fragment node, both events will be reported for each child of
   * the fragment; the order in which children are removed and
   * inserted is implementation-specific.
   *
   * <p> If this DOM has been compiled without mutation event support,
   * these events will not be reported.
   */
  public Node appendChild(Node newChild)
  {
    try
      {
        DomNode child = (DomNode) newChild;

        if (child.nodeType == DOCUMENT_FRAGMENT_NODE)
          {
            // Append all nodes in the fragment to this node
            for (DomNode ctx = child.first; ctx != null; ctx = ctx.next)
              {
                checkMisc(ctx);
              }
            for (DomNode ctx = child.first; ctx != null; )
              {
                DomNode ctxNext = ctx.next;
                appendChild(ctx);
                ctx = ctxNext;
              }
          }
        else
          {
            checkMisc(child);
            if (child.parent != null)
              {
                child.parent.removeChild(child);
              }
            child.parent = this;
            child.index = length++;
            child.setDepth(depth + 1);
            child.next = null;
            if (last == null)
              {
                first = child;
                child.previous = null;
              }
            else
              {
                last.next = child;
                child.previous = last;
              }
            last = child;

            if (reportMutations)
              {
                insertionEvent(null, child);
              }
          }

        return child;
      }
    catch (ClassCastException e)
      {
        throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR,
                                  null, newChild, 0);
    }
  }

  /**
   * <b>DOM L1</b>
   * Inserts the specified node in this node's list of children.
   * Document subclasses must override this to enforce the restrictions
   * that there be only one element and document type child.
   *
   * <p> Causes a DOMNodeInserted mutation event to be reported.  Will
   * first cause a DOMNodeRemoved event to be reported if the newChild
   * parameter already has a parent. If the new child is a document
   * fragment node, both events will be reported for each child of
   * the fragment; the order in which children are removed and inserted
   * is implementation-specific.
   *
   * <p> If this DOM has been compiled without mutation event support,
   * these events will not be reported.
   */
  public Node insertBefore(Node newChild, Node refChild)
  {
    if (refChild == null)
      {
        return appendChild(newChild);
      }

    try
      {
        DomNode child = (DomNode) newChild;
        DomNode ref = (DomNode) refChild;

        if (child.nodeType == DOCUMENT_FRAGMENT_NODE)
          {
            // Append all nodes in the fragment to this node
            for (DomNode ctx = child.first; ctx != null; ctx = ctx.next)
              {
                checkMisc(ctx);
              }
            for (DomNode ctx = child.first; ctx != null; )
              {
                DomNode ctxNext = ctx.next;
                insertBefore(ctx, ref);
                ctx = ctxNext;
              }
          }
        else
          {
            checkMisc(child);
            if (ref == null || ref.parent != this)
              {
                throw new DomDOMException(DOMException.NOT_FOUND_ERR,
                                          null, ref, 0);
              }
            if (ref == child)
              {
                throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR,
                                          "can't insert node before itself",
                                          ref, 0);
              }

            if (child.parent != null)
              {
                child.parent.removeChild(child);
              }
            child.parent = this;
            int i = ref.index;
            child.setDepth(depth + 1);
            child.next = ref;
            if (ref.previous != null)
              {
                ref.previous.next = child;
              }
            child.previous = ref.previous;
            ref.previous = child;
            if (first == ref)
              {
                first = child;
              }
            // index renumbering
            for (DomNode ctx = child; ctx != null; ctx = ctx.next)
              {
                ctx.index = i++;
              }

            if (reportMutations)
              {
                insertionEvent(null, child);
              }
            length++;
          }

        return child;
      }
    catch (ClassCastException e)
      {
        throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR,
                                  null, newChild, 0);
      }
  }

  /**
   * <b>DOM L1</b>
   * Replaces the specified node in this node's list of children.
   * Document subclasses must override this to test the restrictions
   * that there be only one element and document type child.
   *
   * <p> Causes DOMNodeRemoved and DOMNodeInserted mutation event to be
   * reported.  Will cause another DOMNodeRemoved event to be reported if
   * the newChild parameter already has a parent.  These events may be
   * delivered in any order, except that the event reporting removal
   * from such an existing parent will always be delivered before the
   * event reporting its re-insertion as a child of some other node.
   * The order in which children are removed and inserted is implementation
   * specific.
   *
   * <p> If your application needs to depend on the in which those removal
   * and insertion events are delivered, don't use this API.  Instead,
   * invoke the removeChild and insertBefore methods directly, to guarantee
   * a specific delivery order.  Similarly, don't use document fragments,
   * Otherwise your application code may not work on a DOM which implements
   * this method differently.
   *
   * <p> If this DOM has been compiled without mutation event support,
   * these events will not be reported.
   */
  public Node replaceChild(Node newChild, Node refChild)
  {
    try
      {
        DomNode child = (DomNode) newChild;
        DomNode ref = (DomNode) refChild;

        DomEvent.DomMutationEvent event = getMutationEvent();
        boolean doFree = (event != null);

        if (child.nodeType == DOCUMENT_FRAGMENT_NODE)
          {
            // Append all nodes in the fragment to this node
            for (DomNode ctx = child.first; ctx != null; ctx = ctx.next)
              {
                checkMisc(ctx);
              }
            if (ref == null || ref.parent != this)
              {
                throw new DomDOMException(DOMException.NOT_FOUND_ERR,
                                          null, ref, 0);
              }

            if (reportMutations)
              {
                removalEvent(event, ref);
              }
            length--;
            length += child.length;

            if (child.length == 0)
              {
                // Removal
                if (ref.previous != null)
                  {
                    ref.previous.next = ref.next;
                  }
                if (ref.next != null)
                  {
                    ref.next.previous = ref.previous;
                  }
                if (first == ref)
                  {
                    first = ref.next;
                  }
                if (last == ref)
                  {
                    last = ref.previous;
                  }
              }
            else
              {
                int i = ref.index;
                for (DomNode ctx = child.first; ctx != null; ctx = ctx.next)
                  {
                    // Insertion
                    ctx.parent = this;
                    ctx.index = i++;
                    ctx.setDepth(ref.depth);
                    if (ctx == child.first)
                      {
                        ctx.previous = ref.previous;
                      }
                    if (ctx == child.last)
                      {
                        ctx.next = ref.next;
                      }
                  }
                if (first == ref)
                  {
                    first = child.first;
                  }
                if (last == ref)
                  {
                    last = child.last;
                  }
              }
          }
        else
          {
            checkMisc(child);
            if (ref == null || ref.parent != this)
              {
                throw new DomDOMException(DOMException.NOT_FOUND_ERR,
                                          null, ref, 0);
              }

            if (reportMutations)
              {
                removalEvent(event, ref);
              }

            if (child.parent != null)
              {
                child.parent.removeChild(child);
              }
            child.parent = this;
            child.index = ref.index;
            child.setDepth(ref.depth);
            if (ref.previous != null)
              {
                ref.previous.next = child;
              }
            child.previous = ref.previous;
            if (ref.next != null)
              {
                ref.next.previous = child;
              }
            child.next = ref.next;
            if (first == ref)
              {
                first = child;
              }
            if (last == ref)
              {
                last = child;
              }

            if (reportMutations)
              {
                insertionEvent(event, child);
              }
            if (doFree)
              {
                freeMutationEvent();
              }
          }
        ref.parent = null;
        ref.index = 0;
        ref.setDepth(0);
        ref.previous = null;
        ref.next = null;

        return ref;
      }
    catch (ClassCastException e)
      {
        throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR,
                                  null, newChild, 0);
      }
  }

  /**
   * <b>DOM L1</b>
   * Removes the specified child from this node's list of children,
   * or else reports an exception.
   *
   * <p> Causes a DOMNodeRemoved mutation event to be reported.
   *
   * <p> If this DOM has been compiled without mutation event support,
   * these events will not be reported.
   */
  public Node removeChild(Node refChild)
  {
    try
      {
        DomNode ref = (DomNode) refChild;

        if (ref == null || ref.parent != this)
          {
            throw new DomDOMException(DOMException.NOT_FOUND_ERR,
                                      null, ref, 0);
          }
        if (readonly && !owner.building)
          {
            throw new DomDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR,
                                      null, this, 0);
          }

        for (DomNode child = first; child != null; child = child.next)
          {
            if (child == ref)
              {
                if (reportMutations)
                  {
                    removalEvent(null, child);
                  }

                length--;
                if (ref.previous != null)
                  {
                    ref.previous.next = ref.next;
                  }
                if (ref.next != null)
                  {
                    ref.next.previous = ref.previous;
                  }
                if (first == ref)
                  {
                    first = ref.next;
                  }
                if (last == ref)
                  {
                    last = ref.previous;
                  }
                // renumber indices
                int i = 0;
                for (DomNode ctx = first; ctx != null; ctx = ctx.next)
                  {
                    ctx.index = i++;
                  }
                ref.parent = null;
                ref.setDepth(0);
                ref.index = 0;
                ref.previous = null;
                ref.next = null;

                return ref;
              }
          }
        throw new DomDOMException(DOMException.NOT_FOUND_ERR,
                                  "that's no child of mine", refChild, 0);
      }
    catch (ClassCastException e)
      {
        throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR,
                                  null, refChild, 0);
      }
  }

  /**
   * <b>DOM L1 (NodeList)</b>
   * Returns the item with the specified index in this NodeList,
   * else null.
   */
  public Node item(int index)
  {
    DomNode child = first;
    int count = 0;
    while (child != null && count < index)
      {
        child = child.next;
        count++;
      }
    return child;
  }

  /**
   * <b>DOM L1 (NodeList)</b>
   * Returns the number of elements in this NodeList.
   * (Note that many interfaces have a "Length" property, not just
   * NodeList, and if a node subtype must implement one of those,
   * it will also need to override getChildNodes.)
   */
  public int getLength()
  {
    return length;
  }

  /**
   * Minimize extra space consumed by this node to hold children and event
   * listeners.
   */
  public void trimToSize()
  {
  }

  /**
   * <b>DOM L1</b>
   * Returns the previous sibling, if one is known.
   */
  public Node getNextSibling()
  {
    return next;
  }

  /**
   * <b>DOM L1</b>
   * Returns the previous sibling, if one is known.
   */
  public Node getPreviousSibling()
  {
    return previous;
  }

  /**
   * <b>DOM L1</b>
   * Returns the parent node, if one is known.
   */
  public Node getParentNode()
  {
    return parent;
  }

  /**
   * <b>DOM L2</b>
   * Consults the DOM implementation to determine if the requested
   * feature is supported.  DocumentType subclasses must override
   * this method, and associate themselves directly with the
   * DOMImplementation node used.  (This method relies on being able
   * to access the DOMImplementation from the owner document, but
   * DocumentType nodes can be created without an owner.)
   */
  public boolean isSupported(String feature, String version)
  {
    Document            doc = owner;
    DOMImplementation   impl = null;

    if (doc == null && nodeType == DOCUMENT_NODE)
      {
        doc = (Document) this;
      }

    if (doc == null)
      {
        // possible for DocumentType
        throw new IllegalStateException ("unbound ownerDocument");
      }

    impl = doc.getImplementation();
    return impl.hasFeature(feature, version);
  }

  /**
   * <b>DOM L1 (modified in L2)</b>
   * Returns the owner document.  This is only null for Document nodes,
   * and (new in L2) for DocumentType nodes which have not yet been
   * associated with the rest of their document.
   */
  final public Document getOwnerDocument()
  {
    return owner;
  }

  /**
   * <b>DOM L1</b>
   * Does nothing; this must be overridden (along with the
   * getNodeValue method) for nodes with a non-null defined value.
   */
  public void setNodeValue(String value)
  {
  }

  /**
   * <b>DOM L1</b>
   * Returns null; this must be overridden for nodes types with
   * a defined value, along with the setNodeValue method.
   */
  public String getNodeValue()
  {
    return null;
  }

  /** This forces GCJ compatibility.
   * Without this method GCJ is unable to compile to byte code.
   */
  public final short getNodeType()
  {
    return nodeType;
  }

  /** This forces GCJ compatibility.
   * Without this method GCJ seems unable to natively compile GNUJAXP.
   */
  public abstract String getNodeName();

  /**
   * <b>DOM L2</b>
   * Does nothing; this must be overridden (along with the
   * getPrefix method) for element and attribute nodes.
   */
  public void setPrefix(String prefix)
  {
  }

  /**
   * <b>DOM L2</b>
   * Returns null; this must be overridden for element and
   * attribute nodes.
   */
  public String getPrefix()
  {
    return null;
  }

  /**
   * <b>DOM L2</b>
   * Returns null; this must be overridden for element and
   * attribute nodes.
   */
  public String getNamespaceURI()
  {
    return null;
  }

  /**
   * <b>DOM L2</b>
   * Returns the node name; this must be overridden for element and
   * attribute nodes.
   */
  public String getLocalName()
  {
    return null;
  }

  /**
   * <b>DOM L1</b>
   * Returns a clone of this node which optionally includes cloned
   * versions of child nodes.  Clones are always mutable, except for
   * entity reference nodes.
   */
  public Node cloneNode(boolean deep)
  {
    if (deep)
      {
        return cloneNodeDeepInternal(true, null);
      }

    DomNode node = (DomNode) clone();
    if (nodeType == ENTITY_REFERENCE_NODE)
      {
        node.makeReadonly();
      }
    notifyUserDataHandlers(UserDataHandler.NODE_CLONED, this, node);
    return node;
  }

  /**
   * Returns a deep clone of this node.
   */
  private DomNode cloneNodeDeepInternal(boolean root, DomDocument doc)
  {
    DomNode node = (DomNode) clone();
    boolean building = false; // Never used unless root is true
    if (root)
      {
        doc = (nodeType == DOCUMENT_NODE) ? (DomDocument) node : node.owner;
        building = doc.building;
        doc.building = true; // Permit certain structural rules
      }
    node.owner = doc;
    for (DomNode ctx = first; ctx != null; ctx = ctx.next)
      {
        DomNode newChild = ctx.cloneNodeDeepInternal(false, doc);
        node.appendChild(newChild);
      }
    if (nodeType == ENTITY_REFERENCE_NODE)
      {
        node.makeReadonly();
      }
    if (root)
      {
        doc.building = building;
      }
    notifyUserDataHandlers(UserDataHandler.NODE_CLONED, this, node);
    return node;
  }

  void notifyUserDataHandlers(short op, Node src, Node dst)
  {
    if (userDataHandlers != null)
      {
        for (Iterator i = userDataHandlers.entrySet().iterator(); i.hasNext(); )
          {
            Map.Entry entry = (Map.Entry) i.next();
            String key = (String) entry.getKey();
            UserDataHandler handler = (UserDataHandler) entry.getValue();
            Object data = userData.get(key);
            handler.handle(op, key, data, src, dst);
          }
      }
  }

  /**
   * Clones this node; roughly equivalent to cloneNode(false).
   * Element subclasses must provide a new implementation which
   * invokes this method to handle the basics, and then arranges
   * to clone any element attributes directly.  Attribute subclasses
   * must make similar arrangements, ensuring that existing ties to
   * elements are broken by cloning.
   */
  public Object clone()
  {
    try
      {
        DomNode node = (DomNode) super.clone();

        node.parent = null;
        node.depth = 0;
        node.index = 0;
        node.length = 0;
        node.first = null;
        node.last = null;
        node.previous = null;
        node.next = null;

        node.readonly = false;
        node.listeners = new HashSet();
        node.nListeners = 0;
        return node;

      }
    catch (CloneNotSupportedException x)
      {
        throw new Error("clone didn't work");
      }
  }

  // the elements-by-tagname stuff is needed for both
  // elements and documents ... this is in lieu of a
  // common base class between Node and NodeNS.

  /**
   * <b>DOM L1</b>
   * Creates a NodeList giving array-style access to elements with
   * the specified name.  Access is fastest if indices change by
   * small values, and the DOM is not modified.
   */
  public NodeList getElementsByTagName(String tag)
  {
    return new ShadowList(null, tag);
  }

  /**
   * <b>DOM L2</b>
   * Creates a NodeList giving array-style access to elements with
   * the specified namespace and local name.  Access is fastest if
   * indices change by small values, and the DOM is not modified.
   */
  public NodeList getElementsByTagNameNS(String namespace, String local)
  {
    return new ShadowList(namespace, local);
  }


  //
  // This shadow class is GC-able even when the live list it shadows
  // can't be, because of event registration hookups.  Its finalizer
  // makes that live list become GC-able.
  //
  final class ShadowList
    implements NodeList
  {

    private LiveNodeList liveList;

    ShadowList(String ns, String local)
    {
      liveList = new LiveNodeList(ns, local);
    }

    public void finalize()
    {
      liveList.detach();
      liveList = null;
    }

    public Node item(int index)
    {
      return liveList.item(index);
    }

    public int getLength()
    {
      return liveList.getLength();
    }
  }

  final class LiveNodeList
    implements NodeList, EventListener, NodeFilter
  {

    private final boolean matchAnyURI;
    private final boolean matchAnyName;
    private final String elementURI;
    private final String elementName;

    private DomIterator current;
    private int lastIndex;

    LiveNodeList(String uri, String name)
    {
      elementURI = uri;
      elementName = name;
      matchAnyURI = "*".equals(uri);
      matchAnyName = "*".equals(name);

      DomNode.this.addEventListener("DOMNodeInserted", this, true);
      DomNode.this.addEventListener("DOMNodeRemoved", this, true);
    }

    void detach()
    {
      if (current != null)
        current.detach();
      current = null;

      DomNode.this.removeEventListener("DOMNodeInserted", this, true);
      DomNode.this.removeEventListener("DOMNodeRemoved", this, true);
    }

    public short acceptNode(Node element)
    {
      if (element == DomNode.this)
        {
          return FILTER_SKIP;
        }

      // use namespace-aware matching ...
      if (elementURI != null)
        {
          if (!(matchAnyURI
                || elementURI.equals(element.getNamespaceURI())))
            {
              return FILTER_SKIP;
            }
          if (!(matchAnyName
                || elementName.equals(element.getLocalName())))
            {
              return FILTER_SKIP;
            }

          // ... or qName-based kind.
        }
      else
        {
          if (!(matchAnyName
                || elementName.equals(element.getNodeName())))
            {
              return FILTER_SKIP;
            }
        }
      return FILTER_ACCEPT;
    }

    private DomIterator createIterator()
    {
      return new DomIterator(DomNode.this,
                             NodeFilter.SHOW_ELEMENT,
                             this,      /* filter */
                             true       /* expand entity refs */
                            );
    }

    public void handleEvent(Event e)
    {
      MutationEvent     mutation = (MutationEvent) e;
      Node              related = mutation.getRelatedNode();

      // XXX if it's got children ... check all kids too, they
      // will invalidate our saved index

      if (related.getNodeType() != Node.ELEMENT_NODE ||
          related.getNodeName() != elementName ||
          related.getNamespaceURI() != elementURI)
        {
          return;
        }

      if (current != null)
        current.detach();
      current = null;
    }

    public Node item(int index)
    {
      if (current == null)
        {
          current = createIterator();
          lastIndex = -1;
        }

      // last node or before?  go backwards
      if (index <= lastIndex) {
        while (index != lastIndex) {
          current.previousNode ();
          lastIndex--;
        }
        Node ret = current.previousNode ();
        current.detach();
        current = null;
        return ret;
      }

      // somewhere after last node
      while (++lastIndex != index)
        current.nextNode ();

      Node ret = current.nextNode ();
      current.detach();
      current = null;
      return ret;
    }

    public int getLength()
    {
      int retval = 0;
      NodeIterator iter = createIterator();

      while (iter.nextNode() != null)
        {
          retval++;
        }
      iter.detach();
      return retval;
    }

  }

  //
  // EventTarget support
  //
  static final class ListenerRecord
  {

    String type;
    EventListener listener;
    boolean useCapture;

    // XXX use JDK 1.2 java.lang.ref.WeakReference to listener,
    // and we can both get rid of "shadow" classes and remove
    // the need for applications to apply similar trix ... but
    // JDK 1.2 support isn't generally available yet

    ListenerRecord(String type, EventListener listener, boolean useCapture)
    {
      this.type = type.intern();
      this.listener = listener;
      this.useCapture = useCapture;
    }

    public boolean equals(Object o)
    {
      ListenerRecord rec = (ListenerRecord)o;
      return listener == rec.listener
        && useCapture == rec.useCapture
        && type == rec.type;
    }

    public int hashCode()
    {
        return listener.hashCode() ^ type.hashCode();
    }
  }

  /**
   * <b>DOM L2 (Events)</b>
   * Returns an instance of the specified type of event object.
   * Understands about DOM Mutation, HTML, and UI events.
   *
   * <p>If the name of the event type begins with "USER-", then an object
   * implementing the "Event" class will be returned; this provides a
   * limited facility for application-defined events to use the DOM event
   * infrastructure.  Alternatively, use one of the standard DOM event
   * classes and initialize it using use such a "USER-" event type name;
   * or defin, instantiate, and initialize an application-specific subclass
   * of DomEvent and pass that to dispatchEvent().
   *
   * @param eventType Identifies the particular DOM feature module
   *    defining the type of event, such as "MutationEvents".
   *    <em>The event "name" is a different kind of "type".</em>
   */
  public Event createEvent(String eventType)
  {
    eventType = eventType.toLowerCase();

    if ("mutationevents".equals(eventType))
      {
        return new DomEvent.DomMutationEvent(null);
      }

    if ("htmlevents".equals(eventType)
        || "events".equals(eventType)
        || "user-events".equals(eventType))
      {
        return new DomEvent(null);
      }

    if ("uievents".equals(eventType))
      {
        return new DomEvent.DomUIEvent(null);
      }

    // mouse events

    throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR,
                              eventType, null, 0);
  }

  /**
   * <b>DOM L2 (Events)</b>
   * Registers an event listener's interest in a class of events.
   */
  public final void addEventListener(String type,
                                     EventListener listener,
                                     boolean useCapture)
  {
    // prune duplicates
    ListenerRecord record;

    record = new ListenerRecord(type, listener, useCapture);
    listeners.add(record);
    nListeners = listeners.size();
  }

  // XXX this exception should be discarded from DOM

  // this class can be instantiated, unlike the one in the spec
  static final class DomEventException
    extends EventException
  {

    DomEventException()
    {
      super(UNSPECIFIED_EVENT_TYPE_ERR, "unspecified event type");
    }

  }

  /**
   * <b>DOM L2 (Events)</b>
   * Delivers an event to all relevant listeners, returning true if the
   * caller should perform their default action.  Note that the event
   * must have been provided by the createEvent() method on this
   * class, else it can't be dispatched.
   *
   * @see #createEvent
   *
   * @exception NullPointerException When a null event is passed.
   * @exception ClassCastException When the event wasn't provided by
   *    the createEvent method, or otherwise isn't a DomEvent.
   * @exception EventException If the event type wasn't specified
   */
  public final boolean dispatchEvent(Event event)
    throws EventException
  {
    DomEvent e = (DomEvent) event;
    DomNode[] ancestors = null;
    int ancestorMax = 0;
    boolean haveDispatchDataLock = false;

    if (e.type == null)
      {
        throw new DomEventException();
      }

    e.doDefault = true;
    e.target = this;

    //
    // Typical case:  one nonrecursive dispatchEvent call at a time
    // for this class.  If that's our case, we can avoid allocating
    // garbage, which is overall a big win.  Even with advanced GCs
    // that deal well with short-lived garbage, and wayfast allocators,
    // it still helps.
    //
    // Remember -- EVERY mutation goes though here at least once.
    //
    // When populating a DOM tree, trying to send mutation events is
    // the primary cost; this dominates the critical path.
    //
    try
      {
        DomNode current;
        int index;
        boolean haveAncestorRegistrations = false;
        ListenerRecord[] notificationSet;
        int ancestorLen;

        synchronized (lockNode)
          {
            if (!dispatchDataLock)
              {
                haveDispatchDataLock = dispatchDataLock = true;
                notificationSet = DomNode.notificationSet;
                ancestors = DomNode.ancestors;
              }
            else
              {
                notificationSet = new ListenerRecord[NOTIFICATIONS_INIT];
                ancestors = new DomNode[ANCESTORS_INIT];
              }
            ancestorLen = ancestors.length;
          }

        // Climb to the top of this subtree and handle capture, letting
        // each node (from the top down) capture until one stops it or
        // until we get to this one.
        current = (parent == null) ? this : parent;
        if (current.depth >= ANCESTORS_INIT)
          {
            DomNode[] newants = new DomNode[current.depth + 1];
            System.arraycopy(ancestors, 0, newants, 0, ancestors.length);
            ancestors = newants;
            ancestorLen = ancestors.length;
          }
        for (index = 0; index < ancestorLen; index++)
          {
            if (current == null || current.depth == 0)
              break;

            if (current.nListeners != 0)
              {
                haveAncestorRegistrations = true;
              }
            ancestors [index] = current;
            current = current.parent;
          }
        if (current.depth > 0)
          {
            throw new RuntimeException("dispatchEvent capture stack size");
          }

        ancestorMax = index;
        e.stop = false;

        if (haveAncestorRegistrations)
          {
            e.eventPhase = Event.CAPTURING_PHASE;
            while (!e.stop && index-- > 0)
              {
                current = ancestors [index];
                if (current.nListeners != 0)
                  {
                    notifyNode(e, current, true, notificationSet);
                  }
              }
          }

        // Always deliver events to the target node (this)
        // unless stopPropagation was called.  If we saw
        // no registrations yet (typical!), we never will.
        if (!e.stop && nListeners != 0)
          {
            e.eventPhase = Event.AT_TARGET;
            notifyNode (e, this, false, notificationSet);
          }
        else if (!haveAncestorRegistrations)
          {
            e.stop = true;
          }

        // If the event bubbles and propagation wasn't halted,
        // walk back up the ancestor list.  Stop bubbling when
        // any bubbled event handler stops it.

        if (!e.stop && e.bubbles)
          {
            e.eventPhase = Event.BUBBLING_PHASE;
            for (index = 0;
                 !e.stop
                 && index < ancestorMax
                 && (current = ancestors[index]) != null;
                 index++)
              {
                if (current.nListeners != 0)
                  {
                    notifyNode(e, current, false, notificationSet);
                  }
              }
          }
        e.eventPhase = 0;

        // Caller chooses whether to perform the default
        // action based on return from this method.
        return e.doDefault;

      }
    finally
      {
        if (haveDispatchDataLock)
          {
            // synchronize to force write ordering
            synchronized (lockNode)
              {
                // null out refs to ensure they'll be GC'd
                for (int i = 0; i < ancestorMax; i++)
                  {
                    ancestors [i] = null;
                  }
                // notificationSet handled by notifyNode

                dispatchDataLock = false;
              }
          }
      }
  }

  private void notifyNode(DomEvent e,
                          DomNode current,
                          boolean capture,
                          ListenerRecord[] notificationSet)
  {
    int count = 0;
    Iterator iter;

    iter = current.listeners.iterator();

    // do any of this set of listeners get notified?
    while (iter.hasNext())
      {
        ListenerRecord rec = (ListenerRecord)iter.next();

        if (rec.useCapture != capture)
          {
            continue;
          }
        if (!e.type.equals (rec.type))
          {
            continue;
          }
        if (count >= notificationSet.length)
          {
            // very simple growth algorithm
            int len = Math.max(notificationSet.length, 1);
            ListenerRecord[] tmp = new ListenerRecord[len * 2];
            System.arraycopy(notificationSet, 0, tmp, 0,
                             notificationSet.length);
            notificationSet = tmp;
          }
        notificationSet[count++] = rec;
      }
    iter = null;

    // Notify just those listeners
    e.currentNode = current;
    for (int i = 0; i < count; i++)
      {
        try
          {
            iter = current.listeners.iterator();
            // Late in the DOM CR process (3rd or 4th CR?) the
            // removeEventListener spec became asymmetric with respect
            // to addEventListener ... effect is now immediate.
            while (iter.hasNext())
              {
                ListenerRecord rec = (ListenerRecord)iter.next();

                if (rec.equals(notificationSet[i]))
                  {
                    notificationSet[i].listener.handleEvent(e);
                    break;
                  }
              }
            iter = null;
          }
        catch (Exception x)
          {
            // ignore all exceptions
          }
        notificationSet[i] = null;              // free for GC
      }
  }

  /**
   * <b>DOM L2 (Events)</b>
   * Unregisters an event listener.
   */
  public final void removeEventListener(String type,
                                        EventListener listener,
                                        boolean useCapture)
  {
    listeners.remove(new ListenerRecord(type, listener, useCapture));
    nListeners = listeners.size();
    // no exceptions reported
  }

  /**
   * <b>DOM L1 (relocated in DOM L2)</b>
   * In this node and all contained nodes (including attributes if
   * relevant) merge adjacent text nodes.  This is done while ignoring
   * text which happens to use CDATA delimiters).
   */
  public final void normalize()
  {
    // Suspend readonly status
    boolean saved = readonly;
    readonly = false;
    for (DomNode ctx = first; ctx != null; ctx = ctx.next)
      {
        boolean saved2 = ctx.readonly;
        ctx.readonly = false;
        switch (ctx.nodeType)
          {
          case TEXT_NODE:
          case CDATA_SECTION_NODE:
            while (ctx.next != null &&
                   (ctx.next.nodeType == TEXT_NODE ||
                    ctx.next.nodeType == CDATA_SECTION_NODE))
              {
                Text text = (Text) ctx;
                text.appendData(ctx.next.getNodeValue());
                removeChild(ctx.next);
              }
            break;
          case ELEMENT_NODE:
            NamedNodeMap attrs = ctx.getAttributes();
            int len = attrs.getLength();
            for (int i = 0; i < len; i++)
              {
                DomNode attr = (DomNode) attrs.item(i);
                boolean saved3 = attr.readonly;
                attr.readonly = false;
                attr.normalize();
                attr.readonly = saved3;
              }
            // Fall through
          case DOCUMENT_NODE:
          case DOCUMENT_FRAGMENT_NODE:
          case ATTRIBUTE_NODE:
          case ENTITY_REFERENCE_NODE:
            ctx.normalize();
            break;
          }
        ctx.readonly = saved2;
      }
    readonly = saved;
  }

  /**
   * Returns true iff node types match, and either (a) both nodes have no
   * namespace and their getNodeName() values are the same, or (b) both
   * nodes have the same getNamespaceURI() and same getLocalName() values.
   *
   * <p>Note that notion of a "Per-Element-Type" attribute name scope, as
   * found in a non-normative appendix of the XML Namespaces specification,
   * is not supported here.  Your application must implement that notion,
   * typically by not bothering to check nameAndTypeEquals for attributes
   * without namespace URIs unless you already know their elements are
   * nameAndTypeEquals.
   */
  public boolean nameAndTypeEquals(Node other)
  {
    if (other == this)
      {
        return true;
      }
    // node types must match
    if (nodeType != other.getNodeType())
      {
        return false;
      }

    // if both have namespaces, do a "full" comparision
    // this is a "global" partition
    String ns1 = this.getNamespaceURI();
    String ns2 = other.getNamespaceURI();

    if (ns1 != null && ns2 != null)
      {
        return ns1.equals(ns2) &&
          equal(getLocalName(), other.getLocalName());
      }

    // if neither has a namespace, this is a "no-namespace" name.
    if (ns1 == null && ns2 == null)
      {
        if (!getNodeName().equals(other.getNodeName()))
          {
            return false;
          }
        // can test the non-normative "per-element-type" scope here.
        // if this is an attribute node and both nodes have been bound
        // to elements (!!), then return the nameAndTypeEquals()
        // comparison of those elements.
        return true;
      }

    // otherwise they're unequal: one scoped, one not.
    return false;
  }

  // DOM Level 3 methods

  public String getBaseURI()
  {
    return (parent != null) ? parent.getBaseURI() : null;
  }

  public short compareDocumentPosition(Node other)
    throws DOMException
  {
    return (short) compareTo(other);
  }

  /**
   * DOM nodes have a natural ordering: document order.
   */
  public final int compareTo(Object other)
  {
    if (other instanceof DomNode)
      {
        DomNode n1 = this;
        DomNode n2 = (DomNode) other;
        if (n1.owner != n2.owner)
          {
            return 0;
          }
        int d1 = n1.depth, d2 = n2.depth;
        int delta = d1 - d2;
        while (d1 > d2)
          {
            n1 = n1.parent;
            d1--;
          }
        while (d2 > d1)
          {
            n2 = n2.parent;
            d2--;
          }
        int c = compareTo2(n1, n2);
        return (c != 0) ? c : delta;
      }
    return 0;
  }

  /**
   * Compare two nodes at the same depth.
   */
  final int compareTo2(DomNode n1, DomNode n2)
  {
    if (n1 == n2 || n1.depth == 0 || n2.depth == 0)
      {
        return 0;
      }
    int c = compareTo2(n1.parent, n2.parent);
    return (c != 0) ? c : n1.index - n2.index;
  }

  public final String getTextContent()
    throws DOMException
  {
    return getTextContent(true);
  }

  final String getTextContent(boolean topLevel)
    throws DOMException
  {
    switch (nodeType)
      {
      case ELEMENT_NODE:
      case ENTITY_NODE:
      case ENTITY_REFERENCE_NODE:
      case DOCUMENT_FRAGMENT_NODE:
        CPStringBuilder buffer = new CPStringBuilder();
        for (DomNode ctx = first; ctx != null; ctx = ctx.next)
          {
            String textContent = ctx.getTextContent(false);
            if (textContent != null)
              {
                buffer.append(textContent);
              }
          }
        return buffer.toString();
      case TEXT_NODE:
      case CDATA_SECTION_NODE:
        if (((Text) this).isElementContentWhitespace())
          {
            return "";
          }
        return getNodeValue();
      case ATTRIBUTE_NODE:
        return getNodeValue();
      case COMMENT_NODE:
      case PROCESSING_INSTRUCTION_NODE:
        return topLevel ? getNodeValue() : "";
      default:
        return null;
      }
  }

  public void setTextContent(String textContent)
    throws DOMException
  {
    switch (nodeType)
      {
      case ELEMENT_NODE:
      case ATTRIBUTE_NODE:
      case ENTITY_NODE:
      case ENTITY_REFERENCE_NODE:
      case DOCUMENT_FRAGMENT_NODE:
        for (DomNode ctx = first; ctx != null; )
          {
            DomNode n = ctx.next;
            removeChild(ctx);
            ctx = n;
          }
        if (textContent != null)
          {
            Text text = owner.createTextNode(textContent);
            appendChild(text);
          }
        break;
      case TEXT_NODE:
      case CDATA_SECTION_NODE:
      case COMMENT_NODE:
      case PROCESSING_INSTRUCTION_NODE:
        setNodeValue(textContent);
        break;
      }
  }

  public boolean isSameNode(Node other)
  {
    return this == other;
  }

  public String lookupPrefix(String namespaceURI)
  {
    return (parent == null || parent == owner) ? null :
      parent.lookupPrefix(namespaceURI);
  }

  public boolean isDefaultNamespace(String namespaceURI)
  {
    return (parent == null || parent == owner) ? false :
      parent.isDefaultNamespace(namespaceURI);
  }

  public String lookupNamespaceURI(String prefix)
  {
    return (parent == null || parent == owner) ? null :
      parent.lookupNamespaceURI(prefix);
  }

  public boolean isEqualNode(Node arg)
  {
    if (this == arg)
      return true;
    if (arg == null)
      return false;
    if (nodeType != arg.getNodeType())
      return false;
    switch (nodeType)
      {
      case ELEMENT_NODE:
      case ATTRIBUTE_NODE:
        if (!equal(getLocalName(), arg.getLocalName()) ||
            !equal(getNamespaceURI(), arg.getNamespaceURI()))
          return false;
        break;
      case PROCESSING_INSTRUCTION_NODE:
        if (!equal(getNodeName(), arg.getNodeName()) ||
            !equal(getNodeValue(), arg.getNodeValue()))
          return false;
        break;
      case COMMENT_NODE:
      case TEXT_NODE:
      case CDATA_SECTION_NODE:
        if (!equal(getNodeValue(), arg.getNodeValue()))
          return false;
        break;
      }
    // Children
    Node argCtx = arg.getFirstChild();
    getFirstChild(); // because of DomAttr lazy children
    DomNode ctx = first;
    for (; ctx != null && argCtx != null; ctx = ctx.next)
      {
        if (nodeType == DOCUMENT_NODE)
          {
            // Ignore whitespace outside document element
            while (ctx != null && ctx.nodeType == TEXT_NODE)
              ctx = ctx.next;
            while (argCtx != null && ctx.getNodeType() == TEXT_NODE)
              argCtx = argCtx.getNextSibling();
            if (ctx == null && argCtx != null)
              return false;
            else if (argCtx == null && ctx != null)
              return false;
          }
        if (!ctx.isEqualNode(argCtx))
          return false;
        argCtx = argCtx.getNextSibling();
      }
    if (ctx != null || argCtx != null)
      return false;

    // TODO DocumentType
    return true;
  }

  boolean equal(String arg1, String arg2)
  {
    return ((arg1 == null && arg2 == null) ||
            (arg1 != null && arg1.equals(arg2)));
  }

  public Object getFeature(String feature, String version)
  {
    DOMImplementation impl = (nodeType == DOCUMENT_NODE) ?
      ((Document) this).getImplementation() : owner.getImplementation();
    if (impl.hasFeature(feature, version))
      {
        return this;
      }
    return null;
  }

  public Object setUserData(String key, Object data, UserDataHandler handler)
  {
    if (userData == null)
      {
        userData = new HashMap();
      }
    if (handler != null)
      {
        if (userDataHandlers == null)
          {
            userDataHandlers = new HashMap();
          }
        userDataHandlers.put(key, handler);
      }
    return userData.put(key, data);
  }

  public Object getUserData(String key)
  {
    if (userData == null)
      {
        return null;
      }
    return userData.get(key);
  }

  public String toString()
  {
    String nodeName = getNodeName();
    String nodeValue = getNodeValue();
    CPStringBuilder buf = new CPStringBuilder(getClass().getName());
    buf.append('[');
    if (nodeName != null)
      {
        buf.append(nodeName);
      }
    if (nodeValue != null)
      {
        if (nodeName != null)
          {
            buf.append('=');
          }
        buf.append('\'');
        buf.append(encode(nodeValue));
        buf.append('\'');
      }
    buf.append(']');
    return buf.toString();
  }

  String encode(String value)
  {
    CPStringBuilder buf = null;
    int len = value.length();
    for (int i = 0; i < len; i++)
      {
        char c = value.charAt(i);
        if (c == '\n')
          {
            if (buf == null)
              {
                buf = new CPStringBuilder(value.substring(0, i));
              }
            buf.append("\\n");
          }
        else if (c == '\r')
          {
            if (buf == null)
              {
                buf = new CPStringBuilder(value.substring(0, i));
              }
            buf.append("\\r");
          }
        else if (buf != null)
          {
            buf.append(c);
          }
      }
    return (buf != null) ? buf.toString() : value;
  }

  String nodeTypeToString(short nodeType)
  {
    switch (nodeType)
      {
      case ELEMENT_NODE:
        return "ELEMENT_NODE";
      case ATTRIBUTE_NODE:
        return "ATTRIBUTE_NODE";
      case TEXT_NODE:
        return "TEXT_NODE";
      case CDATA_SECTION_NODE:
        return "CDATA_SECTION_NODE";
      case DOCUMENT_NODE:
        return "DOCUMENT_NODE";
      case DOCUMENT_TYPE_NODE:
        return "DOCUMENT_TYPE_NODE";
      case COMMENT_NODE:
        return "COMMENT_NODE";
      case PROCESSING_INSTRUCTION_NODE:
        return "PROCESSING_INSTRUCTION_NODE";
      case DOCUMENT_FRAGMENT_NODE:
        return "DOCUMENT_FRAGMENT_NODE";
      case ENTITY_NODE:
        return "ENTITY_NODE";
      case ENTITY_REFERENCE_NODE:
        return "ENTITY_REFERENCE_NODE";
      case NOTATION_NODE:
        return "NOTATION_NODE";
      default:
        return "UNKNOWN";
      }
  }

  public void list(java.io.PrintStream out, int indent)
  {
    for (int i = 0; i < indent; i++)
      out.print(" ");
    out.println(toString());
    for (DomNode ctx = first; ctx != null; ctx = ctx.next)
      ctx.list(out, indent + 1);
  }

}
