/*
 * $Id$
 *
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2000 The Apache Software Foundation.  All rights 
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer. 
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:  
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Crimson" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written 
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, Sun Microsystems, Inc., 
 * http://www.sun.com.  For more information on the Apache Software 
 * Foundation, please see <http://www.apache.org/>.
 */

package org.apache.xerces.tree;


import java.io.InputStream;
import java.io.OutputStreamWriter;
import java.io.OutputStream;
import java.io.Writer;
import java.io.IOException;

import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;

import org.w3c.dom.*;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;
import org.xml.sax.XMLReader;

import org.apache.xerces.parsers.SAXParser;
import org.apache.xerces.tree.Resolver;

import org.apache.xerces.tree.MessageCatalog;
import org.apache.xerces.tree.XmlNames;


/**
 * This class implements the DOM <em>Document</em> interface, and also
 * provides static factory methods to create document instances.  Instances
 * represent the top level of an XML 1.0 document, typically consisting
 * of processing instructions followed by one tree of XML data.  These
 * documents may be written out for transfer or storage using a variety
 * of text encodings.
 *
 * <P> The static factory methods do not offer any customization options.
 * in particular, they do not enforce XML Namespaces when parsing, do not
 * offer customizable element factories, and discard certain information
 * which is not intended to be significant to applications.  If your
 * application requires more sophisticated use of DOM, you may need
 * to use SAX directly with an <em>XmlDocumentBuilder</em>.
 *
 * <P> Instances are factories for their subsidiary nodes, but applications
 * may provide their own element factory to bind element tags to particular
 * DOM implementation classes (which must subclass ElementNode).  For
 * example, a factory may use a set of classes which support the HTML DOM
 * methods, or which support methods associated with XML vocabularies for
 * specialized problem domains as found within Internet Commerce systems.
 * For example, an element tag <code>&lt;PurchaseOrder&gt;</code>
 * could be mapped to a <code>com.startup.commerce.PurchaseOrder</code>
 * class.  The factory can also use XML Namespace information, if desired.
 *
 * <P> Since DOM requires nodes to be owned exclusively by one document,
 * they can't be moved from one document to another using DOM APIs.  This
 * class provides an <em>changeNodeOwner</em> functionality which may be
 * used to change the document associated with a node, and with any of its
 * children.
 *
 * <P> <em> Only the core DOM model is supported here, not the HTML support.
 * Such support basically adds a set of convenience element types, and so
 * can be implemented through element factories and document subclasses.</em>
 *
 * @see XmlDocumentBuilder
 *
 * @author David Brownell
 * @author Rajiv Mordani
 * @version $Revision$
 */
public class XmlDocument extends ParentNode
    implements DocumentEx, DOMImplementation
{
    // package private (with jdk 1.1 'javac' bug workaround)
    static /* final */ String		eol;

    static {
	String	temp;
	try { temp = System.getProperty ("line.separator", "\n"); }
	catch (SecurityException e) { temp = "\n"; }
	eol = temp;
    }

    static final MessageCatalog		catalog = new Catalog ();

    private Locale		locale = Locale.getDefault ();

    private String		systemId;
    private ElementFactory	factory;

    // package private
    int				mutationCount;
    boolean replaceRootElement;

    /** Constructs an empty document object. */
    public XmlDocument ()
    {
    }

    /**
     * Construct an XML document from the data at the specified URI,
     * optionally validating.  This uses validating parser if
     * validation is requested, otherwise uses non-validating
     * parser.  XML Namespace conformance is not tested when parsing.
     *
     * @param documentURI The URI (normally URL) of the document
     * @param doValidate If true, validity errors are treated as fatal
     *
     * @exception IOException as appropriate
     * @exception SAXException as appropriate
     * @exception SAXParseException (with line number information)
     *	for parsing errors
     * @exception IllegalStateException at least when the parser
     *	is configured incorrectly
     */
    public static XmlDocument createXmlDocument (
	String	documentURI,
	boolean	doValidate
    ) throws IOException, SAXException
    {
	return createXmlDocument (new InputSource (documentURI), doValidate);
    }


    /**
     * Construct an XML document from the data at the specified URI,
     * using the nonvalidating parser.  XML Namespace conformance
     * is not tested when parsing.
     *
     * @param documentURI The URI (normally URL) of the document
     *
     * @exception IOException as appropriate
     * @exception SAXException as appropriate
     * @exception SAXParseException (with line number information)
     *	for parsing errors
     * @exception IllegalStateException at least when the parser
     *	is configured incorrectly
     */
    public static XmlDocument createXmlDocument (String documentURI)
    throws IOException, SAXException
    {
	return createXmlDocument (new InputSource (documentURI), false);
    }


    /**
     * Construct an XML document from input stream, optionally validating.
     * This document must not require interpretation of relative URLs,
     * since the base URL is not known.  This uses the validating parser
     * if validation is requested, otherwise uses the non-validating
     * parser.  XML Namespace conformance is not tested when parsing.
     *
     * @param in Holds xml document
     * @param doValidate If true, validity errors are treated as fatal
     *
     * @exception IOException as appropriate
     * @exception SAXException as appropriate
     * @exception SAXParseException (with line number information)
     *	for parsing errors
     * @exception IllegalStateException at least when the parser
     *	is configured incorrectly
     */
    public static XmlDocument createXmlDocument (
	InputStream	in,
	boolean		doValidate
    ) throws IOException, SAXException
    {
	return createXmlDocument (new InputSource (in), doValidate);
    }


    /**
     * Construct an XML document from the data in the specified input
     * source, optionally validating.  This uses the validating parser
     * if validation is requested, otherwise uses the non-validating
     * parser.  XML Namespace conformance is not tested when parsing.
     *
     * @param in The input source of the document
     * @param doValidate If true, validity errors are treated as fatal
     *
     * @exception IOException as appropriate
     * @exception SAXException as appropriate
     * @exception SAXParseException (with line number information)
     *	for parsing errors
     * @exception IllegalStateException at least when the parser
     *	is configured incorrectly
     */
    public static XmlDocument createXmlDocument(InputSource in, 
    						boolean validate)
        throws IOException, SAXException
    {
        //XMLReader xmlReader = XMLReaderFactory.createXMLReader();

        XMLReader xmlReader = new SAXParser ();

        String namespaces = "http://xml.org/sax/features/namespaces";
        xmlReader.setFeature(namespaces, true);

        String nsPrefixes = "http://xml.org/sax/features/namespace-prefixes";
        xmlReader.setFeature(nsPrefixes, true);

        // Validation
	if (validate) {
        	xmlReader.setFeature(
			"http://xml.org/sax/features/validation", true);
  	}

        // XmlDocumentBuilder is a ContentHandler
        XmlDocumentBuilder builder = new XmlDocumentBuilder();
        builder.setDisableNamespaces(false);

        // The main ContentHandler
        xmlReader.setContentHandler(builder);
          
        // org.xml.sax.ext.LexicalHandler
        String lexHandler = "http://xml.org/sax/properties/lexical-handler";
        xmlReader.setProperty(lexHandler, builder);
//         Object prop = xmlReader.getProperty(lexHandler);
//         System.out.println("LexicalHandler=" + prop);

        // org.xml.sax.ext.DeclHandler
        String declHandler
            = "http://xml.org/sax/properties/declaration-handler";
        xmlReader.setProperty(declHandler, builder);
//         prop = xmlReader.getProperty(declHandler);
//         System.out.println("DeclHandler=" + prop);

        // DTDHandler
        xmlReader.setDTDHandler(builder);

	xmlReader.setEntityResolver (new Resolver ());

        // Parse the input
        xmlReader.parse(in);
	return builder.getDocument();
    }




    /*
     * Returns the top level document element.
     * This is a convenience function in the big picture;
     * use the DOM version instead, at least for now.
     */
    // package private
    ElementNode getDocument ()
    {
	// We ignore comments, PIs, whitespace, etc
	// and return the first (only!) element.
	for (int i = 0; true; i++) {
	    Node n = item (i);
	    if (n == null)
		return null;
	    if (n instanceof ElementNode)
		return (ElementNode) n;
	}
    }

    /**
     * Returns the locale to be used for diagnostic messages.
     */
    public Locale	getLocale ()
	{ return locale; }
    
    /**
     * Assigns the locale to be used for diagnostic messages.
     * Multi-language applications, such as web servers dealing with
     * clients from different locales, need the ability to interact
     * with clients in languages other than the server's default.
     * When an XmlDocument is created, its locale is the default
     * locale for the virtual machine.
     *
     * @see #chooseLocale
     */
    public void	setLocale (Locale locale)
    {
	if (locale == null)
	    locale = Locale.getDefault ();
	this.locale = locale;
    }

    /**
     * Chooses a client locale to use for diagnostics, using the first
     * language specified in the list that is supported by this DOM
     * implementation.  That locale is then automatically assigned using <a
     * href="#setLocale(java.util.Locale)">setLocale()</a>.  Such a list
     * could be provided by a variety of user preference mechanisms,
     * including the HTTP <em>Accept-Language</em> header field.
     *
     * @see org.apache.xerces.tree.MessageCatalog
     *
     * @param languages Array of language specifiers, ordered with the most
     *	preferable one at the front.  For example, "en-ca" then "fr-ca",
     *  followed by "zh_CN".  Both RFC 1766 and Java styles are supported.
     * @return The chosen locale, or null.
     */
    public Locale chooseLocale (String languages [])
    {
	Locale	l = catalog.chooseLocale (languages);

	if (l != null)
	    setLocale (l);
	return l;
    }

    
    /**
     * Writes the document in UTF-8 character encoding, as a well formed
     * XML construct.
     *
     * @param out stream on which the document will be written 
     */
    public void write (OutputStream out) throws IOException
    {
	Writer	writer = new OutputStreamWriter (out, "UTF8");
	write (writer, "UTF-8");
    }

    /**
     * Writes the document as a well formed XML construct.  If the
     * encoding can be determined from the writer, that is used in
     * the document's XML declaration.  The encoding name may first
     * be transformed from a Java-internal form to a standard one;
     * for example, Java's "UTF8" is the standard "UTF-8".
     *
     * <P> <em>Use of UTF-8 (or UTF-16) OutputStreamWriters is strongly
     * encouraged. </em>  All other encodings may lose critical data,
     * since the standard Java output writers substitute characters
     * such as the question mark for data which they can't encode in
     * the current output encoding.  The IETF and other organizations
     * strongly encourage the use of UTF-8; also, all XML processors
     * are guaranteed to support it.
     *
     * @see #write(java.io.Writer,java.lang.String)
     *
     * @param out stream on which the document will be written 
     */
    public void write (Writer out) throws IOException
    {
	String	encoding = null;

	if (out instanceof OutputStreamWriter)
	    encoding = java2std (((OutputStreamWriter)out).getEncoding ());
        write (out, encoding);
    }


    //
    // Try some of the common conversions from Java's internal names
    // (which must fit in class names) to standard ones understood by
    // most other code.  We use the IETF's preferred names; case is
    // supposed to be ignored, note.
    //
    // package private 
    static String java2std (String encodingName)
    {
	if (encodingName == null)
	    return null;

	//
	// ISO-8859-N is a common family of 8 bit encodings;
	// N=1 is the eight bit subset of UNICODE, and there
	// seem to be at least drafts for some N >10.
	//
	if (encodingName.startsWith ("ISO8859_"))	// JDK 1.2
	    return "ISO-8859-" + encodingName.substring (8);
	if (encodingName.startsWith ("8859_"))		// JDK 1.1
	    return "ISO-8859-" + encodingName.substring (5);

	// XXX seven bit encodings ISO-2022-* ...
	// XXX EBCDIC encodings ... 

	if ("ASCII7".equalsIgnoreCase (encodingName)
		|| "ASCII".equalsIgnoreCase (encodingName))
	    return "US-ASCII";
	
	//
	// All XML parsers _must_ support UTF-8 and UTF-16.
	// (UTF-16 ~= ISO-10646-UCS-2 plus surrogate pairs)
	//
	if ("UTF8".equalsIgnoreCase (encodingName))
	    return "UTF-8";
	if (encodingName.startsWith ("Unicode"))
	    return "UTF-16";
	
	//
	// Some common Japanese character sets.
	//
	if ("SJIS".equalsIgnoreCase (encodingName))
	    return "Shift_JIS";
	if ("JIS".equalsIgnoreCase (encodingName))
	    return "ISO-2022-JP";
	if ("EUCJIS".equalsIgnoreCase (encodingName))
	    return "EUC-JP";

	// else we can't really do anything
	return encodingName;
    }

    
    /**
     * Writes the document in the specified encoding, and listing
     * that encoding in the XML declaration.  The document will be
     * well formed XML; at this time, it will not additionally be
     * valid XML or standalone, since it includes no document type
     * declaration.
     *
     * <P> Note that the document will by default be "pretty printed".
     * Extra whitespace is added to indent children of elements according
     * to their level of nesting, unless those elements have (or inherit)
     * the <em>xml:space='preserve'</em> attribute value.  This space
     * will be removed if, when the document is read back with DOM, a
     * call to <em>ElementNode.normalize</em> is made.  To avoid this
     * pretty printing, use a write context configured to disable it,
     * or explicitly assign an <em>xml:space='preserve'</em> attribute to
     * the root node of your document.
     *
     * <P> Also, if a SAX parser was used to construct this tree, data
     * will have been discarded.  Most of that will be insignificant in
     * terms of a "logical" view of document data:  comments, whitespace
     * outside of the top level element, the exact content of the XML
     * directive, and entity references were expanded.  However, <em>if a
     * DOCTYPE declaration was provided, it was also discarded</em>.
     * Such declarations will often be logically significant, due to the
     * attribute value defaulting and normalization they can provide.
     *
     * <P> In general, DOM does not support "round tripping" data from
     * XML to DOM and back without losing data about physical structures
     * and DTD information.  "Logical structure" will be preserved.
     *
     * @see #setDoctype
     * @see #writeXml
     *
     * @param out the writer to use when writing the document
     * @param encoding the encoding name to use; this should be a
     *	standard encoding name registered with the IANA (like "UTF-8")
     *	not a Java-internal name (like "UTF8").
     */
    public void write (Writer out, String encoding)
    throws IOException
    {
	//
	// We put a pretty minimal declaration here, which is the
	// best we can do given SAX input and DOM.  For the moment
	// this precludes our generating "standalone" annotations.
	//
	out.write ("<?xml version=\"1.0\"");
	if (encoding != null) {
	    out.write (" encoding=\"");
	    out.write (encoding);
	    out.write ('\"');
	}
	out.write ("?>");
	out.write (eol);
	out.write (eol);

	writeChildrenXml (createWriteContext (out, 0));
	out.write (eol);
	out.flush ();
    }

    /**
     * Returns an XML write context set up not to pretty-print,
     * and which knows about the entities defined for this document.
     *
     * @param out stream on which the document will be written 
     */
    public XmlWriteContext createWriteContext (Writer out)
    {
	return new ExtWriteContext (out);
    }

    /**
     * Returns an XML write context which pretty-prints output starting
     * at a specified indent level, and which knows about the entities
     * defined for this document.
     *
     * @param out stream on which the document will be written 
     * @param level initial indent level for pretty-printing
     */
    public XmlWriteContext createWriteContext (Writer out, int level)
    {
	return new ExtWriteContext (out, level);
    }

    /**
     * Writes the document out using the specified context, using
     * an encoding name derived from the stream in the context where
     * that is possible.
     *
     * @see #createWriteContext(java.io.Writer)
     * @see #createWriteContext(java.io.Writer,int)
     *
     * @param context describes how to write the document
     */
    public void writeXml (XmlWriteContext context) throws IOException
    {
	Writer	out = context.getWriter ();
	String	encoding = null;

	//
	// XXX as above, it should be possible to be "told" this name
	// in order to use more standard names.  We can pretty print,
	// or we can use the right encoding name; not both!!
	//
	if (out instanceof OutputStreamWriter)
	    encoding = java2std (((OutputStreamWriter)out).getEncoding ());

	//
	// We put a pretty minimal declaration here, which is the
	// best we can do given SAX input and DOM.  For the moment
	// this precludes our generating "standalone" annotations.
	//
	out.write ("<?xml version=\"1.0\"");
	if (encoding != null) {
	    out.write (" encoding=\"");
	    out.write (encoding);
	    out.write ('\"');
	}
	out.write ("?>");
	out.write (eol);
	out.write (eol);

	writeChildrenXml (context);
    }

    /**
     * Writes all the child nodes of the document, following each one
     * with the end-of-line string in use in this environment.
     */
    public void writeChildrenXml (XmlWriteContext context) throws IOException
    {
	int	length = getLength ();
	Writer	out = context.getWriter ();

	if (length == 0)
	    return;
	for (int i = 0; i < length; i++) {
	    ((NodeBase)item (i)).writeXml (context);
	    out.write (eol);
	}
    }


    // package private -- overrides base class method
    void checkChildType (int type)
    throws DOMException
    {
	switch (type) {
	  case ELEMENT_NODE:
	  case PROCESSING_INSTRUCTION_NODE:
	  case COMMENT_NODE:
	  case DOCUMENT_TYPE_NODE:
	    return;
	  default:
	    throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);
	}
    }

    /**
     * Assigns the URI associated with the document, which is its
     * system ID.
     *
     * @param uri The document's system ID, as used when storing
     *	the document.
     */
    final public void setSystemId (String uri)
    {
	systemId = uri;
    }

    /**
     * Returns system ID associated with the document, or null if
     * this is unknown.
     *
     * <P> This URI should not be used when interpreting relative URIs,
     * since the document may be partially stored in external parsed
     * entities with different base URIs.  Instead, use methods in the
     * <em>XmlReadable</em> interface as the document is being parsed,
     * so that the correct base URI is available.
     */
    final public String getSystemId ()
    {
	return systemId;
    }


    // DOM support


    /**
     * DOM:  Appends the specified child node to the document.  Only one
     * element or document type node may be a child of a document.
     *
     * @param node the node to be appended.
     */
    public Node appendChild (Node n)
    throws DOMException
    {
	if (n instanceof Element && getDocument () != null)
	    throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);
	if (n instanceof DocumentType && getDoctype () != null)
	    throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);
	return super.appendChild (n);
    }

    /**
     * DOM:  Inserts the specified child node into the document.  Only one
     * element or document type node may be a child of a document.
     *
     * @param n the node to be inserted.
     * @param refNode the node before which this is to be inserted
     */
    public Node insertBefore (Node n, Node refNode)
    throws DOMException
    {
	if (!replaceRootElement && n instanceof Element && 
	    getDocument () != null)
	    throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);
	if (!replaceRootElement && n instanceof DocumentType 
	    && getDoctype () != null)
	    throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);
	return super.insertBefore (n, refNode);
    }

    /**
     * <b>DOM:</b>  Replaces the specified child with the new node,
     * returning the original child or throwing an exception.
     * The new child must belong to this particular document.
     *
     * @param newChild the new child to be inserted
     * @param refChild node which is to be replaced
     */
    public Node replaceChild (Node newChild, Node refChild)
    throws DOMException
    {
    	if (newChild instanceof DocumentFragment ) {
    	    int elemCount = 0;
	    int docCount = 0;
	    replaceRootElement = false;
	    ParentNode frag = (ParentNode) newChild;
	    Node temp;
	    int i = 0;
	    while ((temp = frag.item (i)) != null) {
                if (temp instanceof Element) 
    	            elemCount++;

                 else if (temp instanceof DocumentType)
	            docCount++;
		i++;
	    }
	    if (elemCount > 1 || docCount > 1)
	        throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);
	    else 
	        replaceRootElement = true;
	}
	return super.replaceChild (newChild, refChild);
    }


    /** DOM: Returns the DOCUMENT_NODE node type constant. */
    final public short getNodeType () { return DOCUMENT_NODE; }


    /** DOM: returns the document type (DTD) */
    final public DocumentType getDoctype ()
    {
	// We ignore comments, PIs, whitespace, etc
	// and return the first (only!) doctype.
	for (int i = 0; true; i++) {
	    Node n = item (i);
	    if (n == null)
		return null;
	    if (n instanceof DocumentType)
		return (DocumentType) n;
	}
    }

    // package private!!
    Doctype createDoctype (String name)
    {
	Doctype	retval = new Doctype (name);
	retval.setOwnerDocument (this);
	return retval;
    }

    /**
     * Establishes how the document prints its document type.  If a system
     * ID (URI) is provided, that is used in a SYSTEM (or PUBLIC, if a public
     * ID is also provided) declaration.  If an internal subset is provided,
     * that will be printed.  The root element in the DTD will be what the
     * document itself provides.
     *
     * @param dtdPublicId Holds a "public identifier" used to identify the
     *	last part of the external DTD subset that is read into the DTD.
     *	This may be omitted, and in any case is ignored unless a system
     *	ID is provided.
     * @param dtdSystemId Holds a "system identifier" (a URI) used to
     *	identify the last part of the external DTD subset that is read
     *	into the DTD.  This may be omitted, in which case the document
     *	type will contain at most an internal subset.  This URI should
     *	not be a relative URI unless the document will be accessed in a
     *	context from which that relative URI makes sense.
     * @param internalSubset Optional; this holds XML text which will
     *	be put into the internal subset.  This must be legal syntax,
     *	and it is not tested by this document.
     */
    public DocumentType setDoctype (
	String	dtdPublicId,
	String	dtdSystemId,
	String	internalSubset
    ) {
	Doctype	retval = (Doctype) getDoctype ();

	if (retval != null)
	    retval.setPrintInfo (dtdPublicId, dtdSystemId,
		    internalSubset);
	else {
	    retval = new Doctype (dtdPublicId, dtdSystemId,
		    internalSubset);
	    retval.setOwnerDocument (this);
	    insertBefore (retval, getFirstChild ());
	}
	return retval;
    }

    
    /** DOM: Returns the content root element. */
    public Element getDocumentElement ()
	{ return getDocument (); }

    /**
     * Assigns the element factory to be used by this document.
     *
     * @param factory the element factory to be used; if this is null,
     *	all elements will be implemented by <em>ElementNode</em>.
     */
    final public void setElementFactory (ElementFactory factory)
    {
	this.factory = factory;
    }

    /**
     * Returns the element factory to be used by this document.
     */
    final public ElementFactory getElementFactory ()
    {
	return factory;
    }


    /**
     * DOM:  Create a new element, associated with this document, with
     * no children, attributes, or parent, by calling createElementEx.
     *
     * @param tagName the tag of the element, used to determine what
     *	type element to create as well as what tag to assign the new node.
     * @exception IllegalArgumentException if a mapping is defined,
     *	but is invalid because the element can't be instantiated or
     *	does not subclass <em>ElementNode</em>.
     */
    final public Element createElement (String tagName)
    throws DOMException
    {
	return createElementEx (tagName);
    }

    /**
     * <b>DOM2:</b>
     * @since DOM Level 2
     * XXX Does not work with ElementFactory
     */
    public Element createElementNS(String namespaceURI, String qualifiedName)
        throws DOMException
    {
        ElementNode retval = new ElementNode(namespaceURI, qualifiedName);
	retval.setOwnerDocument(this);
        return retval;
    }

    /**
     * Create a new element, associated with this document, with no
     * children, attributes, or parent.  This uses the element factory,
     * or else directly constructs an ElementNode.
     *
     * @param tagName the tag of the element, used to determine what
     *	type element to create as well as what tag to assign the new node.
     * @exception IllegalArgumentException if a mapping is defined,
     *	but is invalid because the element can't be instantiated or
     *	does not subclass <em>ElementNode</em>.
     */
    final public ElementEx createElementEx (String tagName)
    throws DOMException
    {
        ElementNode			retval;
	
	if (!XmlNames.isName (tagName))
	    throw new DomEx (DomEx.INVALID_CHARACTER_ERR);

	if (factory != null)
	    retval = (ElementNode) factory.createElementEx (tagName);
	else 
	    retval = new ElementNode ();
        retval.setTag (tagName);
	retval.setOwnerDocument (this);
        return retval;
    }

    /**
     * Create a new element, associated with this document, with no
     * children, attributes, or parent.  This uses the element factory,
     * or else directly constructs an ElementNode.
     *
     * @param uri The namespace used to determine what type of element to
     *	create.  This is not stored with the element; the element must be
     *	inserted into a DOM tree in a location where namespace declarations
     *	cause its tag to be interpreted correctly.
     * @param tagName The tag of the element, which should not contain
     *	any namespace prefix.
     * @exception IllegalArgumentException When a mapping is defined,
     *	but is invalid because the element can't be instantiated or
     *	does not subclass <em>ElementNode</em>.
     */
    final public ElementEx createElementEx (String uri, String tagName)
    throws DOMException
    {
        ElementNode	retval;
	
	if (!XmlNames.isName (tagName))
	    throw new DomEx (DomEx.INVALID_CHARACTER_ERR);

	if (factory != null)
	    retval = (ElementNode) factory.createElementEx (uri, tagName);
	else 
	    retval = new ElementNode ();
        retval.setTag (tagName);
	retval.setOwnerDocument (this);
        return retval;
    }

    /**
     * DOM:  returns a Text node initialized with the given text.
     *
     * @param text The contents of the text node being created, which
     *	should never contain "<em>]]&gt;</em>".
     */
    public Text createTextNode (String text)
    {
        TextNode			retval;
	
	retval = new TextNode ();
	retval.setOwnerDocument (this);
	if (text != null)
	    retval.setText (text.toCharArray ());
	return retval;
    }

    /**
     * DOM:  Returns a CDATA section initialized with the given text.
     *
     * @param text the text which the CDATA section will hold, which
     *	should never contain "<em>]]&gt;</em>".
     */
    public CDATASection createCDATASection (String text)
    {
	CDataNode	retval = new CDataNode ();

	if (text != null)
	    retval.setText (text.toCharArray ());
	retval.setOwnerDocument (this);
	return retval;
    }

    // package private ... convenience rtn, reduced mallocation
    TextNode newText (char buf [], int offset, int len)
    throws SAXException
    {
	TextNode	retval = (TextNode) createTextNode (null);
	char		data [] = new char [len];

	System.arraycopy (buf, offset, data, 0, len);
	retval.setText (data);
        return retval;
    }
        

    /**
     * DOM:  Returns a Processing Instruction node for the specified
     * processing target, with the given instructions.
     *
     * @param target the target of the processing instruction
     * @param instructions the processing instruction, which should
     *	never contain "<em>?&gt;</em>".
     */
    public ProcessingInstruction createProcessingInstruction (
	String target,
	String instructions
    ) throws DOMException
    {
	if (!XmlNames.isName (target))
	    throw new DomEx (DomEx.INVALID_CHARACTER_ERR);

	PINode	retval = new PINode (target, instructions);
	retval.setOwnerDocument (this);
	return retval;
    }


    /**
     * DOM:  Returns a valueless attribute node with no default value.
     *
     * @param name the name of the attribute.
     */
    public Attr createAttribute (String name)
    throws DOMException
    {
	if (!XmlNames.isName (name))
	    throw new DomEx (DomEx.INVALID_CHARACTER_ERR);

	AttributeNode retval = new AttributeNode (name, null, true, null);
	retval.setOwnerDocument (this);
	return retval;
    }

    /**
     * <b>DOM2:</b>
     * @since DOM Level 2
     */
    public Attr createAttributeNS(String namespaceURI,
                                  String qualifiedName)
        throws DOMException
    {
        // XXX do some checking here

	AttributeNode retval = new AttributeNode(qualifiedName, null, true,
                                                 null);
	retval.setOwnerDocument(this);
	return retval;
    }

    /**
     * DOM:  creates a comment node.
     *
     * @param data The characters which will be in the comment.
     *	This should not include the "<em>--</em>" characters.
     */
    public Comment createComment (String data)
    {
	CommentNode retval = new CommentNode (data);
	retval.setOwnerDocument (this);
	return retval;
    }


    /** DOM:  returns null. */
    public Document getOwnerDoc ()
    {
	return null;
    }

    /**
     * DOM: Returns an object describing the features of the DOM implementation 
     * used by this document:  it supports the XML 1.0 feature set.
     */
    public DOMImplementation getImplementation ()
	{ return this; }

    /**
     * DOM:  Creates a new document fragment.
     */
    public DocumentFragment createDocumentFragment ()
    {
	DocFragNode	retval = new DocFragNode ();
	retval.setOwnerDocument (this);
	return retval;
    }


    /**
     * DOM:  Creates an entity reference to the named entity.
     * Note that the entity must already be defined in the document
     * type, and that the name must be a legal entity name.
     *
     * @param name the name of the the parsed entity
     */
    public EntityReference createEntityReference (String name)
    throws DOMException
    {
	if (!XmlNames.isName (name))
	    throw new DomEx (DomEx.INVALID_CHARACTER_ERR);

	EntityRefNode retval = new EntityRefNode (name);
	retval.setOwnerDocument (this);
	return retval;
    }


    /** DOM: Returns the string "#document". */
    final public String getNodeName () { return "#document"; }


    /**
     * DOM: Returns a copy of this document.
     *
     * <P> <em>Note:</em> At this time, any element factory or document
     * type associated with this document will not be cloned.
     *
     * @param deep if true, child nodes are also cloned.
     */
    public Node cloneNode (boolean deep)
    {
	XmlDocument	retval = new XmlDocument ();

	retval.systemId = systemId;
	// XXX clone the element factory ...

	if (deep) {
	    Node	node;

	    for (int i = 0; (node = item (i)) != null; i++) {
		if (node instanceof DocumentType) {
		    // XXX recreate
		    continue;
		}
		node = node.cloneNode (true);
		retval.changeNodeOwner (node);
		retval.appendChild (node);
	    }
	}

	return retval;
    }

    
    /**
     * Changes the "owner document" of the given node, and all child
     * and associated attribute nodes, to be this document.  If the
     * node has a parent, it is first removed from that parent.
     * 
     * @param node
     * @exception DOMException WRONG_DOCUMENT_ERROR when attempting
     *	to change the owner for some other DOM implementation<P>
     *	HIERARCHY_REQUEST_ERROR when the node is a document, document
     *	type, entity, or notation; or when it is an attribute associated
     *  with an element whose owner is not being (recursively) changed.
     */
    final public void changeNodeOwner (Node node)
    throws DOMException
    {
	TreeWalker	walker;
	NodeBase	n;

	if (node.getOwnerDocument () == this)
	    return;
	if (!(node instanceof NodeBase))
	    throw new DomEx (DomEx.WRONG_DOCUMENT_ERR);

	switch (node.getNodeType ()) {
	  // Documents _are_ owners; can't switch identities
	  case Node.DOCUMENT_NODE:

	  // Entities, Notations only live in doctypes ... we
	  // don't support changing their ownership at this time
	  case Node.ENTITY_NODE:
	  case Node.NOTATION_NODE:
	  case Node.DOCUMENT_TYPE_NODE:
	    throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);
	}

	//
	// If node is an attribute, its "scoped" by one element...
	// and if that scope hasn't been changed (i.e. if this isn't
	// a recursive call) we can't really fix anything!
	//
	if (node instanceof AttributeNode) {
	    AttributeNode	attr = (AttributeNode) node;
	    ElementNode		scope = attr.getNameScope ();

	    if (scope != null && scope.getOwnerDocument () != this)
		throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);
	}

	// unparent node if needed
	n = (NodeBase) node.getParentNode ();
	if (n != null)
	    n.removeChild (node);
	
	// change any children (including self)
	for (walker = new TreeWalker (node),
		    n = (NodeBase) walker.getCurrent ();
		n != null;
		n = (NodeBase) walker.getNext ()) {
	    n.setOwnerDocument (this);

	    // Elements have associated attributes, which must
	    // also have owners changed.
	    if (n instanceof ElementNode) {
		NamedNodeMap	list = n.getAttributes ();
		int		length = list.getLength ();
		for (int i = 0; i < length; i++)
		    changeNodeOwner (list.item (i));
	    }
	}
    }

    /**
     * Reports on features that this implementation supports.  Allows code to
     * be shared with NodeBase.supports().
     */
    static boolean hasFeature0(String feature, String version) {
	if (!"XML".equalsIgnoreCase(feature)) {
	    return false;
        }
        if (version.equalsIgnoreCase("2.0") || version.equalsIgnoreCase("1.0")
                || version == null) {
            return true;
        }
        return false;
    }

    /**
     * DOM: Reports on features that this document supports
     *
     * @param feature identifies a feature of this DOM implementation;
     *	case is ignored
     * @param version optionally identifies the version of the feature
     */
    public boolean hasFeature(String feature, String version) {
        return hasFeature0(feature, version);
    }

    /**
     * <b>DOM2:</b>
     * @since DOM Level 2
     */
    public DocumentType createDocumentType(String qualifiedName,
                                           String publicId,
                                           String systemId,
                                           String internalSubset)
    {
        return new Doctype(qualifiedName, publicId, systemId, internalSubset);
    }

    public DocumentType createDocumentType(String qualifiedName,
                                           String publicId,
                                           String systemId)
    {
        return createDocumentType (qualifiedName, publicId, systemId, null);
    }

    /**
     * <b>DOM2:</b>
     * @since DOM Level 2
     */
    public Document createDocument(String namespaceURI, 
                                   String qualifiedName, 
                                   DocumentType doctype)
        throws DOMException
    {
        // Create document and append DocumentType to it
        // Note: WRONG_DOCUMENT_ERR is checked by appendChild()
        Document doc = new XmlDocument();
        doc.appendChild(doctype);

        // Create document element and append it
        // Note: name exceptions are checked by createElementNS()
        Element docElement = doc.createElementNS(namespaceURI, qualifiedName);
        doc.appendChild(docElement);

        return doc;
    }

    /**
     * <b>DOM2:</b>
     * @since DOM Level 2
     */
    public Element getElementById(String elementId) {
        return getElementExById(elementId);
    }

    /**
     * Returns the element whose ID is given by the parameter; or null
     * if no such element exists.  This relies on elements to know the 
     * name of their ID attribute, as will be currently be true only if
     * the document has been parsed from XML text with a DTD using the
     * <em>XmlDocumentBuilder</em> class, or if it has been constructed
     * using specialized DOM implementation classes which know the name
     * of their ID attribute.  (XML allows only one ID attribute per
     * element, and different elements may use different names for their
     * ID attributes.)
     *
     * <P> This may be used to implement internal IDREF linkage, as well
     * as some kinds of <em>XPointer</em> linkage as used in current
     * drafts of <em>XLink</em>.
     *
     * @param id The value of the ID attribute which will be matched
     *	by any element which is returned. 
     */
    // Note:  HTML DOM has getElementById() with "Element" return type
    public ElementEx getElementExById (String id)
    {
	if (id == null)
	    throw new IllegalArgumentException (getMessage ("XD-000"));

	TreeWalker	w = new TreeWalker (this);
	ElementEx	element;

	while ((element = (ElementEx) w.getNextElement (null)) != null) {
	    String	idAttr = element.getIdAttributeName ();
	    String	value;

	    if (idAttr == null)
		continue;
	    value = element.getAttribute (idAttr);
	    if (value.equals (id))
		return element;
	}
	return null;
    }

    /**
     * @since DOM Level 2
     * XXX Fix to better conform to spec.  cloneNode() also needs to be fixed.
     */
    public Node importNode(Node importedNode, boolean deep)
        throws DOMException
    {
        Node retval = null;

        switch (importedNode.getNodeType()) {
        case DOCUMENT_NODE:
        case DOCUMENT_TYPE_NODE:
            throw new DomEx(DomEx.NOT_SUPPORTED_ERR);
        default:
            retval = importedNode.cloneNode(deep);
        }

        ((NodeBase)retval).setOwnerDocument(this);
        return retval;
    }


    //
    // Represent document fragments other than the document itself.
    // (This class is primarily motivated for use with editors.)
    //
    static final class DocFragNode extends ParentNode
	implements DocumentFragment
    {
	// package private -- overrides base class method
	void checkChildType (int type)
	throws DOMException
	{
	    switch (type) {
	      case ELEMENT_NODE:
	      case PROCESSING_INSTRUCTION_NODE:
	      case COMMENT_NODE:
	      case TEXT_NODE:
	      case CDATA_SECTION_NODE:
	      case ENTITY_REFERENCE_NODE:
		return;
	      default:
		throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);
	    }
	}

	public void writeXml (XmlWriteContext context) throws IOException
	{
	    this.writeChildrenXml (context);
	}

	public Node getParentNode ()
	    { return null; }
	
	public void setParentNode (Node p)
	    { if (p != null) throw new IllegalArgumentException (); }
	
	public short getNodeType ()
	    { return DOCUMENT_FRAGMENT_NODE; }
	
	public String getNodeName () { 
	    return ("#document-fragment");
	}
	
	public Node cloneNode (boolean deep)
	{
	    DocFragNode	retval = new DocFragNode ();
	    ((NodeBase)retval).setOwnerDocument 
	    			((XmlDocument)this.getOwnerDocument ());

	    if (deep) {
	        Node	node;

	        for (int i = 0; (node = item (i)) != null; i++) {
		    node = node.cloneNode (true);
		    retval.appendChild (node);
	        }
	    }
	    return retval;
	}
    }


    //
    // Represent entity references.
    //
    final static class EntityRefNode extends ParentNode
	implements EntityReference
    {
	private String	entity;

	EntityRefNode (String name)
	{
	    if (name == null)
		throw new IllegalArgumentException (getMessage ("XD-002"));
	    entity = name;
	}
	
	// package private -- overrides base class method
	void checkChildType (int type)
	throws DOMException
	{
	    switch (type) {
	      case ELEMENT_NODE:
	      case PROCESSING_INSTRUCTION_NODE:
	      case COMMENT_NODE:
	      case TEXT_NODE:
	      case CDATA_SECTION_NODE:
	      case ENTITY_REFERENCE_NODE:
		return;
	      default:
		throw new DomEx (DomEx.HIERARCHY_REQUEST_ERR);
	    }
	}
	public void writeXml (XmlWriteContext context)
	throws IOException
	{
	    if (!context.isEntityDeclared (entity))
		throw new IOException (getMessage ("XD-003", new Object[]
							{ entity }));

	    Writer out = context.getWriter ();

	    out.write ('&');
	    out.write (entity);
	    out.write (';');
	}

	public short getNodeType ()
	    { return ENTITY_REFERENCE_NODE; }
	
	public String getNodeName ()
	    { return entity; }
	
	public Node cloneNode (boolean deep) { 
	    EntityRefNode retval = new EntityRefNode (entity);
	    ((NodeBase)retval).setOwnerDocument((
	    			XmlDocument)this.getOwnerDocument ());
	    if (deep) {
	        Node	node;

	        for (int i = 0; (node = item (i)) != null; i++) {
		    node = node.cloneNode (true);
		    retval.appendChild (node);
	        }
		// XXX
		//throw new RuntimeException (getMessage ("XD-001"));
	    }
	    return retval;
       	}
    }

    class ExtWriteContext extends XmlWriteContext
    {
	ExtWriteContext (Writer out) { super (out); }
	ExtWriteContext (Writer out, int level) { super (out, level); }

	public boolean isEntityDeclared (String name)
	{
	    if (super.isEntityDeclared (name))
		return true;

	    DocumentType	doctype = getDoctype ();

	    if (doctype == null)
		return false;
	    else
		return doctype.getEntities ().getNamedItem (name) != null;
	}
    }

    static class Catalog extends MessageCatalog
    {
	Catalog () { super (Catalog.class); }
    }
}
