/* Consumer.java --
   Copyright (C) 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 org.w3c.dom.DocumentType;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.ext.Attributes2;

import gnu.xml.pipeline.DomConsumer;
import gnu.xml.pipeline.EventConsumer;


/**
 * Event consumer which constructs DOM documents using the implementation
 * in this package, using SAX2 events.  This packages various backdoors
 * into this DOM implementation, as needed to address DOM requirements
 * that can't be met by strictly conforming implementations of DOM.
 *
 * <p> These requirements all relate to {@link DocumentType} nodes and
 * features of that node type.  These features are normally not used,
 * because that interface only exposes a subset of the information found
 * in DTDs.  More, that subset does not include the most important typing
 * information.  For example, it excludes element content models and
 * attribute typing.  It does expose some entity management issues,
 * although entity management doesn't relate to document typing.
 *
 * <p> Note that SAX2 does not expose the literal text of the DTD's
 * internal subset, so it will not be present in DOM trees constructed
 * using this API.  (Though with a good SAX2 implementation, it could
 * be partially recreated...)
 *
 * @author David Brownell
 */
public class Consumer extends DomConsumer
{
    /**
     * Constructs an unconfigured event consumer,
     * as a terminus in a SAX event pipeline.
     */
    // used by PipelineFactory [terminus]
    public Consumer ()
    throws SAXException
    {
        super (DomDocument.class);
        setHandler (new Backdoor (this));
    }

    /**
     * Constructs an unconfigured event consumer,
     * as a stage in a SAX event pipeline.
     */
    // used by PipelineFactory [filter]
    public Consumer (EventConsumer next)
    throws SAXException
    {
        super (DomDocument.class, next);
        setHandler (new Backdoor (this));
    }

    /**
     * Implements the backdoors needed by DOM.
     * All methods in this class use implementation-specific APIs that are
     * implied by the DOM specification (needed to implement testable
     * behavior) but which are excluded from the DOM specification.
     */
    public static class Backdoor extends DomConsumer.Handler
    {
        /**
         * Constructor.
         * @param consumer must have been initialized to use the
         *      {@link DomDocument} class (or a subclass) for
         *      constructing DOM trees
         */
        protected Backdoor (DomConsumer consumer)
        throws SAXException
            { super (consumer); }

        // helper routine
        private DomDoctype getDoctype ()
        throws SAXException
        {
            DomDocument         doc = (DomDocument) getDocument ();
            DocumentType        dt = doc.getDoctype ();

            if (dt == null)
                throw new SAXException ("doctype missing!");
            return (DomDoctype) dt;
        }

        // SAX2 "lexical" event
        public void startDTD (String name, String publicId, String systemId)
        throws SAXException
        {
            DomDocument         doc = (DomDocument) getDocument ();

            super.startDTD (name, publicId, systemId);
            // DOM L2 doctype creation model is bizarre
            DomDoctype dt = new DomDoctype (doc, name, publicId, systemId);
            doc.appendChild (dt);
        }

        // SAX2 "lexical" event
        public void endDTD ()
        throws SAXException
        {
            super.endDTD ();
            // DOM L2 has no way to make things readonly
            getDoctype ().makeReadonly ();
        }

        // SAX1 DTD event
        public void notationDecl (
            String name,
            String publicId, String systemId
        ) throws SAXException
        {
            // DOM L2 can't create/save notation nodes
            getDoctype ().declareNotation (name, publicId, systemId);
        }

        // SAX1 DTD event
        public void unparsedEntityDecl (
            String name,
            String publicId, String systemId,
            String notationName
        ) throws SAXException
        {
            // DOM L2 can't create/save entity nodes
            getDoctype ().declareEntity (name, publicId, systemId,
                notationName);
        }

        // SAX2 declaration event
        public void internalEntityDecl (String name, String value)
        throws SAXException
        {
            // DOM L2 can't create/save entity nodes
            // NOTE:  this doesn't save the value as a child of this
            // node, though it could realistically do so.
            getDoctype ().declareEntity (name, null, null, null);
        }

        // SAX2 declaration event
        public void externalEntityDecl (
            String name,
            String publicId,
            String systemId
        ) throws SAXException
        {
            // DOM L2 can't create/save entity nodes
            // NOTE:  DOM allows for these to have children, if
            // they don't have unbound namespace references.
            getDoctype ().declareEntity (name, publicId, systemId, null);
        }

        // SAX2 element
        public void startElement (
            String uri,
            String localName,
            String qName,
            Attributes atts
        ) throws SAXException
        {
            Node                top;

            super.startElement (uri, localName, qName, atts);

            // might there be more work?
            top = getTop ();
            if (!top.hasAttributes () || !(atts instanceof Attributes2))
                return;

            // remember any attributes that got defaulted
            DomNamedNodeMap     map = (DomNamedNodeMap) top.getAttributes ();
            Attributes2         attrs = (Attributes2) atts;
            int                 length = atts.getLength ();

            //map.compact ();
            for (int i = 0; i < length; i++) {
                if (attrs.isSpecified (i))
                    continue;

                // value was defaulted.
                String          temp = attrs.getQName (i);
                DomAttr         attr;

                if ("".equals (temp))
                    attr = (DomAttr) map.getNamedItemNS (attrs.getURI (i),
                            atts.getLocalName (i));
                else
                    attr = (DomAttr) map.getNamedItem (temp);

                // DOM L2 can't write this flag, only read it
                attr.setSpecified (false);
            }
        }

        public void endElement (
            String uri,
            String localName,
            String qName
        ) throws SAXException
        {
            DomNode     top = (DomNode) getTop ();
            top.compact ();
            super.endElement (uri, localName, qName);
        }

        protected Text createText (
            boolean     isCDATA,
            char        buf [],
            int         off,
            int         len
        ) {
            DomDocument doc = (DomDocument) getDocument ();

            if (isCDATA)
                return doc.createCDATASection (buf, off, len);
            else
                return doc.createTextNode (buf, off, len);
        }

        public void elementDecl(String name, String model)
          throws SAXException
        {
          getDoctype().elementDecl(name, model);
        }

        public void attributeDecl (
            String      ename,
            String      aname,
            String      type,
            String      mode,
            String      value
        ) throws SAXException
        {
          getDoctype().attributeDecl(ename, aname, type, mode, value);
            /*
            if (value == null && !"ID".equals (type))
                return;

            DomDoctype.ElementInfo      info;

            info = getDoctype ().getElementInfo (ename);
            if (value != null)
                info.setAttrDefault (aname, value);
            if ("ID".equals (type))
                info.setIdAttr (aname);
                */

        }

        // force duplicate name checking off while we're
        // using parser output (don't duplicate the work)
        public void startDocument () throws SAXException
        {
            super.startDocument ();

            DomDocument doc = (DomDocument) getDocument ();
            doc.setStrictErrorChecking(false);
            doc.setBuilding(true);
        }

        public void endDocument ()
        throws SAXException
        {
            DomDocument doc = (DomDocument) getDocument ();
            doc.setStrictErrorChecking(true);
            doc.setBuilding(false);
            doc.compact ();
            DomDoctype doctype = (DomDoctype) doc.getDoctype();
            if (doctype != null)
              {
                doctype.makeReadonly();
              }
            super.endDocument ();
        }

        // these three methods collaborate to populate entity
        // refs, marking contents readonly on end-of-entity

        public boolean canPopulateEntityRefs ()
            { return true; }

        public void startEntity (String name)
        throws SAXException
        {
            if (name.charAt (0) == '%' || "[dtd]".equals (name))
                return;
            super.startEntity (name);

            DomNode     top = (DomNode) getTop ();

            if (top.getNodeType () == Node.ENTITY_REFERENCE_NODE)
                top.readonly = false;
        }

        public void endEntity (String name)
        throws SAXException
        {
            if (name.charAt (0) == '%' || "[dtd]".equals (name))
                return;
            DomNode     top = (DomNode) getTop ();

            if (top.getNodeType () == Node.ENTITY_REFERENCE_NODE) {
                top.compact ();
                top.makeReadonly ();
            }
            super.endEntity (name);
        }
    }
}
