/* DomConsumer.java -- 
   Copyright (C) 1999,2000,2001 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., 59 Temple Place, Suite 330, Boston, MA
02111-1307 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.pipeline;

import gnu.xml.aelfred2.ContentHandler2;
import gnu.xml.util.DomParser;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.ErrorHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXParseException;
import org.xml.sax.ext.DeclHandler;
import org.xml.sax.ext.LexicalHandler;
import org.xml.sax.helpers.AttributesImpl;
import org.w3c.dom.Attr;
import org.w3c.dom.CDATASection;
import org.w3c.dom.CharacterData;
import org.w3c.dom.Document;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Element;
import org.w3c.dom.EntityReference;
import org.w3c.dom.Node;
import org.w3c.dom.ProcessingInstruction;
import org.w3c.dom.Text;

/**
 * This consumer builds a DOM Document from its input, acting either as a
 * pipeline terminus or as an intermediate buffer.  When a document's worth
 * of events has been delivered to this consumer, that document is read with
 * a {@link DomParser} and sent to the next consumer.  It is also available
 * as a read-once property.
 *
 * <p>The DOM tree is constructed as faithfully as possible.  There are some
 * complications since a DOM should expose behaviors that can't be implemented
 * without API backdoors into that DOM, and because some SAX parsers don't
 * report all the information that DOM permits to be exposed.  The general
 * problem areas involve information from the Document Type Declaration (DTD).
 * DOM only represents a limited subset, but has some behaviors that depend
 * on much deeper knowledge of a document's DTD.  You shouldn't have much to
 * worry about unless you change handling of "noise" nodes from its default
 * setting (which ignores them all); note if you use JAXP to populate your
 * DOM trees, it wants to save "noise" nodes by default.  (Such nodes include
 * ignorable whitespace, comments, entity references and CDATA boundaries.)
 * Otherwise, your
 * main worry will be if you use a SAX parser that doesn't flag ignorable
 * whitespace unless it's validating (few don't).
 *
 * <p> The SAX2 events used as input must contain XML Names for elements
 * and attributes, with original prefixes.  In SAX2,
 * this is optional unless the "namespace-prefixes" parser feature is set.
 * Moreover, many application components won't provide completely correct
 * structures anyway.  <em>Before you convert a DOM to an output document,
 * you should plan to postprocess it to create or repair such namespace
 * information.</em> The {@link NSFilter} pipeline stage does such work.
 *
 * <p> <em>Note:  changes late in DOM L2 process made it impractical to
 * attempt to create the DocumentType node in any implementation-neutral way,
 * much less to populate it (L1 didn't support even creating such nodes).
 * To create and populate such a node, subclass the inner
 * {@link DomConsumer.Handler} class and teach it about the backdoors into
 * whatever DOM implementation you want.  It's possible that some revised
 * DOM API (L3?) will make this problem solvable again. </em>
 *
 * @see DomParser
 *
 * @author David Brownell
 */
public class DomConsumer implements EventConsumer
{
    private Class		domImpl;

    private boolean		hidingCDATA = true;
    private boolean		hidingComments = true;
    private boolean		hidingWhitespace = true;
    private boolean		hidingReferences = true;

    private Handler		handler;
    private ErrorHandler	errHandler;

    private EventConsumer	next;

    // FIXME:  this can't be a generic pipeline stage just now,
    // since its input became a Class not a String (to be turned
    // into a class, using the right class loader)


    /**
     * Configures this pipeline terminus to use the specified implementation
     * of DOM when constructing its result value.
     *
     * @param impl class implementing {@link org.w3c.dom.Document Document}
     *	which publicly exposes a default constructor
     *
     * @exception SAXException when there is a problem creating an
     *	empty DOM document using the specified implementation
     */
    public DomConsumer (Class impl)
    throws SAXException
    {
	domImpl = impl;
	handler = new Handler (this);
    }

    /**
     * This is the hook through which a subclass provides a handler
     * which knows how to access DOM extensions, specific to some
     * implementation, to record additional data in a DOM.
     * Treat this as part of construction; don't call it except
     * before (or between) parses.
     */
    protected void setHandler (Handler h)
    {
	handler = h;
    }


    private Document emptyDocument ()
    throws SAXException
    {
	try {
	    return (Document) domImpl.newInstance ();
	} catch (IllegalAccessException e) {
	    throw new SAXException ("can't access constructor: "
		    + e.getMessage ());
	} catch (InstantiationException e) {
	    throw new SAXException ("can't instantiate Document: "
		    + e.getMessage ());
	}
    }


    /**
     * Configures this consumer as a buffer/filter, using the specified
     * DOM implementation when constructing its result value.
     *
     * <p> This event consumer acts as a buffer and filter, in that it
     * builds a DOM tree and then writes it out when <em>endDocument</em>
     * is invoked.  Because of the limitations of DOM, much information
     * will as a rule not be seen in that replay.  To get a full fidelity
     * copy of the input event stream, use a {@link TeeConsumer}.
     *
     * @param impl class implementing {@link org.w3c.dom.Document Document}
     *	which publicly exposes a default constructor
     * @param next receives a "replayed" sequence of parse events when
     *	the <em>endDocument</em> method is invoked.
     *
     * @exception SAXException when there is a problem creating an
     *	empty DOM document using the specified DOM implementation
     */
    public DomConsumer (Class impl, EventConsumer n)
    throws SAXException
    {
	this (impl);
	next = n;
    }


    /**
     * Returns the document constructed from the preceding
     * sequence of events.  This method should not be
     * used again until another sequence of events has been
     * given to this EventConsumer.  
     */
    final public Document getDocument ()
    {
	return handler.clearDocument ();
    }

    public void setErrorHandler (ErrorHandler handler)
    {
	errHandler = handler;
    }


    /**
     * Returns true if the consumer is hiding entity references nodes
     * (the default), and false if EntityReference nodes should
     * instead be created.  Such EntityReference nodes will normally be
     * empty, unless an implementation arranges to populate them and then
     * turn them back into readonly objects.
     *
     * @see #setHidingReferences
     */
    final public boolean	isHidingReferences ()
	{ return hidingReferences; }

    /**
     * Controls whether the consumer will hide entity expansions,
     * or will instead mark them with entity reference nodes.
     *
     * @see #isHidingReferences
     * @param flag False if entity reference nodes will appear
     */
    final public void		setHidingReferences (boolean flag)
	{ hidingReferences = flag; }
    

    /**
     * Returns true if the consumer is hiding comments (the default),
     * and false if they should be placed into the output document.
     *
     * @see #setHidingComments
     */
    public final boolean isHidingComments ()
	{ return hidingComments; }

    /**
     * Controls whether the consumer is hiding comments.
     *
     * @see #isHidingComments
     */
    public final void setHidingComments (boolean flag)
	{ hidingComments = flag; }


    /**
     * Returns true if the consumer is hiding ignorable whitespace
     * (the default), and false if such whitespace should be placed
     * into the output document as children of element nodes.
     *
     * @see #setHidingWhitespace
     */
    public final boolean isHidingWhitespace ()
	{ return hidingWhitespace; }

    /**
     * Controls whether the consumer hides ignorable whitespace
     *
     * @see #isHidingComments
     */
    public final void setHidingWhitespace (boolean flag)
	{ hidingWhitespace = flag; }


    /**
     * Returns true if the consumer is saving CDATA boundaries, or
     * false (the default) otherwise.
     *
     * @see #setHidingCDATA
     */
    final public boolean	isHidingCDATA ()
	{ return hidingCDATA; }

    /**
     * Controls whether the consumer will save CDATA boundaries.
     *
     * @see #isHidingCDATA
     * @param flag True to treat CDATA text differently from other
     *	text nodes
     */
    final public void		setHidingCDATA (boolean flag)
	{ hidingCDATA = flag; }
    


    /** Returns the document handler being used. */
    final public ContentHandler getContentHandler ()
	{ return handler; }

    /** Returns the DTD handler being used. */
    final public DTDHandler getDTDHandler ()
	{ return handler; }

    /**
     * Returns the lexical handler being used.
     * (DOM construction can't really use declaration handlers.)
     */
    final public Object getProperty (String id)
    throws SAXNotRecognizedException
    {
	if ("http://xml.org/sax/properties/lexical-handler".equals (id))
	    return handler;
	if ("http://xml.org/sax/properties/declaration-handler".equals (id))
	    return handler;
	throw new SAXNotRecognizedException (id);
    }

    EventConsumer getNext () { return next; }

    ErrorHandler getErrorHandler () { return errHandler; }

    /**
     * Class used to intercept various parsing events and use them to
     * populate a DOM document.  Subclasses would typically know and use
     * backdoors into specific DOM implementations, used to implement 
     * DTD-related functionality.
     *
     * <p> Note that if this ever throws a DOMException (runtime exception)
     * that will indicate a bug in the DOM (e.g. doesn't support something
     * per specification) or the parser (e.g. emitted an illegal name, or
     * accepted illegal input data). </p>
     */
    public static class Handler
	implements ContentHandler2, LexicalHandler,
	    DTDHandler, DeclHandler
    {
	protected DomConsumer		consumer;

	private DOMImplementation	impl;
	private Document 		document;
	private boolean		isL2;

	private Locator		locator;
	private Node		top;
	private boolean		inCDATA;
	private boolean		mergeCDATA;
	private boolean		inDTD;
	private String		currentEntity;

	private boolean		recreatedAttrs;
	private AttributesImpl	attributes = new AttributesImpl ();

	/**
	 * Subclasses may use SAX2 events to provide additional
	 * behaviors in the resulting DOM.
	 */
	protected Handler (DomConsumer consumer)
	throws SAXException
	{
	    this.consumer = consumer;
	    document = consumer.emptyDocument ();
	    impl = document.getImplementation ();
	    isL2 = impl.hasFeature ("XML", "2.0");
	}

	private void fatal (String message, Exception x)
	throws SAXException
	{
	    SAXParseException	e;
	    ErrorHandler	errHandler = consumer.getErrorHandler ();;

	    if (locator == null)
		e = new SAXParseException (message, null, null, -1, -1, x);
	    else
		e = new SAXParseException (message, locator, x);
	    if (errHandler != null)
		errHandler.fatalError (e);
	    throw e;
	}

	/**
	 * Returns and forgets the document produced.  If the handler is
	 * reused, a new document may be created.
	 */
	Document clearDocument ()
	{
	    Document retval = document;
	    document = null;
	    locator = null;
	    return retval;
	}

	/**
	 * Returns the document under construction.
	 */
	protected Document getDocument ()
	    { return document; }
	
	/**
	 * Returns the current node being populated.  This is usually
	 * an Element or Document, but it might be an EntityReference
	 * node if some implementation-specific code knows how to put
	 * those into the result tree and later mark them as readonly.
	 */
	protected Node getTop ()
	    { return top; }


	// SAX1
	public void setDocumentLocator (Locator locator)
	{
	    this.locator = locator;
	}

	// SAX1
	public void startDocument ()
	throws SAXException
	{
	    if (document == null)
		try {
		    if (isL2) {
			// couple to original implementation
			document = impl.createDocument (null, "foo", null);
			document.removeChild (document.getFirstChild ());
		    } else {
			document = consumer.emptyDocument ();
		    }
		} catch (Exception e) {
		    fatal ("DOM create document", e);
		}
	    top = document;
	}

        // ContentHandler2
        public void xmlDecl(String version,
                            String encoding,
                            boolean standalone,
                            String inputEncoding)
          throws SAXException
        {
          if (document != null)
            {
              document.setXmlVersion(version);
              document.setXmlStandalone(standalone);
            }
        }

	// SAX1
	public void endDocument ()
	throws SAXException
	{
	    try {
		if (consumer.getNext () != null && document != null) {
		    DomParser	parser = new DomParser (document);

		    EventFilter.bind (parser, consumer.getNext ());
		    parser.parse ("ignored");
		}
	    } finally {
		top = null;
	    }
	}

	// SAX1
	public void processingInstruction (String target, String data)
	throws SAXException
	{
	    // we can't create populated entity ref nodes using
	    // only public DOM APIs (they've got to be readonly)
	    if (currentEntity != null)
		return;

	    ProcessingInstruction	pi;

	    if (isL2
		    // && consumer.isUsingNamespaces ()
		    && target.indexOf (':') != -1)
		namespaceError (
		    "PI target name is namespace nonconformant: "
			+ target);
	    if (inDTD)
		return;
	    pi = document.createProcessingInstruction (target, data);
	    top.appendChild (pi);
	}

	/**
	 * Subclasses may overrride this method to provide a more efficient
	 * way to construct text nodes.
	 * Typically, copying the text into a single character array will
	 * be more efficient than doing that as well as allocating other
	 * needed for a String, including an internal StringBuffer.
	 * Those additional memory and CPU costs can be incurred later,
	 * if ever needed.
	 * Unfortunately the standard DOM factory APIs encourage those costs
	 * to be incurred early.
	 */
	protected Text createText (
	    boolean	isCDATA,
	    char	ch [],
	    int		start,
	    int		length
	) {
	    String	value = new String (ch, start, length);

	    if (isCDATA)
		return document.createCDATASection (value);
	    else
		return document.createTextNode (value);
	}

	// SAX1
	public void characters (char ch [], int start, int length)
	throws SAXException
	{
	    // we can't create populated entity ref nodes using
	    // only public DOM APIs (they've got to be readonly
	    // at creation time)
	    if (currentEntity != null)
		return;

	    Node	lastChild = top.getLastChild ();

	    // merge consecutive text or CDATA nodes if appropriate.
	    if (lastChild instanceof Text) {
		if (consumer.isHidingCDATA ()
			// consecutive Text content ... always merge
			|| (!inCDATA
			    && !(lastChild instanceof CDATASection))
			// consecutive CDATASection content ... don't
			// merge between sections, only within them
			|| (inCDATA && mergeCDATA
			    && lastChild instanceof CDATASection)
			    ) {
		    CharacterData	last = (CharacterData) lastChild;
		    String		value = new String (ch, start, length);
		    
		    last.appendData (value);
		    return;
		}
	    }
	    if (inCDATA && !consumer.isHidingCDATA ()) {
		top.appendChild (createText (true, ch, start, length));
		mergeCDATA = true;
	    } else
		top.appendChild (createText (false, ch, start, length));
	}

	// SAX2
	public void skippedEntity (String name)
	throws SAXException
	{
	    // this callback is useless except to report errors, since
	    // we can't know if the ref was in content, within an
	    // attribute, within a declaration ... only one of those
	    // cases supports more intelligent action than a panic.
	    fatal ("skipped entity: " + name, null);
	}

	// SAX2
	public void startPrefixMapping (String prefix, String uri)
	throws SAXException
	{
	    // reconstruct "xmlns" attributes deleted by all
	    // SAX2 parsers without "namespace-prefixes" = true
	    if ("".equals (prefix))
		attributes.addAttribute ("", "", "xmlns",
			"CDATA", uri);
	    else
		attributes.addAttribute ("", "", "xmlns:" + prefix,
			"CDATA", uri);
	    recreatedAttrs = true;
	}

	// SAX2
	public void endPrefixMapping (String prefix)
	throws SAXException
	    { }

	// SAX2
	public void startElement (
	    String uri,
	    String localName,
	    String qName,
	    Attributes atts
	) throws SAXException
	{
	    // we can't create populated entity ref nodes using
	    // only public DOM APIs (they've got to be readonly)
	    if (currentEntity != null)
		return;

	    // parser discarded basic information; DOM tree isn't writable
	    // without massaging to assign prefixes to all nodes.
	    // the "NSFilter" class does that massaging.
	    if (qName.length () == 0)
		qName = localName;


	    Element	element;
	    int		length = atts.getLength ();

	    if (!isL2) {
		element = document.createElement (qName);

		// first the explicit attributes ...
		length = atts.getLength ();
		for (int i = 0; i < length; i++)
		    element.setAttribute (atts.getQName (i),
					    atts.getValue (i));
		// ... then any recreated ones (DOM deletes duplicates)
		if (recreatedAttrs) {
		    recreatedAttrs = false;
		    length = attributes.getLength ();
		    for (int i = 0; i < length; i++)
			element.setAttribute (attributes.getQName (i),
						attributes.getValue (i));
		    attributes.clear ();
		}

		top.appendChild (element);
		top = element;
		return;
	    }

	    // For an L2 DOM when namespace use is enabled, use
	    // createElementNS/createAttributeNS except when
	    // (a) it's an element in the default namespace, or
	    // (b) it's an attribute with no prefix
	    String	namespace;
	    
	    if (localName.length () != 0)
		namespace = (uri.length () == 0) ? null : uri;
	    else
		namespace = getNamespace (getPrefix (qName), atts);

	    if (namespace == null)
		element = document.createElement (qName);
	    else
		element = document.createElementNS (namespace, qName);

	    populateAttributes (element, atts);
	    if (recreatedAttrs) {
		recreatedAttrs = false;
		// ... DOM deletes any duplicates
		populateAttributes (element, attributes);
		attributes.clear ();
	    }

	    top.appendChild (element);
	    top = element;
	}

	final static String	xmlnsURI = "http://www.w3.org/2000/xmlns/";

	private void populateAttributes (Element element, Attributes attrs)
	throws SAXParseException
	{
	    int		length = attrs.getLength ();

	    for (int i = 0; i < length; i++) {
		String	type = attrs.getType (i);
		String	value = attrs.getValue (i);
		String	name = attrs.getQName (i);
		String	local = attrs.getLocalName (i);
		String	uri = attrs.getURI (i);

		// parser discarded basic information, DOM tree isn't writable
		if (name.length () == 0)
		    name = local;

		// all attribute types other than these three may not
		// contain scoped names... enumerated attributes get
		// reported as NMTOKEN, except for NOTATION values
		if (!("CDATA".equals (type)
			|| "NMTOKEN".equals (type)
			|| "NMTOKENS".equals (type))) {
		    if (value.indexOf (':') != -1) {
			namespaceError (
				"namespace nonconformant attribute value: "
				    + "<" + element.getNodeName ()
				    + " " + name + "='" + value + "' ...>");
		    }
		}

		// xmlns="" is legal (undoes default NS)
		// xmlns:foo="" is illegal
		String prefix = getPrefix (name);
		String namespace;

		if ("xmlns".equals (prefix)) {
		    if ("".equals (value))
			namespaceError ("illegal null namespace decl, " + name);
		    namespace = xmlnsURI;
		} else if ("xmlns".equals (name))
		    namespace = xmlnsURI;

		else if (prefix == null)
		    namespace = null;
		else if (!"".equals(uri) && uri.length () != 0)
		    namespace = uri;
		else
		    namespace = getNamespace (prefix, attrs);

		if (namespace == null)
		    element.setAttribute (name, value);
		else
		    element.setAttributeNS (namespace, name, value);
	    }
	}

	private String getPrefix (String name)
	{
	    int		temp;

	    if ((temp = name.indexOf (':')) > 0)
		return name.substring (0, temp);
	    return null;
	}

	// used with SAX1-level parser output 
	private String getNamespace (String prefix, Attributes attrs)
	throws SAXParseException
	{
	    String namespace;
	    String decl;

	    // defaulting 
	    if (prefix == null) {
		decl = "xmlns";
		namespace = attrs.getValue (decl);
		if ("".equals (namespace))
		    return null;
		else if (namespace != null)
		    return namespace;

	    // "xmlns" is like a keyword
	    // ... according to the Namespace REC, but DOM L2 CR2+
	    // and Infoset violate that by assigning a namespace.
	    // that conflict is resolved elsewhere.
	    } else if ("xmlns".equals (prefix))
		return null;

	    // "xml" prefix is fixed
	    else if ("xml".equals (prefix))
		return "http://www.w3.org/XML/1998/namespace";

	    // otherwise, expect a declaration
	    else {
		decl = "xmlns:" + prefix;
		namespace = attrs.getValue (decl);
	    }
	    
	    // if we found a local declaration, great
	    if (namespace != null)
		return namespace;


	    // ELSE ... search up the tree we've been building
	    for (Node n = top;
		    n != null && n.getNodeType () != Node.DOCUMENT_NODE;
		    n = (Node) n.getParentNode ()) {
		if (n.getNodeType () == Node.ENTITY_REFERENCE_NODE)
		    continue;
		Element e = (Element) n;
		Attr attr = e.getAttributeNode (decl);
		if (attr != null)
		    return attr.getNodeValue ();
	    }
	    // see above re "xmlns" as keyword
	    if ("xmlns".equals (decl))
		return null;

	    namespaceError ("Undeclared namespace prefix: " + prefix);
	    return null;
	}

	// SAX2
	public void endElement (String uri, String localName, String qName)
	throws SAXException
	{
	    // we can't create populated entity ref nodes using
	    // only public DOM APIs (they've got to be readonly)
	    if (currentEntity != null)
		return;

	    top = top.getParentNode ();
	}

	// SAX1 (mandatory reporting if validating)
	public void ignorableWhitespace (char ch [], int start, int length)
	throws SAXException
	{
	    if (consumer.isHidingWhitespace ())
		return;
	    characters (ch, start, length);
	}

	// SAX2 lexical event
	public void startCDATA ()
	throws SAXException
	{
	    inCDATA = true;
	    // true except for the first fragment of a cdata section
	    mergeCDATA = false;
	}
	
	// SAX2 lexical event
	public void endCDATA ()
	throws SAXException
	{
	    inCDATA = false;
	}
	
	// SAX2 lexical event
	//
	// this SAX2 callback merges two unrelated things:
	//	- Declaration of the root element type ... belongs with
	//    the other DTD declaration methods, NOT HERE.
	//	- IDs for the optional external subset ... belongs here
	//    with other lexical information.
	//
	// ...and it doesn't include the internal DTD subset, desired
	// both to support DOM L2 and to enable "pass through" processing
	//
	public void startDTD (String name, String publicId, String SystemId)
	throws SAXException
	{
	    // need to filter out comments and PIs within the DTD
	    inDTD = true;
	}
	
	// SAX2 lexical event
	public void endDTD ()
	throws SAXException
	{
	    inDTD = false;
	}
	
	// SAX2 lexical event
	public void comment (char ch [], int start, int length)
	throws SAXException
	{
	    Node	comment;

	    // we can't create populated entity ref nodes using
	    // only public DOM APIs (they've got to be readonly)
	    if (consumer.isHidingComments ()
		    || inDTD
		    || currentEntity != null)
		return;
	    comment = document.createComment (new String (ch, start, length));
	    top.appendChild (comment);
	}

	/**
	 * May be overridden by subclasses to return true, indicating
	 * that entity reference nodes can be populated and then made
	 * read-only.
	 */
	public boolean canPopulateEntityRefs ()
	    { return false; }

	// SAX2 lexical event
	public void startEntity (String name)
	throws SAXException
	{
	    // are we ignoring what would be contents of an
	    // entity ref, since we can't populate it?
	    if (currentEntity != null)
		return;

	    // Are we hiding all entity boundaries?
	    if (consumer.isHidingReferences ())
		return;

	    // SAX2 shows parameter entities; DOM hides them
	    if (name.charAt (0) == '%' || "[dtd]".equals (name))
		return;

	    // Since we can't create a populated entity ref node in any
	    // standard way, we create an unpopulated one.
	    EntityReference ref = document.createEntityReference (name);
	    top.appendChild (ref);
	    top = ref;

	    // ... allowing subclasses to populate them
	    if (!canPopulateEntityRefs ())
		currentEntity = name;
	}

	// SAX2 lexical event
	public void endEntity (String name)
	throws SAXException
	{
	    if (name.charAt (0) == '%' || "[dtd]".equals (name))
		return;
	    if (name.equals (currentEntity))
		currentEntity = null;
	    if (!consumer.isHidingReferences ())
		top = top.getParentNode ();
	}


	// SAX1 DTD event
	public void notationDecl (
	    String name,
	    String publicId, String SystemId
	) throws SAXException
	{
	    /* IGNORE -- no public DOM API lets us store these
	     * into the doctype node
	     */
	}

	// SAX1 DTD event
	public void unparsedEntityDecl (
	    String name,
	    String publicId, String SystemId,
	    String notationName
	) throws SAXException
	{
	    /* IGNORE -- no public DOM API lets us store these
	     * into the doctype node
	     */
	}

	// SAX2 declaration event
	public void elementDecl (String name, String model)
	throws SAXException
	{
	    /* IGNORE -- no content model support in DOM L2 */
	}

	// SAX2 declaration event
	public void attributeDecl (
	    String eName,
	    String aName,
	    String type,
	    String mode,
	    String value
	) throws SAXException
	{
	    /* IGNORE -- no attribute model support in DOM L2 */
	}

	// SAX2 declaration event
	public void internalEntityDecl (String name, String value)
	throws SAXException
	{
	    /* IGNORE -- no public DOM API lets us store these
	     * into the doctype node
	     */
	}

	// SAX2 declaration event
	public void externalEntityDecl (
	    String name,
	    String publicId,
	    String SystemId
	) throws SAXException
	{
	    /* IGNORE -- no public DOM API lets us store these
	     * into the doctype node
	     */
	}

	//
	// These really should offer the option of nonfatal handling,
	// like other validity errors, though that would cause major
	// chaos in the DOM data structures.  DOM is already spec'd
	// to treat many of these as fatal, so this is consistent.
	//
	private void namespaceError (String description)
	throws SAXParseException
	{
	    SAXParseException err;
	    
	    err = new SAXParseException (description, locator);
	    throw err;
	}
    }
}
