/* 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;
  private boolean defaultAttributes = 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;
  }

  /**
   * Sets whether to default attributes for new elements.
   */
  public void setDefaultAttributes(boolean flag)
  {
    defaultAttributes = 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.
   * The node name of the created element will be equal to {@code name}.
   * The namespace, prefix and local name will all be {@code null}.
   */
  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, null, null);
        element = domElement;
      }
    if (defaultAttributes)
      setDefaultAttributes(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);
    if (defaultAttributes)
      setDefaultAttributes(element, name);
    return element;
  }
  
  private void setDefaultAttributes(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();
            String value = attr.value;
            if ("#IMPLIED".equals(attr.mode) && value == null)
              continue;
            DomAttr node = (DomAttr) createAttribute(attr.name);
            
            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, null, 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);
  }

}

