/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 2001 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 "Xerces" 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, International
 * Business Machines, Inc., http://www.apache.org.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */

package org.apache.xerces.parsers;

import java.util.Hashtable;

import org.apache.xerces.impl.Constants;
import org.apache.xerces.util.SymbolTable;

import org.apache.xerces.xni.QName;
import org.apache.xerces.xni.XMLAttributes;
import org.apache.xerces.xni.XMLString;
import org.apache.xerces.xni.parser.XMLParserConfiguration;

import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.DocumentHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.Parser;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.DeclHandler;
import org.xml.sax.ext.LexicalHandler;

/**
 * This is the base class of all SAX parsers. It implements both the 
 * SAX1 and SAX2 parser functionality, while the actual pipeline is
 * defined in the parser configuration.
 *
 * @author Stubs generated by DesignDoc on Mon Sep 11 11:10:57 PDT 2000
 * @author Arnaud Le Hors, IBM
 * @author Andy Clark, IBM
 *
 * @version $Id$ 
 */
public abstract class AbstractSAXParser
    extends AbstractXMLDocumentParser
    implements Parser, XMLReader // SAX1, SAX2
    {

    //
    // Constants
    //

    // NOTE: The locator and symbol table properties are for internal
    //       use. -Ac

    /** Property identifier: locator. */
    protected static final String LOCATOR =
        Constants.XERCES_PROPERTY_PREFIX + Constants.LOCATOR_PROPERTY;

    /** Property identifier: symbol table. */
    protected static final String SYMBOL_TABLE =
        Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;

    //
    // Data
    //

    // parser handlers

    /** Content handler. */
    protected ContentHandler fContentHandler;

    /** Document handler. */
    protected DocumentHandler fDocumentHandler;

    /** DTD handler. */
    protected org.xml.sax.DTDHandler fDTDHandler;

    /** Decl handler. */
    protected DeclHandler fDeclHandler;

    /** Lexical handler. */
    protected LexicalHandler fLexicalHandler;

    // symbols
       
    /** Symbol: empty string (""). */
    private String fEmptySymbol;

    // state

    /** 
     * True if a parse is in progress. This state is needed because
     * some features/properties cannot be set while parsing (e.g.
     * validation and namespaces).
     */
    protected boolean fParseInProgress = false;

    //
    // Constructors
    //

    /** Default constructor. */
    protected AbstractSAXParser(XMLParserConfiguration config) {
        super(config);

    } // <init>(XMLParserConfiguration)

    //
    // XMLDocumentHandler methods
    //

    /**
     * The start of the document.
     *
     * @param systemId The system identifier of the entity if the entity
     *                 is external, null otherwise.
     * @param encoding The auto-detected IANA encoding name of the entity
     *                 stream. This value will be null in those situations
     *                 where the entity encoding is not auto-detected (e.g.
     *                 internal entities or a document entity that is
     *                 parsed from a java.io.Reader).
     *     
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void startDocument(String systemId, String encoding) 
        throws SAXException {

        // SAX1
        if (fDocumentHandler != null) {
            fDocumentHandler.startDocument();
        }

        // SAX2
        if (fContentHandler != null) {
            fContentHandler.startDocument();
        }

    } // startDocument(String,String)

    /**
     * Notifies of the presence of the DOCTYPE line in the document.
     * 
     * @param rootElement The name of the root element.
     * @param publicId    The public identifier if an external DTD or null
     *                    if the external DTD is specified using SYSTEM.
     * @param systemId    The system identifier if an external DTD, null
     *                    otherwise.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void doctypeDecl(String rootElement,
                            String publicId, String systemId)
        throws SAXException {
        fInDTD = true;

        // SAX2 extension
        if (fLexicalHandler != null) {
            fLexicalHandler.startDTD(rootElement, publicId, systemId);
        }

    } // doctypeDecl(String,String,String)

    /**
     * The start of a namespace prefix mapping. This method will only be
     * called when namespace processing is enabled.
     * 
     * @param prefix The namespace prefix.
     * @param uri    The URI bound to the prefix.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void startPrefixMapping(String prefix, String uri)
        throws SAXException {

        // SAX2
        if (fContentHandler != null) {
            fContentHandler.startPrefixMapping(prefix, uri);
        }

    } // startPrefixMapping(String prefix, String uri)

    /**
     * The start of an element. If the document specifies the start element
     * by using an empty tag, then the startElement method will immediately
     * be followed by the endElement method, with no intervening methods.
     * 
     * @param element    The name of the element.
     * @param attributes The element attributes.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void startElement(QName element, XMLAttributes attributes) 
        throws SAXException {

        // SAX1
        if (fDocumentHandler != null) {
            fDocumentHandler.startElement(element.rawname, attributes);
        }

        // SAX2
        if (fContentHandler != null) {
            String uri = element.uri != null ? element.uri : fEmptySymbol;
            fContentHandler.startElement(uri, element.localpart,
                                         element.rawname, attributes);
        }

    } // startElement(QName,XMLAttributes)

    /**
     * Character content.
     * 
     * @param text The content.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void characters(XMLString text) throws SAXException {

        if (fInDTD) {
            return;
        }

        // SAX1
        if (fDocumentHandler != null) {
            fDocumentHandler.characters(text.ch, text.offset, text.length);
        }

        // SAX2
        if (fContentHandler != null) {
            fContentHandler.characters(text.ch, text.offset, text.length);
        }

    } // characters(XMLString)

    /**
     * Ignorable whitespace. For this method to be called, the document
     * source must have some way of determining that the text containing
     * only whitespace characters should be considered ignorable. For
     * example, the validator can determine if a length of whitespace
     * characters in the document are ignorable based on the element
     * content model.
     * 
     * @param text The ignorable whitespace.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void ignorableWhitespace(XMLString text) 
        throws SAXException {

        // SAX1
        if (fDocumentHandler != null) {
            fDocumentHandler.ignorableWhitespace(text.ch, text.offset, text.length);
        }

        // SAX2
        if (fContentHandler != null) {
            fContentHandler.ignorableWhitespace(text.ch, text.offset, text.length);
        }

    } // ignorableWhitespace(XMLString)

    /**
     * The end of an element.
     * 
     * @param element The name of the element.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void endElement(QName element) throws SAXException {

        // SAX1
        if (fDocumentHandler != null) {
            fDocumentHandler.endElement(element.rawname);
        }

        // SAX2
        if (fContentHandler != null) {
            String uri = element.uri != null ? element.uri : fEmptySymbol;
            fContentHandler.endElement(uri, element.localpart,
                                       element.rawname);
        }

    } // endElement(QName)

    /**
     * The end of a namespace prefix mapping. This method will only be
     * called when namespace processing is enabled.
     * 
     * @param prefix The namespace prefix.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void endPrefixMapping(String prefix) throws SAXException {

        // SAX2
        if (fContentHandler != null) {
            fContentHandler.endPrefixMapping(prefix);
        }

    } // endPrefixMapping(String)

    /**
     * The end of the document.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void endDocument() throws SAXException {

        // SAX1
        if (fDocumentHandler != null) {
            fDocumentHandler.endDocument();
        }

        // SAX2
        if (fContentHandler != null) {
            fContentHandler.endDocument();
        }

    } // endDocument()

    //
    // XMLDocumentHandler and XMLDTDHandler methods
    //

    /**
     * This method notifies of the start of an entity. The DTD has the
     * pseudo-name of "[dtd]; parameter entity names start with '%'; and 
     * general entity names are just the entity name.
     * <p>
     * <strong>Note:</strong> Since the document is an entity, the handler
     * will be notified of the start of the document entity by calling the
     * startEntity method with the entity name "[xml]" <em>before</em> calling
     * the startDocument method. When exposing entity boundaries through the
     * SAX API, the document entity is never reported, however.
     * <p>
     * <strong>Note:</strong> Since the DTD is an entity, the handler
     * will be notified of the start of the DTD entity by calling the
     * startEntity method with the entity name "[dtd]" <em>before</em> calling
     * the startDTD method.
     * <p>
     * <strong>Note:</strong> This method is not called for entity references
     * appearing as part of attribute values.
     * 
     * @param name     The name of the entity.
     * @param publicId The public identifier of the entity if the entity
     *                 is external, null otherwise.
     * @param systemId The system identifier of the entity if the entity
     *                 is external, null otherwise.
     * @param encoding The auto-detected IANA encoding name of the entity
     *                 stream. This value will be null in those situations
     *                 where the entity encoding is not auto-detected (e.g.
     *                 internal parameter entities).
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void startEntity(String name, String publicId, String systemId,
                            String encoding) throws SAXException {
        if (fLexicalHandler != null) {
            fLexicalHandler.startEntity(name);
        }
    } // startEntity(String,String,String,String)

    /**
     * This method notifies the end of an entity. The DTD has the pseudo-name 
     * of "[dtd]; parameter entity names start with '%'; and general entity
     * names are just the entity name.
     * <p>
     * <strong>Note:</strong> Since the document is an entity, the handler
     * will be notified of the end of the document entity by calling the
     * endEntity method with the entity name "[xml]" <em>after</em> calling
     * the endDocument method. When exposing entity boundaries through the
     * SAX API, the document entity is never reported, however.
     * <p>
     * <strong>Note:</strong> Since the DTD is an entity, the handler
     * will be notified of the end of the DTD entity by calling the
     * endEntity method with the entity name "[dtd]" <em>after</em> calling
     * the endDTD method.
     * <p>
     * <strong>Note:</strong> This method is not called for entity references
     * appearing as part of attribute values.
     * 
     * @param name The name of the entity.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void endEntity(String name) throws SAXException {
        if (fLexicalHandler != null) {
            fLexicalHandler.endEntity(name);
        }
    } // endEntity(String)

    /**
     * A comment.
     * 
     * @param text The text in the comment.
     *
     * @throws SAXException Thrown by application to signal an error.
     */
    public void comment(XMLString text) throws SAXException {

        // SAX2 extension
        if (fLexicalHandler != null) {
            fLexicalHandler.comment(text.ch, 0, text.length);
        }

    } // comment(XMLString)

    /**
     * A processing instruction. Processing instructions consist of a
     * target name and, optionally, text data. The data is only meaningful
     * to the application.
     * <p>
     * Typically, a processing instruction's data will contain a series
     * of pseudo-attributes. These pseudo-attributes follow the form of
     * element attributes but are <strong>not</strong> parsed or presented
     * to the application as anything other than text. The application is
     * responsible for parsing the data.
     * 
     * @param target The target.
     * @param data   The data or null if none specified.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void processingInstruction(String target, XMLString data)
        throws SAXException {

        //
        // REVISIT - I keep running into SAX apps that expect
        //   null data to be an empty string, which is contrary
        //   to the comment for this method in the SAX API.
        //

        // SAX1
        if (fDocumentHandler != null) {
            fDocumentHandler.processingInstruction(target,
                                                   data.toString());
        }

        // SAX2
        if (fContentHandler != null) {
            fContentHandler.processingInstruction(target, data.toString());
        }

    } // processingInstruction(String,XMLString)

    //
    // XMLDTDHandler methods
    //

    /**
     * An element declaration.
     * 
     * @param name         The name of the element.
     * @param contentModel The element content model.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void elementDecl(String name, String contentModel) 
        throws SAXException {

        // SAX2 extension
        if (fDeclHandler != null) {
            fDeclHandler.elementDecl(name, contentModel);
        }

    } // elementDecl(String,String)

    /**
     * An attribute declaration.
     * 
     * @param elementName   The name of the element that this attribute
     *                      is associated with.
     * @param attributeName The name of the attribute.
     * @param type          The attribute type. This value will be one of
     *                      the following: "CDATA", "ENTITY", "ENTITIES",
     *                      "ENUMERATION", "ID", "IDREF", "IDREFS", 
     *                      "NMTOKEN", "NMTOKENS", or "NOTATION".
     * @param enumeration   If the type has the value "ENUMERATION" or
     *                      "NOTATION", this array holds the allowed attribute
     *                      values; otherwise, this array is null.
     * @param defaultType   The attribute default type. This value will be
     *                      one of the following: "#FIXED", "#IMPLIED",
     *                      "#REQUIRED", or null.
     * @param defaultValue  The attribute default value, or null if no
     *                      default value is specified.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void attributeDecl(String elementName, String attributeName, 
                              String type, String[] enumeration, 
                              String defaultType, XMLString defaultValue)
        throws SAXException {

        // SAX2 extension
        if (fDeclHandler != null) {
            if (type.equals("NOTATION")) {
                StringBuffer str = new StringBuffer();
                str.append(type);
                str.append(" (");
                for (int i = 0; i < enumeration.length; i++) {
                    str.append(enumeration[i]);
                    if (i < enumeration.length - 1) {
                        str.append('|');
                    }
                }
                str.append(')');
                type = str.toString();
            }
            String value = defaultValue.toString();
            fDeclHandler.attributeDecl(elementName, attributeName,
                                       type, defaultType, value);
        }

    } // attributeDecl(String,String,String,String[],String,XMLString)

    /**
     * An internal entity declaration.
     * 
     * @param name The name of the entity. Parameter entity names start with
     *             '%', whereas the name of a general entity is just the 
     *             entity name.
     * @param text The value of the entity.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void internalEntityDecl(String name, XMLString text)
        throws SAXException {

        // SAX2 extensions
        if (fDeclHandler != null) {
            fDeclHandler.internalEntityDecl(name, text.toString());
        }

    } // internalEntityDecl(String,XMLString)

    /**
     * An external entity declaration.
     * 
     * @param name     The name of the entity. Parameter entity names start
     *                 with '%', whereas the name of a general entity is just
     *                 the entity name.
     * @param publicId The public identifier of the entity or null if the
     *                 the entity was specified with SYSTEM.
     * @param systemId The system identifier of the entity.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void externalEntityDecl(String name, String publicId,
                                   String systemId) throws SAXException {

        // SAX2 extension
        if (fDeclHandler != null) {
            fDeclHandler.externalEntityDecl(name, publicId, systemId);
        }

    } // externalEntityDecl(String,String,String)

    /**
     * An unparsed entity declaration.
     * 
     * @param name     The name of the entity.
     * @param publicId The public identifier of the entity, or null if not
     *                 specified.
     * @param systemId The system identifier of the entity, or null if not
     *                 specified.
     * @param notation The name of the notation.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void unparsedEntityDecl(String name, String publicId,
                                   String systemId, String notation)
        throws SAXException {

        // SAX2 extension
        if (fDTDHandler != null) {
            fDTDHandler.unparsedEntityDecl(name, publicId,
                                           systemId, notation);
        }

    } // unparsedEntityDecl(String,String,String,String)

    /**
     * A notation declaration
     * 
     * @param name     The name of the notation.
     * @param publicId The public identifier of the notation, or null if not
     *                 specified.
     * @param systemId The system identifier of the notation, or null if not
     *                 specified.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void notationDecl(String name, String publicId, String systemId)
        throws SAXException {

        // SAX1 and SAX2
        if (fDTDHandler != null) {
            fDTDHandler.notationDecl(name, publicId, systemId);
        }

    } // notationDecl(String,String,String)

    /**
     * The end of the DTD.
     *
     * @throws SAXException Thrown by handler to signal an error.
     */
    public void endDTD() throws SAXException {
        fInDTD = false;

        // SAX2 extension
        if (fLexicalHandler != null) {
            fLexicalHandler.endDTD();
        }

    } // endDTD()

    //
    // Parser and XMLReader methods
    //

    /**
     * Allow an application to register a DTD event handler.
     * <p>
     * If the application does not register a DTD handler, all DTD
     * events reported by the SAX parser will be silently ignored.
     * <p>
     * Applications may register a new or different handler in the
     * middle of a parse, and the SAX parser must begin using the new
     * handler immediately.
     *
     * @param dtdHandler The DTD handler.
     *
     * @exception java.lang.NullPointerException If the handler 
     *            argument is null.
     *
     * @see #getDTDHandler
     */
    public void setDTDHandler(DTDHandler dtdHandler) {
        // REVISIT: SAX1 doesn't require a null pointer exception
        //          to be thrown but SAX2 does. [Q] How do we
        //          resolve this? Currently I'm erring on the side
        //          of SAX2. -Ac
        if (dtdHandler == null) {
            throw new NullPointerException();
        }
        fDTDHandler = dtdHandler;
    } // setDTDHandler(DTDHandler)

    //
    // Parser methods
    //

    /**
     * Allow an application to register a document event handler.
     * <p>
     * If the application does not register a document handler, all
     * document events reported by the SAX parser will be silently
     * ignored (this is the default behaviour implemented by
     * HandlerBase).
     * <p>
     * Applications may register a new or different handler in the
     * middle of a parse, and the SAX parser must begin using the new
     * handler immediately.
     *
     * @param documentHandler The document handler.
     */
    public void setDocumentHandler(DocumentHandler documentHandler) {
        fDocumentHandler = documentHandler;
        try {
            Locator locator = (Locator)fConfiguration.getProperty(LOCATOR);
            if (locator != null) {
                fDocumentHandler.setDocumentLocator(locator);
            }
        }
        catch (SAXException e) {
            // do nothing
        }
    } // setDocumentHandler(DocumentHandler)

    //
    // XMLReader methods
    //

    /**
     * Allow an application to register a content event handler.
     * <p>
     * If the application does not register a content handler, all
     * content events reported by the SAX parser will be silently
     * ignored.
     * <p>
     * Applications may register a new or different handler in the
     * middle of a parse, and the SAX parser must begin using the new
     * handler immediately.
     *
     * @param contentHandler The content handler.
     *
     * @exception java.lang.NullPointerException If the handler 
     *            argument is null.
     *
     * @see #getContentHandler
     */
    public void setContentHandler(ContentHandler contentHandler) {
        if (contentHandler == null) {
            throw new NullPointerException();
        }
        fContentHandler = contentHandler;
    } // setContentHandler(ContentHandler)

    /**
     * Return the current content handler.
     *
     * @return The current content handler, or null if none
     *         has been registered.
     *
     * @see #setContentHandler
     */
    public ContentHandler getContentHandler() {
        return fContentHandler;
    } // getContentHandler():ContentHandler

    /**
     * Return the current DTD handler.
     *
     * @return The current DTD handler, or null if none
     *         has been registered.
     * @see #setDTDHandler
     */
    public DTDHandler getDTDHandler() {
        return fDTDHandler;
    } // getDTDHandler():DTDHandler

    /**
     * Set the state of any feature in a SAX2 parser.  The parser
     * might not recognize the feature, and if it does recognize
     * it, it might not be able to fulfill the request.
     *
     * @param featureId The unique identifier (URI) of the feature.
     * @param state The requested state of the feature (true or false).
     *
     * @exception SAXNotRecognizedException If the
     *            requested feature is not known.
     * @exception SAXNotSupportedException If the
     *            requested feature is known, but the requested
     *            state is not supported.
     */
    public void setFeature(String featureId, boolean state)
        throws SAXNotRecognizedException, SAXNotSupportedException {

        //
        // SAX2 Features
        //

        if (featureId.startsWith(Constants.SAX_FEATURE_PREFIX)) {
            String feature = featureId.substring(Constants.SAX_FEATURE_PREFIX.length());

            // http://xml.org/sax/features/namespace-prefixes
            //   controls the reporting of raw prefixed names and Namespace 
            //   declarations (xmlns* attributes): when this feature is false 
            //   (the default), raw prefixed names may optionally be reported, 
            //   and xmlns* attributes must not be reported.
            //
            if (feature.equals(Constants.NAMESPACE_PREFIXES_FEATURE)) {
                fConfiguration.setFeature(featureId, state);
                return;
            }
            // http://xml.org/sax/features/string-interning
            //   controls the use of java.lang.String#intern() for strings
            //   passed to SAX handlers.
            //
            if (feature.equals(Constants.STRING_INTERNING_FEATURE)) {
                if (state) {
                    // REVISIT: Localize this error message. -Ac
                    throw new SAXNotSupportedException(
                        "PAR018 " + state + " state for feature \"" + featureId
                        + "\" is not supported.\n" + state + '\t' + featureId);
                }
                return;
            }
   
            //
            // Drop through and perform default processing
            //
        }

        //
        // Xerces Features
        //

        /*
        else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) {
            String feature = featureId.substring(XERCES_FEATURES_PREFIX.length());
            //
            // Drop through and perform default processing
            //
        }
        */

        //
        // Perform default processing
        //

        super.setFeature(featureId, state);

    } // setFeature(String,boolean)

    /**
     * Query the state of a feature.
     *
     * Query the current state of any feature in a SAX2 parser.  The
     * parser might not recognize the feature.
     *
     * @param featureId The unique identifier (URI) of the feature
     *                  being set.
     * @return The current state of the feature.
     * @exception org.xml.sax.SAXNotRecognizedException If the
     *            requested feature is not known.
     * @exception SAXNotSupportedException If the
     *            requested feature is known but not supported.
     */
    public boolean getFeature(String featureId)
        throws SAXNotRecognizedException, SAXNotSupportedException {

        //
        // SAX2 Features
        //

        if (featureId.startsWith(Constants.SAX_FEATURE_PREFIX)) {
            String feature =
                featureId.substring(Constants.SAX_FEATURE_PREFIX.length());

            // http://xml.org/sax/features/namespace-prefixes
            //   controls the reporting of raw prefixed names and Namespace 
            //   declarations (xmlns* attributes): when this feature is false 
            //   (the default), raw prefixed names may optionally be reported, 
            //   and xmlns* attributes must not be reported.
            //
            if (feature.equals(Constants.NAMESPACE_PREFIXES_FEATURE)) {
                boolean state = fConfiguration.getFeature(featureId);
                return state;
            }
            // http://xml.org/sax/features/string-interning
            //   controls the use of java.lang.String#intern() for strings
            //   passed to SAX handlers.
            //
            if (feature.equals(Constants.STRING_INTERNING_FEATURE)) {
                return false;
            }

            //
            // Drop through and perform default processing
            //
        }

        //
        // Xerces Features
        //

        /*
        else if (featureId.startsWith(XERCES_FEATURES_PREFIX)) {
            //
            // Drop through and perform default processing
            //
        }
        */

        //
        // Perform default processing
        //

        return super.getFeature(featureId);

    } // getFeature(String):boolean

    /**
     * Set the value of any property in a SAX2 parser.  The parser
     * might not recognize the property, and if it does recognize
     * it, it might not support the requested value.
     *
     * @param propertyId The unique identifier (URI) of the property
     *                   being set.
     * @param Object The value to which the property is being set.
     *
     * @exception SAXNotRecognizedException If the
     *            requested property is not known.
     * @exception SAXNotSupportedException If the
     *            requested property is known, but the requested
     *            value is not supported.
     */
    public void setProperty(String propertyId, Object value)
        throws SAXNotRecognizedException, SAXNotSupportedException {

        //
        // SAX2 core properties
        //

        if (propertyId.startsWith(Constants.SAX_PROPERTY_PREFIX)) {
            String property =
                propertyId.substring(Constants.SAX_PROPERTY_PREFIX.length());
            //
            // http://xml.org/sax/properties/lexical-handler
            // Value type: org.xml.sax.ext.LexicalHandler
            // Access: read/write, pre-parse only
            //   Set the lexical event handler.
            //
            if (property.equals(Constants.LEXICAL_HANDLER_PROPERTY)) {
                try {
                    setLexicalHandler((LexicalHandler)value);
                }
                catch (ClassCastException e) {
                    // REVISIT: Localize this error message. -ac
                    throw new SAXNotSupportedException(
                    "PAR012 For propertyID \""
                    +propertyId+"\", the value \""
                    +value+"\" cannot be cast to LexicalHandler."
                    +'\n'+propertyId+'\t'+value+"\tLexicalHandler");
                }
                return;
            }
            //
            // http://xml.org/sax/properties/declaration-handler
            // Value type: org.xml.sax.ext.DeclHandler
            // Access: read/write, pre-parse only
            //   Set the DTD declaration event handler.
            //
            if (property.equals(Constants.DECLARATION_HANDLER_PROPERTY)) {
                try {
                    setDeclHandler((DeclHandler)value);
                }
                catch (ClassCastException e) {
                    // REVISIT: Localize this error message. -ac
                    throw new SAXNotSupportedException(
                    "PAR012 For propertyID \""
                    +propertyId+"\", the value \""
                    +value+"\" cannot be cast to DeclHandler."
                    +'\n'+propertyId+'\t'+value+"\tDeclHandler"
                    );
                }
                return;
            }
            //
            // http://xml.org/sax/properties/dom-node
            // Value type: DOM Node
            // Access: read-only
            //   Get the DOM node currently being visited, if the SAX parser is
            //   iterating over a DOM tree.  If the parser recognises and
            //   supports this property but is not currently visiting a DOM
            //   node, it should return null (this is a good way to check for
            //   availability before the parse begins).
            //
            if (property.equals(Constants.DOM_NODE_PROPERTY)) {
                // REVISIT: Localize this error message. -ac
                throw new SAXNotSupportedException(
                    "PAR013 Property \""+propertyId+"\" is read only."
                    +'\n'+propertyId
                    ); // read-only property
            }
            //
            // Drop through and perform default processing
            //
        }

        //
        // Xerces Properties
        //

        /*
        else if (propertyId.startsWith(XERCES_PROPERTIES_PREFIX)) {
            //
            // Drop through and perform default processing
            //
        }
        */

        //
        // Perform default processing
        //

        super.setProperty(propertyId, value);

    } // setProperty(String,Object)

    /**
     * Query the value of a property.
     *
     * Return the current value of a property in a SAX2 parser.
     * The parser might not recognize the property.
     *
     * @param propertyId The unique identifier (URI) of the property
     *                   being set.
     * @return The current value of the property.
     * @exception org.xml.sax.SAXNotRecognizedException If the
     *            requested property is not known.
     * @exception SAXNotSupportedException If the
     *            requested property is known but not supported.
     */
    public Object getProperty(String propertyId)
        throws SAXNotRecognizedException, SAXNotSupportedException {

        //
        // SAX2 core properties
        //

        if (propertyId.startsWith(Constants.SAX_PROPERTY_PREFIX)) {
            String property =
                propertyId.substring(Constants.SAX_PROPERTY_PREFIX.length());
            //
            // http://xml.org/sax/properties/lexical-handler
            // Value type: org.xml.sax.ext.LexicalHandler
            // Access: read/write, pre-parse only
            //   Set the lexical event handler.
            //
            if (property.equals(Constants.LEXICAL_HANDLER_PROPERTY)) {
                return getLexicalHandler();
            }
            //
            // http://xml.org/sax/properties/declaration-handler
            // Value type: org.xml.sax.ext.DeclHandler
            // Access: read/write, pre-parse only
            //   Set the DTD declaration event handler.
            //
            if (property.equals(Constants.DECLARATION_HANDLER_PROPERTY)) {
                return getDeclHandler();
            }
            //
            // http://xml.org/sax/properties/dom-node
            // Value type: DOM Node
            // Access: read-only
            //   Get the DOM node currently being visited, if the SAX parser is
            //   iterating over a DOM tree.  If the parser recognises and
            //   supports this property but is not currently visiting a DOM
            //   node, it should return null (this is a good way to check for
            //   availability before the parse begins).
            //
            if (property.equals(Constants.DOM_NODE_PROPERTY)) {
                // REVISIT: Localize this error message. -Ac
                throw new SAXNotSupportedException(
                "PAR014 Cannot getProperty(\""+propertyId
                +"\". No DOM Tree exists.\n"+propertyId
                ); // we are not iterating a DOM tree
            }
            //
            // Drop through and perform default processing
            //
        }

        //
        // Xerces properties
        //

        /*
        else if (propertyId.startsWith(XERCES_PROPERTIES_PREFIX)) {
            //
            // Drop through and perform default processing
            //
        }
        */

        //
        // Perform default processing
        //

        return super.getProperty(propertyId);

    } // getProperty(String):Object

    //
    // Protected methods
    //

    // SAX2 core properties

    /**
     * Set the DTD declaration event handler.
     * <p>
     * This method is the equivalent to the property:
     * <pre>
     * http://xml.org/sax/properties/declaration-handler
     * </pre>
     *
     * @param handler The new handler.
     *
     * @see #getDeclHandler
     * @see #setProperty
     */
    protected void setDeclHandler(DeclHandler handler) 
        throws SAXNotRecognizedException, SAXNotSupportedException {

        if (fParseInProgress) {
            // REVISIT: Localize this error message. -Ac
            throw new SAXNotSupportedException(
                "PAR011 Feature: http://xml.org/sax/properties/declaration-handler"
                +" is not supported during parse."
                +"\nhttp://xml.org/sax/properties/declaration-handler");
        }
        fDeclHandler = handler;

    } // setDeclHandler(DeclHandler)

    /**
     * Returns the DTD declaration event handler.
     *
     * @see #setDeclHandler
     */
    protected DeclHandler getDeclHandler() 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        return fDeclHandler;
    } // getDeclHandler():DeclHandler

    /**
     * Set the lexical event handler.
     * <p>
     * This method is the equivalent to the property:
     * <pre>
     * http://xml.org/sax/properties/lexical-handler
     * </pre>
     *
     * @param handler lexical event handler
     *
     * @see #getLexicalHandler
     * @see #setProperty
     */
    protected void setLexicalHandler(LexicalHandler handler)
        throws SAXNotRecognizedException, SAXNotSupportedException {

        if (fParseInProgress) {
            // REVISIT: Localize this error message. -Ac
            throw new SAXNotSupportedException(
            "PAR011 Feature: http://xml.org/sax/properties/lexical-handler"
            +" is not supported during parse."
            +"\nhttp://xml.org/sax/properties/lexical-handler");
        }
        fLexicalHandler = handler;

    } // setLexicalHandler(LexicalHandler)

    /**
     * Returns the lexical handler.
     *
     * @see #setLexicalHandler
     */
    protected LexicalHandler getLexicalHandler() 
        throws SAXNotRecognizedException, SAXNotSupportedException {
        return fLexicalHandler;
    } // getLexicalHandler():LexicalHandler

    //
    // XMLDocumentParser methods
    //

    /** 
     * Reset all components before parsing. 
     *
     * @throws SAXException Thrown if an error occurs during initialization.
     */
    public void reset() throws SAXException {
        super.reset();

        // reset state
        fInDTD = false;

        // save needed symbols
        SymbolTable symbolTable = (SymbolTable)fConfiguration.getProperty(SYMBOL_TABLE);
        fEmptySymbol = symbolTable.addSymbol("");

    } // reset()

} // class AbstractSAXParser
