/* DomDocument.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.Iterator;
import javax.xml.XMLConstants;

import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.DocumentType;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.DOMException;
import org.w3c.dom.Element;
import org.w3c.dom.Entity;
import org.w3c.dom.EntityReference;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.Notation;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;
import org.w3c.dom.UserDataHandler;
import org.w3c.dom.traversal.DocumentTraversal;
import org.w3c.dom.traversal.NodeFilter;
import org.w3c.dom.traversal.NodeIterator;
import org.w3c.dom.traversal.TreeWalker;
import org.w3c.dom.xpath.XPathEvaluator;
import org.w3c.dom.xpath.XPathException;
import org.w3c.dom.xpath.XPathExpression;
import org.w3c.dom.xpath.XPathNSResolver;

/**
 * <p> "Document" and "DocumentTraversal" implementation.
 *
 * <p> Note that when this checks names for legality, it uses an
 * approximation of the XML rules, not the real ones.  Specifically,
 * it uses Unicode rules, with sufficient tweaks to pass a majority
 * of basic XML conformance tests.  (The huge XML character tables are
 * hairy to implement.)
 *
 * @author David Brownell 
 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
 */
public class DomDocument
  extends DomNode
  implements Document, DocumentTraversal, XPathEvaluator
{

  private final DOMImplementation implementation;
  private boolean checkingCharacters = true;
  boolean checkingWellformedness = true;

  boolean building; // if true, skip mutation events in the tree
  
  DomDocumentConfiguration config;

  String inputEncoding;
  String encoding;
  String version = "1.0";
  boolean standalone;
  String systemId;
  
  /**
   * Constructs a Document node, associating it with an instance
   * of the DomImpl class.
   *
   * <p> Note that this constructor disables character checking.
   * It is normally used when connecting a DOM to an XML parser,
   * and duplicating such checks is undesirable.  When used for
   * purposes other than connecting to a parser, you should
   * re-enable that checking.
   *
   * @see #setCheckingCharacters
   */
  public DomDocument()
  {
    this(new DomImpl());
  }
  
  /**
   * Constructs a Document node, associating it with the specified
   * implementation.  This should only be used in conjunction with
   * a specialized implementation; it will normally be called by
   * that implementation.
   *
   * @see DomImpl
   * @see #setCheckingCharacters
   */
  protected DomDocument(DOMImplementation impl)
  {
    super(DOCUMENT_NODE, null);
    implementation = impl;
  }

  /**
   * Sets the <code>building</code> flag.
   * Mutation events in the document are not reported.
   */
  public void setBuilding(boolean flag)
  {
    building = flag;
  }

  /**
   * Sets whether to check for document well-formedness.
   * If true, an exception will be raised if a second doctype or root
   * element node is added to the document.
   */
  public void setCheckWellformedness(boolean flag)
  {
    checkingWellformedness = flag;
  }

  /**
   * Sets whether to check for document characters.
   */
  public void setCheckingCharacters(boolean flag)
  {
    checkingCharacters = flag;
  }  
  
  /**
   * <b>DOM L1</b>
   * Returns the constant "#document".
   */
  final public String getNodeName()
  {
    return "#document";
  }

  /**
   * <b>DOM L1</b>
   * Returns the document's root element, or null.
   */
  final public Element getDocumentElement()
  {
    for (DomNode ctx = first; ctx != null; ctx = ctx.next)
      {
        if (ctx.nodeType == ELEMENT_NODE)
          {
            return (Element) ctx;
          }
      }
    return null;
  }

  /**
   * <b>DOM L1</b>
   * Returns the document's DocumentType, or null.
   */
  final public DocumentType getDoctype()
  {
    for (DomNode ctx = first; ctx != null; ctx = ctx.next)
      {
      if (ctx.nodeType == DOCUMENT_TYPE_NODE)
          {
            return (DocumentType) ctx;
          }
      }
    return null;
  }

  /**
   * <b>DOM L1</b>
   * Returns the document's DOMImplementation.
   */
  final public DOMImplementation getImplementation()
  {
    return implementation;
  }

  /**
   * <b>DOM L1 (relocated in DOM L2)</b>
   * Returns the element with the specified "ID" attribute, or null.
   *
   * <p>Returns null unless {@link Consumer} was used to populate internal
   * DTD declaration information, using package-private APIs.  If that
   * internal DTD information is available, the document may be searched for
   * the element with that ID.
   */
  public Element getElementById(String id)
  {
    if (id == null || id.length() == 0)
      {
        return null;
      }
    DomDoctype doctype = (DomDoctype) getDoctype();
    if (doctype != null && !doctype.hasIds())
      {
        doctype = null;
      }
    
    // yes, this is linear in size of document.
    // it'd be easy enough to maintain a hashtable.
    Node current = getDocumentElement();
    Node temp;
    
    if (current == null)
      {
        return null;
      }
    while (current != this)
      {
        // done?
        if (current.getNodeType() == ELEMENT_NODE)
          {
            DomElement element = (DomElement) current;
            if (element.userIdAttrs != null)
              {
                for (Iterator i = element.userIdAttrs.iterator();
                     i.hasNext(); )
                  {
                    Node idAttr = (Node) i.next();
                    if (id.equals(idAttr.getNodeValue()))
                      {
                        return element;
                      }
                  }
              }
            if (doctype != null)
              {
                DTDElementTypeInfo info =
                  doctype.getElementTypeInfo(current.getNodeName());
                if (info != null &&
                    id.equals(element.getAttribute(info.idAttrName)))
                  {
                    return element;
                  }
              }
            // xml:id
            String xmlId = element.getAttribute("xml:id");
            if (xmlId == null)
              {
                xmlId = element.getAttributeNS(XMLConstants.XML_NS_URI,
                                               "id");
              }
            if (id.equals(xmlId))
              {
                return element;
              }
          }
        
        // descend?
        if (current.hasChildNodes())
          {
            current = current.getFirstChild();
            continue;
          }
        
        // lateral?
        temp = current.getNextSibling();
        if (temp != null)
          {
            current = temp;
            continue;
          }
        
        // back up ... 
        do
          {
            temp = current.getParentNode();
            if (temp == null)
              {
                return null;
              }
            current = temp;
            temp = current.getNextSibling();
          }
        while (temp == null);
        current = temp;
      }
    return null;
  }

  private void checkNewChild(Node newChild)
  {
    if (newChild.getNodeType() == ELEMENT_NODE
        && getDocumentElement() != null)
      {
        throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR,
                                  "document element already present: " +
                                  getDocumentElement(), newChild, 0);
      }
    if (newChild.getNodeType() == DOCUMENT_TYPE_NODE
        && getDoctype() != null)
      {
        throw new DomDOMException(DOMException.HIERARCHY_REQUEST_ERR,
                                  "document type already present: " +
                                  getDoctype(), newChild, 0);
      }
  }

  /**
   * <b>DOM L1</b>
   * Appends the specified node to this node's list of children,
   * enforcing the constraints that there be only one root element
   * and one document type child.
   */
  public Node appendChild(Node newChild)
  {
    if (checkingWellformedness)
      {
        checkNewChild(newChild);
      }
    return super.appendChild(newChild);
  }

  /**
   * <b>DOM L1</b>
   * Inserts the specified node in this node's list of children,
   * enforcing the constraints that there be only one root element
   * and one document type child.
   */
  public Node insertBefore(Node newChild, Node refChild)
  {
    if (checkingWellformedness)
      {
        checkNewChild(newChild);
      }
    return super.insertBefore(newChild, refChild);
  }

  /**
   * <b>DOM L1</b>
   * Replaces the specified node in this node's list of children,
   * enforcing the constraints that there be only one root element
   * and one document type child.
   */
  public Node replaceChild(Node newChild, Node refChild)
  {
    if (checkingWellformedness &&
        ((newChild.getNodeType() == ELEMENT_NODE &&
          refChild.getNodeType() != ELEMENT_NODE) ||
         (newChild.getNodeType() == DOCUMENT_TYPE_NODE &&
          refChild.getNodeType() != DOCUMENT_TYPE_NODE)))
      {
        checkNewChild(newChild);
      }
    return super.replaceChild(newChild, refChild);
  }
 
  // NOTE:  DOM can't really tell when the name of an entity,
  // notation, or PI must follow the namespace rules (excluding
  // colons) instead of the XML rules (which allow them without
  // much restriction).  That's an API issue.  verifyXmlName
  // aims to enforce the XML rules, not the namespace rules.
  
  /**
   * Throws a DOM exception if the specified name is not a legal XML 1.0
   * Name.
   * @deprecated This method is deprecated and may be removed in future
   * versions of GNU JAXP
   */
  public static void verifyXmlName(String name)
  {
    // XXX why is this public?
    checkName(name, false);
  }

  static void checkName(String name, boolean xml11)
  {
    if (name == null)
      {
        throw new DomDOMException(DOMException.NAMESPACE_ERR, name, null, 0);
      }
    int len = name.length();
    if (len == 0)
      {
        throw new DomDOMException(DOMException.NAMESPACE_ERR, name, null, 0);
      }

    // dog: rewritten to use the rules for XML 1.0 and 1.1
    
    // Name start character
    char c = name.charAt(0);
    if (xml11)
      {
        // XML 1.1
        if ((c < 0x0041 || c > 0x005a) &&
            (c < 0x0061 || c > 0x007a) &&
            c != ':' && c != '_' &&
            (c < 0x00c0 || c > 0x00d6) &&
            (c < 0x00d8 || c > 0x00f6) &&
            (c < 0x00f8 || c > 0x02ff) &&
            (c < 0x0370 || c > 0x037d) &&
            (c < 0x037f || c > 0x1fff) &&
            (c < 0x200c || c > 0x200d) &&
            (c < 0x2070 || c > 0x218f) &&
            (c < 0x2c00 || c > 0x2fef) &&
            (c < 0x3001 || c > 0xd7ff) &&
            (c < 0xf900 || c > 0xfdcf) &&
            (c < 0xfdf0 || c > 0xfffd) &&
            (c < 0x10000 || c > 0xeffff))
          {
            throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
                                      name, null, c);
          }
      }
    else
      {
        // XML 1.0
        int type = Character.getType(c);
        switch (type)
          {
          case Character.LOWERCASE_LETTER: // Ll
          case Character.UPPERCASE_LETTER: // Lu
          case Character.OTHER_LETTER: // Lo
          case Character.TITLECASE_LETTER: // Lt
          case Character.LETTER_NUMBER: // Nl
            if ((c > 0xf900 && c < 0xfffe) ||
                (c >= 0x20dd && c <= 0x20e0))
              {
                // Compatibility area and Unicode 2.0 exclusions
                throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
                                          name, null, c);
              }
            break;
          default:
            if (c != ':' && c != '_' && (c < 0x02bb || c > 0x02c1) &&
                c != 0x0559 && c != 0x06e5 && c != 0x06e6)
              {
                throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
                                          name, null, c);
              }
          }
      }

    // Subsequent characters
    for (int i = 1; i < len; i++)
      {
        c = name.charAt(i);
        if (xml11)
          {
            // XML 1.1
            if ((c < 0x0041 || c > 0x005a) &&
                (c < 0x0061 || c > 0x007a) &&
                (c < 0x0030 || c > 0x0039) &&
                c != ':' && c != '_' && c != '-' && c != '.' &&
                (c < 0x00c0 || c > 0x00d6) &&
                (c < 0x00d8 || c > 0x00f6) &&
                (c < 0x00f8 || c > 0x02ff) &&
                (c < 0x0370 || c > 0x037d) &&
                (c < 0x037f || c > 0x1fff) &&
                (c < 0x200c || c > 0x200d) &&
                (c < 0x2070 || c > 0x218f) &&
                (c < 0x2c00 || c > 0x2fef) &&
                (c < 0x3001 || c > 0xd7ff) &&
                (c < 0xf900 || c > 0xfdcf) &&
                (c < 0xfdf0 || c > 0xfffd) &&
                (c < 0x10000 || c > 0xeffff) &&
                c != 0x00b7 &&
                (c < 0x0300 || c > 0x036f) &&
                (c < 0x203f || c > 0x2040))
              {
                throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR, name,
                                          null, c);
              }
          }
        else
          {
            // XML 1.0
            int type = Character.getType(c);
            switch (type)
              {
              case Character.LOWERCASE_LETTER: // Ll
              case Character.UPPERCASE_LETTER: // Lu
              case Character.DECIMAL_DIGIT_NUMBER: // Nd
              case Character.OTHER_LETTER: // Lo
              case Character.TITLECASE_LETTER: // Lt
              case Character.LETTER_NUMBER: // Nl
              case Character.COMBINING_SPACING_MARK: // Mc
              case Character.ENCLOSING_MARK: // Me
              case Character.NON_SPACING_MARK: // Mn
              case Character.MODIFIER_LETTER: // Lm
                if ((c > 0xf900 && c < 0xfffe) ||
                    (c >= 0x20dd && c <= 0x20e0))
                  {
                    // Compatibility area and Unicode 2.0 exclusions
                    throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
                                              name, null, c);
                  }
                break;
              default:
                if (c != '-' && c != '.' && c != ':' && c != '_' &&
                    c != 0x0387 && (c < 0x02bb || c > 0x02c1) &&
                    c != 0x0559 && c != 0x06e5 && c != 0x06e6 && c != 0x00b7)
                  {
                    throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
                                              name, null, c);
                  }
              }
          }
      }

    // FIXME characters with a font or compatibility decomposition (i.e.
    // those with a "compatibility formatting tag" in field 5 of the
    // database -- marked by field 5 beginning with a "<") are not allowed.
  }

  // package private
  static void checkNCName(String name, boolean xml11)
  {
    checkName(name, xml11);
    int len = name.length();
    int index = name.indexOf(':');
    if (index != -1)
      {
        if (index == 0 || index == (len - 1) || name.lastIndexOf(':') != index)
          {
            throw new DomDOMException(DOMException.NAMESPACE_ERR, name, null, 0);
          }
      }
  }

  // package private
  static void checkChar(String value, boolean xml11)
  {
    char[] chars = value.toCharArray();
    checkChar(chars, 0, chars.length, xml11);
  }
  
  static void checkChar(char[] buf, int off, int len, boolean xml11)
  {
    for (int i = 0; i < len; i++)
      {
        char c = buf[i];
        
        // assume surrogate pairing checks out OK, for simplicity
        if ((c >= 0x0020 && c <= 0xd7ff) ||
            (c == 0x000a || c == 0x000d || c == 0x0009) ||
            (c >= 0xe000 && c <= 0xfffd) ||
            (c >= 0x10000 && c <= 0x10ffff))
          {
            continue;
          }
        if (xml11)
          {
            if ((c >= 0x0001 && c <= 0x001f) ||
                (c >= 0x007f && c <= 0x0084) ||
                (c >= 0x0086 && c <= 0x009f))
              {
                continue;
              }
          }
        throw new DomDOMException(DOMException.INVALID_CHARACTER_ERR,
                                  new String(buf, off, len), null, c);
      }
  }

  /**
   * <b>DOM L1</b>
   * Returns a newly created element with the specified name.
   */
  public Element createElement(String name)
  {
    Element element;
    
    if (checkingCharacters)
      {
        checkName(name, "1.1".equals(version));
      }
    if (name.startsWith("xml:"))
      {
        element = createElementNS(null, name);
      }
    else
      {
        DomElement domElement = new DomElement(this, null, name);
        domElement.localName = null;
        element = domElement;
      }
    defaultAttributes(element, name);
    return element;
  }

  /**
   * <b>DOM L2</b>
   * Returns a newly created element with the specified name
   * and namespace information.
   */
  public Element createElementNS(String namespaceURI, String name)
  {
    if (checkingCharacters)
      {
        checkNCName(name, "1.1".equals(version));
      }
    
    if ("".equals(namespaceURI))
      {
        namespaceURI = null;
      }
    if (name.startsWith("xml:"))
      {
        if (namespaceURI != null
            && !XMLConstants.XML_NS_URI.equals(namespaceURI))
          {
            throw new DomDOMException(DOMException.NAMESPACE_ERR,
                                      "xml namespace is always " +
                                      XMLConstants.XML_NS_URI, this, 0);
          }
        namespaceURI = XMLConstants.XML_NS_URI;
      }
    else if (XMLConstants.XMLNS_ATTRIBUTE.equals(name) ||
             name.startsWith("xmlns:"))
      {
        throw new DomDOMException(DOMException.NAMESPACE_ERR,
                                  "xmlns is reserved", this, 0);
      }
    else if (namespaceURI == null && name.indexOf(':') != -1)
      {
        throw new DomDOMException(DOMException.NAMESPACE_ERR,
                                  "prefixed name '" + name +
                                  "' needs a URI", this, 0);
      }
    
    Element  element = new DomElement(this, namespaceURI, name);
    defaultAttributes(element, name);
    return element;
  }
  
  private void defaultAttributes(Element element, String name)
  {
    DomDoctype doctype = (DomDoctype) getDoctype();
    if (doctype == null)
      {
        return;
      }

    // default any attributes that need it
    DTDElementTypeInfo info = doctype.getElementTypeInfo(name);
    if (info != null)
      {
        for (Iterator i = info.attributes(); i != null && i.hasNext(); )
          {
            DTDAttributeTypeInfo attr = (DTDAttributeTypeInfo) i.next();
            DomAttr node = (DomAttr) createAttribute(attr.name);
            
            String value = attr.value;
            if (value == null)
              {
                value = "";
              }
            node.setValue(value);
            node.setSpecified(false);
            element.setAttributeNode(node);
          }
      }
  }

  /**
   * <b>DOM L1</b>
   * Returns a newly created document fragment.
   */
  public DocumentFragment createDocumentFragment()
  {
    return new DomDocumentFragment(this);
  }

  /**
   * <b>DOM L1</b>
   * Returns a newly created text node with the specified value.
   */
  public Text createTextNode(String value)
  {
    if (checkingCharacters)
      {
        checkChar(value, "1.1".equals(version));
      }
    return new DomText(this, value);
  }

  /**
   * Returns a newly created text node with the specified value.
   */
  public Text createTextNode(char[] buf, int off, int len)
  {
    if (checkingCharacters)
      {
        checkChar(buf, off, len, "1.1".equals(version));
      }
    return new DomText(this, buf, off, len);
  }

  /**
   * <b>DOM L1</b>
   * Returns a newly created comment node with the specified value.
   */
  public Comment createComment(String value)
  {
    if (checkingCharacters)
      {
        checkChar(value, "1.1".equals(version));
      }
    return new DomComment(this, value);
  }

  /**
   * <b>DOM L1</b>
   * Returns a newly created CDATA section node with the specified value.
   */
  public CDATASection createCDATASection(String value)
  {
    if (checkingCharacters)
      {
        checkChar(value, "1.1".equals(version));
      }
    return new DomCDATASection(this, value);
  }

  /**
   * Returns a newly created CDATA section node with the specified value.
   */
  public CDATASection createCDATASection(char[] buf, int off, int len)
  {
    if (checkingCharacters)
      {
        checkChar(buf, off, len, "1.1".equals(version));
      }
    return new DomCDATASection(this, buf, off, len);
  }

  /**
   * <b>DOM L1</b>
   * Returns a newly created processing instruction.
   */
  public ProcessingInstruction createProcessingInstruction(String target,
                                                           String data)
  {
    if (checkingCharacters)
      {
        boolean xml11 = "1.1".equals(version);
        checkName(target, xml11);
        if ("xml".equalsIgnoreCase(target))
          {
            throw new DomDOMException(DOMException.SYNTAX_ERR,
                                      "illegal PI target name",
                                      this, 0);
          }
        checkChar(data, xml11);
      }
    return new DomProcessingInstruction(this, target, data);
  }

  /**
   * <b>DOM L1</b>
   * Returns a newly created attribute with the specified name.
   */
  public Attr createAttribute(String name)
  {
    if (checkingCharacters)
      {
        checkName(name, "1.1".equals(version));
      }
    if (name.startsWith("xml:"))
      {
        return createAttributeNS(XMLConstants.XML_NS_URI, name);
      }
    else if (XMLConstants.XMLNS_ATTRIBUTE.equals(name) ||
             name.startsWith("xmlns:"))
      {
        return createAttributeNS(XMLConstants.XMLNS_ATTRIBUTE_NS_URI, name);
      }
    else
      {
        DomAttr ret = new DomAttr(this, null, name);
        ret.localName = null;
        return ret;
      }
  }

  /**
   * <b>DOM L2</b>
   * Returns a newly created attribute with the specified name
   * and namespace information.
   */
  public Attr createAttributeNS(String namespaceURI, String name)
  {
    if (checkingCharacters)
      {
        checkNCName(name, "1.1".equals(version));
      }
    
    if ("".equals(namespaceURI))
      {
        namespaceURI = null;
      }
    if (name.startsWith ("xml:"))
      {
        if (namespaceURI == null)
          {
            namespaceURI = XMLConstants.XML_NS_URI;
          }
        else if (!XMLConstants.XML_NS_URI.equals(namespaceURI))
          {
            throw new DomDOMException(DOMException.NAMESPACE_ERR,
                                      "xml namespace is always " +
                                      XMLConstants.XML_NS_URI,
                                      this, 0);
          }
      }
    else if (XMLConstants.XMLNS_ATTRIBUTE.equals(name) ||
             name.startsWith("xmlns:"))
      {
        if (namespaceURI == null)
          {
            namespaceURI = XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
          }
        else if (!XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI))
          {
            throw new DomDOMException(DOMException.NAMESPACE_ERR,
                                      "xmlns namespace must be " +
                                      XMLConstants.XMLNS_ATTRIBUTE_NS_URI,
                                      this, 0);
          }
      }
    else if (namespaceURI == null && name.indexOf(':') != -1)
      {
        throw new DomDOMException(DOMException.NAMESPACE_ERR,
                        "prefixed name needs a URI: " + name, this, 0);
      }
    return new DomAttr(this, namespaceURI, name);
  }
  
  /**
   * <b>DOM L1</b>
   * Returns a newly created reference to the specified entity.
   * The caller should populate this with the appropriate children
   * and then mark it as readonly.
   *
   * @see DomNode#makeReadonly
   */
  public EntityReference createEntityReference(String name)
  {
    DomEntityReference ret = new DomEntityReference(this, name);
    DocumentType doctype = getDoctype();
    if (doctype != null)
      {
        DomEntity ent = (DomEntity) doctype.getEntities().getNamedItem(name);
        if (ent != null)
          {
            for (DomNode ctx = ent.first; ctx != null; ctx = ctx.next)
              {
                ret.appendChild(ctx.cloneNode(true));
              }
          }
      }
    ret.makeReadonly();
    return ret;
  }

  /**
   * <b>DOM L2</b>
   * Makes a copy of the specified node, with all nodes "owned" by
   * this document and with children optionally copied.  This type
   * of standard utility has become, well, a standard utility.
   *
   * <p> Note that EntityReference nodes created through this method (either
   * directly, or recursively) never have children, and that there is no
   * portable way to associate them with such children.
   *
   * <p> Note also that there is no requirement that the specified node
   * be associated with a different document.  This differs from the
   * <em>cloneNode</em> operation in that the node itself is not given
   * an opportunity to participate, so that any information managed
   * by node subclasses will be lost.
   */
  public Node importNode(Node src, boolean deep)
  {
    Node dst = null;
    switch (src.getNodeType())
      {
      case TEXT_NODE:
        dst = createTextNode(src.getNodeValue());
        break;
      case CDATA_SECTION_NODE:
        dst = createCDATASection(src.getNodeValue());
        break;
      case COMMENT_NODE:
        dst = createComment(src.getNodeValue());
        break;
      case PROCESSING_INSTRUCTION_NODE:
        dst = createProcessingInstruction(src.getNodeName(),
                                          src.getNodeValue());
        break;
      case NOTATION_NODE:
        // NOTE:  There's no standard way to create
        // these, or add them to a doctype.  Useless.
        Notation notation = (Notation) src;
        dst = new DomNotation(this, notation.getNodeName(),
                              notation.getPublicId(),
                              notation.getSystemId());
        break;
      case ENTITY_NODE:
        // NOTE:  There's no standard way to create
        // these, or add them to a doctype.  Useless.
        Entity entity = (Entity) src;
        dst = new DomEntity(this, entity.getNodeName(),
                            entity.getPublicId(),
                            entity.getSystemId(),
                            entity.getNotationName());
        if (deep)
          {
            for (Node ctx = src.getFirstChild(); ctx != null;
                 ctx = ctx.getNextSibling())
              {
                dst.appendChild(importNode(ctx, deep));
              }
          }
        break;
      case ENTITY_REFERENCE_NODE:
        dst = createEntityReference(src.getNodeName());
        break;
      case DOCUMENT_FRAGMENT_NODE:
        dst = new DomDocumentFragment(this);
        if (deep)
          {
            for (Node ctx = src.getFirstChild(); ctx != null;
                 ctx = ctx.getNextSibling())
              {
                dst.appendChild(importNode(ctx, deep));
              }
          }
        break;
      case ATTRIBUTE_NODE:
        String attr_nsuri = src.getNamespaceURI();
        if (attr_nsuri != null)
          {
            dst = createAttributeNS(attr_nsuri, src.getNodeName());
          }
        else
          {
            dst = createAttribute(src.getNodeName());
          }
        // this is _always_ done regardless of "deep" setting
        for (Node ctx = src.getFirstChild(); ctx != null;
             ctx = ctx.getNextSibling())
          {
            dst.appendChild(importNode(ctx, false));
          }
        break;
      case ELEMENT_NODE:
        String elem_nsuri = src.getNamespaceURI();
        if (elem_nsuri != null)
          {
            dst = createElementNS(elem_nsuri, src.getNodeName());
          }
        else
          {
            dst = createElement(src.getNodeName());
          }
        NamedNodeMap srcAttrs = src.getAttributes();
        NamedNodeMap dstAttrs = dst.getAttributes();
        int len = srcAttrs.getLength();
        for (int i = 0; i < len; i++)
          {
            Attr a = (Attr) srcAttrs.item(i);
            Attr dflt;
            
            // maybe update defaulted attributes
            dflt = (Attr) dstAttrs.getNamedItem(a.getNodeName());
            if (dflt != null)
              {
                String newval = a.getNodeValue();
                if (!dflt.getNodeValue().equals(newval)
                    || a.getSpecified () == true)
                  {
                    dflt.setNodeValue (newval);
                  }
                continue;
              }
            
            dstAttrs.setNamedItem((Attr) importNode(a, false));
          }
        if (deep)
          {
            for (Node ctx = src.getFirstChild(); ctx != null;
                 ctx = ctx.getNextSibling())
              {
                dst.appendChild(importNode(ctx, true));
              }
          }
        break;
        // can't import document or doctype nodes
      case DOCUMENT_NODE:
      case DOCUMENT_TYPE_NODE:
        // FALLTHROUGH
        // can't import unrecognized or nonstandard nodes
      default:
        throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR, null, src, 0);
      }
    
    // FIXME cleanup a bit -- for deep copies, copy those
    // children in one place, here (code sharing is healthy)

    if (src instanceof DomNode)
      {
        ((DomNode) src).notifyUserDataHandlers(UserDataHandler.NODE_IMPORTED,
                                               src, dst);
      }
    return dst;
  }

  /**
   * <b>DOM L2 (Traversal)</b>
   * Returns a newly created node iterator.  Don't forget to detach
   * this iterator when you're done using it!
   *
   * @see DomIterator
   */
  public NodeIterator createNodeIterator(Node root,
                                         int whatToShow,
                                         NodeFilter filter,
                                         boolean expandEntities)
  {
    return new DomNodeIterator(root, whatToShow, filter, expandEntities,
                               false);
  }

  public TreeWalker createTreeWalker(Node root,
                                     int whatToShow,
                                     NodeFilter filter,
                                     boolean expandEntities)
  {
    return new DomNodeIterator(root, whatToShow, filter, expandEntities,
                               true);
  }

  // DOM Level 3 methods
  
  /**
   * DOM L3
   */
  public String getInputEncoding()
  {
    return inputEncoding;
  }

  public void setInputEncoding(String inputEncoding)
  {
    this.inputEncoding = inputEncoding;
  }
  
  /**
   * DOM L3
   */
  public String getXmlEncoding()
  {
    return encoding;
  }
  
  public void setXmlEncoding(String encoding)
  {
    this.encoding = encoding;
  }
  
  public boolean getXmlStandalone()
  {
    return standalone;
  }

  public void setXmlStandalone(boolean xmlStandalone)
  {
    standalone = xmlStandalone;
  }

  public String getXmlVersion()
  {
    return version;
  }

  public void setXmlVersion(String xmlVersion)
  {
    if (xmlVersion == null)
      {
        xmlVersion = "1.0";
      }
    if ("1.0".equals(xmlVersion) ||
        "1.1".equals(xmlVersion))
      {
        version = xmlVersion;
      }
    else
      {
        throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR);
      }
  }

  public boolean getStrictErrorChecking()
  {
    return checkingCharacters;
  }

  public void setStrictErrorChecking(boolean strictErrorChecking)
  {
    checkingCharacters = strictErrorChecking;
  }

  public String lookupPrefix(String namespaceURI)
  {
    Node root = getDocumentElement();
    return (root == null) ? null : root.lookupPrefix(namespaceURI);
  }

  public boolean isDefaultNamespace(String namespaceURI)
  {
    Node root = getDocumentElement();
    return (root == null) ? false : root.isDefaultNamespace(namespaceURI);
  }

  public String lookupNamespaceURI(String prefix)
  {
    Node root = getDocumentElement();
    return (root == null) ? null : root.lookupNamespaceURI(prefix);
  }

  public String getBaseURI()
  {
    return getDocumentURI();
    /*
    Node root = getDocumentElement();
    if (root != null)
      {
        NamedNodeMap attrs = root.getAttributes();
        Node xmlBase = attrs.getNamedItemNS(XMLConstants.XML_NS_URI, "base");
        if (xmlBase != null)
          {
            return xmlBase.getNodeValue();
          }
      }
    return systemId;
    */
  }
  
  public String getDocumentURI()
  {
    return systemId;
  }

  public void setDocumentURI(String documentURI)
  {
    systemId = documentURI;
  }

  public Node adoptNode(Node source)
  {
    int sourceNodeType = source.getNodeType();
    switch (sourceNodeType)
      {
      case DOCUMENT_NODE:
      case DOCUMENT_TYPE_NODE:
        throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR);
      case ENTITY_NODE:
      case NOTATION_NODE:
        throw new DomDOMException(DOMException.NO_MODIFICATION_ALLOWED_ERR);
      }
    if (source instanceof DomNode)
      {
        // GNU native
        DomNode src = (DomNode) source;
        DomNode dst = src;
        if (dst.parent != null)
          {
            dst = (DomNode) dst.cloneNode(true);
          }
        dst.setOwner(this);
        src.notifyUserDataHandlers(UserDataHandler.NODE_ADOPTED, src, dst);
        return dst;
      }
    else
      {
        // Some other implementation
        Node dst = null;
        switch (sourceNodeType)
          {
          case Node.ATTRIBUTE_NODE:
              {
                Attr src = (Attr) source;
                String nodeName = src.getNodeName();
                String localName = src.getLocalName();
                String namespaceUri = src.getNamespaceURI();
                dst = (localName == null) ?
                  createAttribute(nodeName) :
                  createAttributeNS(namespaceUri, nodeName);
                adoptChildren(src, dst);
                break;
              }
          case Node.CDATA_SECTION_NODE:
              {
                CDATASection src = (CDATASection) source;
                dst = createCDATASection(src.getData());
                break;
              }
          case Node.COMMENT_NODE:
              {
                Comment src = (Comment) source;
                dst = createComment(src.getData());
                break;
              }
          case Node.DOCUMENT_FRAGMENT_NODE:
              {
                DocumentFragment src = (DocumentFragment) source;
                dst = createDocumentFragment();
                adoptChildren(src, dst);
                break;
              }
          case Node.ELEMENT_NODE:
              {
                Element src = (Element) source;
                String nodeName = src.getNodeName();
                String localName = src.getLocalName();
                String namespaceUri = src.getNamespaceURI();
                dst = (localName == null) ?
                  createElement(nodeName) :
                  createElementNS(namespaceUri, nodeName);
                adoptAttributes(src, dst);
                adoptChildren(src, dst);
                break;
              }
          case Node.ENTITY_REFERENCE_NODE:
              {
                EntityReference src = (EntityReference) source;
                dst = createEntityReference(src.getNodeName());
                adoptChildren(src, dst);
                break;
              }
          case Node.PROCESSING_INSTRUCTION_NODE:
              {
                ProcessingInstruction src = (ProcessingInstruction) source;
                dst = createProcessingInstruction(src.getTarget(),
                                                  src.getData());
                break;
              }
          case Node.TEXT_NODE:
              {
                Text src = (Text) source;
                dst = createTextNode(src.getData());
                break;
              }
          }
        return dst;
      }
  }

  void adoptChildren(Node src, Node dst)
  {
    Node node = src.getFirstChild();
    while (node != null)
      {
        Node next = node.getNextSibling();
        dst.appendChild(adoptNode(node));
        node = next;
      }
  }

  void adoptAttributes(Node src, Node dst)
  {
    NamedNodeMap srcAttrs = src.getAttributes();
    NamedNodeMap dstAttrs = dst.getAttributes();
    int len = srcAttrs.getLength();
    for (int i = 0; i < len; i++)
      {
        Node node = srcAttrs.item(i);
        String localName = node.getLocalName();
        if (localName == null)
          {
            dstAttrs.setNamedItem(adoptNode(node));
          }
        else
          {
            dstAttrs.setNamedItemNS(adoptNode(node));
          }
      }
  }

  public DOMConfiguration getDomConfig()
  {
    if (config == null)
      {
        config = new DomDocumentConfiguration();
      }
    return config;
  }

  public boolean isEqualNode(Node arg)
  {
    if (!super.isEqualNode(arg))
      return false;
    Document d = (Document) arg;
    String dversion = d.getXmlVersion();
    if (dversion == null || !dversion.equals(version))
      return false;
    boolean dstandalone = d.getXmlStandalone();
    if (dstandalone != standalone)
      return false;
    String dencoding = d.getXmlEncoding();
    if (dencoding == null || dencoding.equalsIgnoreCase("UTF-8"))
      {
        if (encoding != null && !encoding.equalsIgnoreCase("UTF-8"))
          return false;
      }
    else
      {
        if (!dencoding.equals(encoding))
          return false;
      }
    return true;
  }

  public void normalizeDocument()
  {
    boolean save = building;
    building = true;
    normalizeNode(this);
    building = save;
  }

  void normalizeNode(DomNode node)
  {
    node.normalize();
    if (config != null)
      {
        switch (node.nodeType)
          {
          case CDATA_SECTION_NODE:
            if (!config.cdataSections)
              {
                // replace CDATA section with text node
                Text text = createTextNode(node.getNodeValue());
                node.parent.insertBefore(text, node);
                node.parent.removeChild(node);
                // merge adjacent text nodes
                String data = text.getWholeText();
                node = (DomNode) text.replaceWholeText(data);
              }
            else if (config.splitCdataSections)
              {
                String value = node.getNodeValue();
                int i = value.indexOf("]]>");
                while (i != -1)
                  {
                    Node node2 = createCDATASection(value.substring(0, i));
                    node.parent.insertBefore(node2, node);
                    value = value.substring(i + 3);
                    node.setNodeValue(value);
                    i = value.indexOf("]]>");
                  }
              }
            break;
          case COMMENT_NODE:
            if (!config.comments)
              {
                node.parent.removeChild(node);
              }
            break;
          case TEXT_NODE:
            if (!config.elementContentWhitespace &&
                ((Text) node).isElementContentWhitespace())
              {
                node.parent.removeChild(node);
              }
            break;
          case ENTITY_REFERENCE_NODE:
            if (!config.entities)
              {
                for (DomNode ctx = node.first; ctx != null; )
                  {
                    DomNode ctxNext = ctx.next;
                    node.parent.insertBefore(ctx, node);
                    ctx = ctxNext;
                  }
                node.parent.removeChild(node);
              }
            break;
          case ELEMENT_NODE:
            if (!config.namespaceDeclarations)
              {
                DomNamedNodeMap attrs =
                  (DomNamedNodeMap) node.getAttributes();
                boolean aro = attrs.readonly;
                attrs.readonly = false; // Ensure we can delete if necessary
                int len = attrs.getLength();
                for (int i = 0; i < len; i++)
                  {
                    Node attr = attrs.item(i);
                    String namespace = attr.getNamespaceURI();
                    if (XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespace))
                      {
                        attrs.removeNamedItemNS(namespace,
                                                attr.getLocalName());
                        i--;
                        len--;
                      }
                  }
                attrs.readonly = aro;
              }
            break;
          }
      }
    for (DomNode ctx = node.first; ctx != null; )
      {
        DomNode ctxNext = ctx.next;
        normalizeNode(ctx);
        ctx = ctxNext;
      }
  }
  
  public Node renameNode(Node n, String namespaceURI, String qualifiedName)
    throws DOMException
  {
    if (n instanceof DomNsNode)
      {
        DomNsNode src = (DomNsNode) n;
        if (src == null)
          {
            throw new DomDOMException(DOMException.NOT_FOUND_ERR);
          }
        if (src.owner != this)
          {
            throw new DomDOMException(DOMException.WRONG_DOCUMENT_ERR,
                                      null, src, 0);
          }
        boolean xml11 = "1.1".equals(version);
        checkName(qualifiedName, xml11);
        int ci = qualifiedName.indexOf(':');
        if ("".equals(namespaceURI))
          {
            namespaceURI = null;
          }
        if (namespaceURI != null)
          {
            checkNCName(qualifiedName, xml11);
            String prefix = (ci == -1) ? "" :
              qualifiedName.substring(0, ci);
            if (XMLConstants.XML_NS_PREFIX.equals(prefix) &&
                !XMLConstants.XML_NS_URI.equals(namespaceURI))
              {
                throw new DomDOMException(DOMException.NAMESPACE_ERR,
                                "xml namespace must be " +
                                XMLConstants.XML_NS_URI, src, 0);
              }
            else if (src.nodeType == ATTRIBUTE_NODE &&
                     (XMLConstants.XMLNS_ATTRIBUTE.equals(prefix) ||
                      XMLConstants.XMLNS_ATTRIBUTE.equals(qualifiedName)) &&
                     !XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI))
              {
                throw new DomDOMException(DOMException.NAMESPACE_ERR,
                                "xmlns namespace must be " +
                                XMLConstants.XMLNS_ATTRIBUTE_NS_URI, src, 0);
              }
            if (XMLConstants.XML_NS_URI.equals(namespaceURI) &&
                !XMLConstants.XML_NS_PREFIX.equals(prefix))
              {
                throw new DomDOMException(DOMException.NAMESPACE_ERR,
                                "xml namespace must be " +
                                XMLConstants.XML_NS_URI, src, 0);
              }
            else if (src.nodeType == ATTRIBUTE_NODE &&
                     XMLConstants.XMLNS_ATTRIBUTE_NS_URI.equals(namespaceURI) &&
                     !(XMLConstants.XMLNS_ATTRIBUTE.equals(prefix) ||
                       XMLConstants.XMLNS_ATTRIBUTE.equals(qualifiedName)))
              {
                throw new DomDOMException(DOMException.NAMESPACE_ERR,
                                "xmlns namespace must be " +
                                XMLConstants.XMLNS_ATTRIBUTE_NS_URI, src, 0);
              }
                
          }
        src.setNodeName(qualifiedName);
        src.setNamespaceURI(namespaceURI);
        src.notifyUserDataHandlers(UserDataHandler.NODE_RENAMED, src, src);
        // TODO MutationNameEvents
        // DOMElementNameChanged or DOMAttributeNameChanged
        return src;
      }
    throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR, null, n, 0);
  }

  // -- XPathEvaluator --
  
  public XPathExpression createExpression(String expression,
                                          XPathNSResolver resolver)
    throws XPathException, DOMException
  {
    return new DomXPathExpression(this, expression, resolver);
  }
  
  public XPathNSResolver createNSResolver(Node nodeResolver)
  {
    return new DomXPathNSResolver(nodeResolver);
  }
    
  public Object evaluate(String expression,
                         Node contextNode,
                         XPathNSResolver resolver,
                         short type,
                         Object result)
    throws XPathException, DOMException
  {
    XPathExpression xpe =
      new DomXPathExpression(this, expression, resolver);
    return xpe.evaluate(contextNode, type, result);
  }

}

