/* 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);
              }
          }
        
        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)
  {
    DomNode node = (DomNode) clone();
    
    if (deep)
      {
        DomDocument doc = (nodeType == DOCUMENT_NODE) ?
          (DomDocument) node : node.owner;
        boolean building = doc.building;
        doc.building = true; // Permit certain structural rules
        for (DomNode ctx = first; ctx != null; ctx = ctx.next)
          {
            DomNode newChild = (DomNode) ctx.cloneNode(deep);
            newChild.setOwner(doc);
            node.appendChild(newChild);
          }
        doc.building = building;
      }
    if (nodeType == ENTITY_REFERENCE_NODE)
      {
        node.makeReadonly();
      }
    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;
        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);
  }

}

