/* 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 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:
        StringBuffer buffer = new StringBuffer();
        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();
    StringBuffer buf = new StringBuffer(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)
  {
    StringBuffer 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 StringBuffer(value.substring(0, i));
              }
            buf.append("\\n");
          }
        else if (c == '\r')
          {
            if (buf == null)
              {
                buf = new StringBuffer(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);
  }

}

