/*
 * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
 */

/*
 * Copyright 2005 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package com.sun.org.apache.xerces.internal.impl;

import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
import com.sun.org.apache.xerces.internal.util.AugmentationsImpl;
import com.sun.org.apache.xerces.internal.util.XMLAttributesIteratorImpl;
import com.sun.org.apache.xerces.internal.util.XMLChar;
import com.sun.org.apache.xerces.internal.util.XMLStringBuffer;
import com.sun.org.apache.xerces.internal.util.XMLSymbols;
import com.sun.org.apache.xerces.internal.utils.SecuritySupport;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.Limit;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
import com.sun.org.apache.xerces.internal.xni.Augmentations;
import com.sun.org.apache.xerces.internal.xni.QName;
import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
import com.sun.org.apache.xerces.internal.xni.XMLString;
import com.sun.org.apache.xerces.internal.xni.XNIException;
import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentScanner;
import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
import com.sun.xml.internal.stream.XMLBufferListener;
import com.sun.xml.internal.stream.XMLEntityStorage;
import com.sun.xml.internal.stream.dtd.DTDGrammarUtil;
import java.io.EOFException;
import java.io.IOException;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.events.XMLEvent;


/**
 *
 * This class is responsible for scanning the structure and content
 * of document fragments.
 *
 * This class has been modified as per the new design which is more suited to
 * efficiently build pull parser. Lot of improvements have been done and
 * the code has been added to support stax functionality/features.
 *
 * @author Neeraj Bajaj SUN Microsystems
 * @author K.Venugopal SUN Microsystems
 * @author Glenn Marcy, IBM
 * @author Andy Clark, IBM
 * @author Arnaud  Le Hors, IBM
 * @author Eric Ye, IBM
 * @author Sunitha Reddy, SUN Microsystems
 * @version $Id: XMLDocumentFragmentScannerImpl.java,v 1.19 2010-11-02 19:54:55 joehw Exp $
 *
 */
public class XMLDocumentFragmentScannerImpl
        extends XMLScanner
        implements XMLDocumentScanner, XMLComponent, XMLEntityHandler, XMLBufferListener {

    //
    // Constants
    //

    protected int fElementAttributeLimit, fXMLNameLimit;

    /** External subset resolver. **/
    protected ExternalSubsetResolver fExternalSubsetResolver;

    // scanner states

    //XXX this should be divided into more states.
    /** Scanner state: start of markup. */
    protected static final int SCANNER_STATE_START_OF_MARKUP = 21;

    /** Scanner state: content. */
    protected static final int SCANNER_STATE_CONTENT = 22;

    /** Scanner state: processing instruction. */
    protected static final int SCANNER_STATE_PI = 23;

    /** Scanner state: DOCTYPE. */
    protected static final int SCANNER_STATE_DOCTYPE = 24;

    /** Scanner state: XML Declaration */
    protected static final int SCANNER_STATE_XML_DECL = 25;

    /** Scanner state: root element. */
    protected static final int SCANNER_STATE_ROOT_ELEMENT = 26;

    /** Scanner state: comment. */
    protected static final int SCANNER_STATE_COMMENT = 27;

    /** Scanner state: reference. */
    protected static final int SCANNER_STATE_REFERENCE = 28;

    // <book type="hard"> reading attribute name 'type'
    protected static final int SCANNER_STATE_ATTRIBUTE = 29;

    // <book type="hard"> //reading attribute value.
    protected static final int SCANNER_STATE_ATTRIBUTE_VALUE = 30;

    /** Scanner state: trailing misc. USED BY DOCUMENT_SCANNER_IMPL*/
    //protected static final int SCANNER_STATE_TRAILING_MISC = 32;

    /** Scanner state: end of input. */
    protected static final int SCANNER_STATE_END_OF_INPUT = 33;

    /** Scanner state: terminated. */
    protected static final int SCANNER_STATE_TERMINATED = 34;

    /** Scanner state: CDATA section. */
    protected static final int SCANNER_STATE_CDATA = 35;

    /** Scanner state: Text declaration. */
    protected static final int SCANNER_STATE_TEXT_DECL = 36;

    /** Scanner state: Text declaration. */
    protected static final int SCANNER_STATE_CHARACTER_DATA = 37;

    //<book type="hard">foo</book>
    protected static final int SCANNER_STATE_START_ELEMENT_TAG = 38;

    //<book type="hard">foo</book> reading </book>
    protected static final int SCANNER_STATE_END_ELEMENT_TAG = 39;

    protected static final int SCANNER_STATE_CHAR_REFERENCE = 40;
    protected static final int SCANNER_STATE_BUILT_IN_REFS = 41;

    // feature identifiers


    /** Feature identifier: notify built-in refereces. */
    protected static final String NOTIFY_BUILTIN_REFS =
            Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_BUILTIN_REFS_FEATURE;

    /** Property identifier: entity resolver. */
    protected static final String ENTITY_RESOLVER =
            Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;

    /** Feature identifier: standard uri conformant */
    protected static final String STANDARD_URI_CONFORMANT =
            Constants.XERCES_FEATURE_PREFIX +Constants.STANDARD_URI_CONFORMANT_FEATURE;

    /** Property identifier: Security property manager. */
    private static final String XML_SECURITY_PROPERTY_MANAGER =
            Constants.XML_SECURITY_PROPERTY_MANAGER;

    /** access external dtd: file protocol
     *  For DOM/SAX, the secure feature is set to true by default
     */
    final static String EXTERNAL_ACCESS_DEFAULT = Constants.EXTERNAL_ACCESS_DEFAULT;

    // recognized features and properties

    /** Recognized features. */
    private static final String[] RECOGNIZED_FEATURES = {
                NAMESPACES,
                VALIDATION,
                NOTIFY_BUILTIN_REFS,
                NOTIFY_CHAR_REFS,
                Constants.STAX_REPORT_CDATA_EVENT
    };

    /** Feature defaults. */
    private static final Boolean[] FEATURE_DEFAULTS = {
                Boolean.TRUE,
                null,
                Boolean.FALSE,
                Boolean.FALSE,
                Boolean.TRUE
    };

    /** Recognized properties. */
    private static final String[] RECOGNIZED_PROPERTIES = {
        SYMBOL_TABLE,
                ERROR_REPORTER,
                ENTITY_MANAGER,
                XML_SECURITY_PROPERTY_MANAGER
    };

    /** Property defaults. */
    private static final Object[] PROPERTY_DEFAULTS = {
                null,
                null,
                null,
                null
    };

    private static final char [] cdata = {'[','C','D','A','T','A','['};
    static final char [] xmlDecl = {'<','?','x','m','l'};
    // private static final char [] endTag = {'<','/'};
    // debugging

    /** Debug scanner state. */
    private static final boolean DEBUG_SCANNER_STATE = false;

    /** Debug driver. */
    private static final boolean DEBUG_DISPATCHER = false;

    /** Debug content driver scanning. */
    protected static final boolean DEBUG_START_END_ELEMENT = false;


    /** Debug driver next */
    protected static final boolean DEBUG_NEXT = false ;

    /** Debug driver next */
    protected static final boolean DEBUG = false;
    protected static final boolean DEBUG_COALESCE = false;
    //
    // Data
    //

    // protected data

    /** Document handler. */
    protected XMLDocumentHandler fDocumentHandler;
    protected int fScannerLastState ;

    /** Entity Storage */
    protected XMLEntityStorage fEntityStore;

    /** Entity stack. */
    protected int[] fEntityStack = new int[4];

    /** Markup depth. */
    protected int fMarkupDepth;

    //is the element empty
    protected boolean fEmptyElement ;

    //track if we are reading attributes, this is usefule while
    //there is a callback
    protected boolean fReadingAttributes = false;

    /** Scanner state. */
    protected int fScannerState;

    /** SubScanner state: inside scanContent method. */
    protected boolean fInScanContent = false;
    protected boolean fLastSectionWasCData = false;
    protected boolean fLastSectionWasEntityReference = false;
    protected boolean fLastSectionWasCharacterData = false;

    /** has external dtd */
    protected boolean fHasExternalDTD;

    /** Standalone. */
    protected boolean fStandaloneSet;
    protected boolean fStandalone;
    protected String fVersion;

    // element information

    /** Current element. */
    protected QName fCurrentElement;

    /** Element stack. */
    protected ElementStack fElementStack = new ElementStack();
    protected ElementStack2 fElementStack2 = new ElementStack2();

    // other info

    /** Document system identifier.
     * REVISIT:  So what's this used for?  - NG
     * protected String fDocumentSystemId;
     ******/

    protected String fPITarget ;

    //xxx do we need to create an extra XMLString object... look for using fTempString for collecting all the data values
    protected XMLString fPIData  = new XMLString();

    // features


    /** Notify built-in references. */
    protected boolean fNotifyBuiltInRefs = false;

    //STAX related properties
    //defaultValues.
    protected boolean fSupportDTD = true;
    protected boolean fReplaceEntityReferences = true;
    protected boolean fSupportExternalEntities = false;
    protected boolean fReportCdataEvent = false ;
    protected boolean fIsCoalesce = false ;
    protected String fDeclaredEncoding =  null;
    /** Xerces Feature: Disallow doctype declaration. */
    protected boolean fDisallowDoctype = false;

    /**
     * comma-delimited list of protocols that are allowed for the purpose
     * of accessing external dtd or entity references
     */
    protected String fAccessExternalDTD = EXTERNAL_ACCESS_DEFAULT;

    /**
     * standard uri conformant (strict uri).
     * http://apache.org/xml/features/standard-uri-conformant
     */
    protected boolean fStrictURI;

    // drivers

    /** Active driver. */
    protected Driver fDriver;

    /** Content driver. */
    protected Driver fContentDriver = createContentDriver();

    // temporary variables

    /** Element QName. */
    protected QName fElementQName = new QName();

    /** Attribute QName. */
    protected QName fAttributeQName = new QName();

    /**
     * CHANGED: Using XMLAttributesIteratorImpl instead of XMLAttributesImpl. This class
     * implements Iterator interface so we can directly give Attributes in the form of
     * iterator.
     */
    protected XMLAttributesIteratorImpl fAttributes = new XMLAttributesIteratorImpl();


    /** String. */
    protected XMLString fTempString = new XMLString();

    /** String. */
    protected XMLString fTempString2 = new XMLString();

    /** Array of 3 strings. */
    private String[] fStrings = new String[3];

    /** Making the buffer accesible to derived class -- String buffer. */
    protected XMLStringBuffer fStringBuffer = new XMLStringBuffer();

    /** Making the buffer accesible to derived class -- String buffer. */
    protected XMLStringBuffer fStringBuffer2 = new XMLStringBuffer();

    /** stores character data. */
    /** Making the buffer accesible to derived class -- stores PI data */
    protected XMLStringBuffer fContentBuffer = new XMLStringBuffer();

    /** Single character array. */
    private final char[] fSingleChar = new char[1];
    private String fCurrentEntityName = null;

    // New members
    protected boolean fScanToEnd = false;

    protected DTDGrammarUtil dtdGrammarUtil= null;

    protected boolean fAddDefaultAttr = false;

    protected boolean foundBuiltInRefs = false;


    //skip element algorithm
    static final short MAX_DEPTH_LIMIT = 5 ;
    static final short ELEMENT_ARRAY_LENGTH = 200 ;
    static final short MAX_POINTER_AT_A_DEPTH = 4 ;
    static final boolean DEBUG_SKIP_ALGORITHM = false;
    //create a elemnet array of length equal to ELEMENT_ARRAY_LENGTH
    String [] fElementArray = new String[ELEMENT_ARRAY_LENGTH] ;
    //pointer location where last element was skipped
    short fLastPointerLocation = 0 ;
    short fElementPointer = 0 ;
    //2D array to store pointer info
    short [] [] fPointerInfo = new short[MAX_DEPTH_LIMIT] [MAX_POINTER_AT_A_DEPTH] ;
    protected String fElementRawname ;
    protected boolean fShouldSkip = false;
    protected boolean fAdd = false ;
    protected boolean fSkip = false;

    /** Reusable Augmentations. */
    private Augmentations fTempAugmentations = null;
    //
    // Constructors
    //

    /** Default constructor. */
    public XMLDocumentFragmentScannerImpl() {
    } // <init>()

    //
    // XMLDocumentScanner methods
    //

    /**
     * Sets the input source.
     *
     * @param inputSource The input source.
     *
     * @throws IOException Thrown on i/o error.
     */
    public void setInputSource(XMLInputSource inputSource) throws IOException {
        fEntityManager.setEntityHandler(this);
        fEntityManager.startEntity(false, "$fragment$", inputSource, false, true);
        // fDocumentSystemId = fEntityManager.expandSystemId(inputSource.getSystemId());
    } // setInputSource(XMLInputSource)

    /**
     * Scans a document.
     *
     * @param complete True if the scanner should scan the document
     *                 completely, pushing all events to the registered
     *                 document handler. A value of false indicates that
     *                 that the scanner should only scan the next portion
     *                 of the document and return. A scanner instance is
     *                 permitted to completely scan a document if it does
     *                 not support this "pull" scanning model.
     *
     * @return True if there is more to scan, false otherwise.
     */
    public boolean scanDocument(boolean complete)
    throws IOException, XNIException {

        // keep dispatching "events"
        fEntityManager.setEntityHandler(this);
        //System.out.println(" get Document Handler in NSDocumentHandler " + fDocumentHandler );

        int event = next();
        do {
            switch (event) {
                case XMLStreamConstants.START_DOCUMENT :
                    //fDocumentHandler.startDocument(fEntityManager.getEntityScanner(),fEntityManager.getEntityScanner().getVersion(),fNamespaceContext,null);// not able to get
                    break;
                case XMLStreamConstants.START_ELEMENT :
                    //System.out.println(" in scann element");
                    //fDocumentHandler.startElement(getElementQName(),fAttributes,null);
                    break;
                case XMLStreamConstants.CHARACTERS :
                    fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
                    fDocumentHandler.characters(getCharacterData(),null);
                    break;
                case XMLStreamConstants.SPACE:
                    //check if getCharacterData() is the right function to retrieve ignorableWhitespace information.
                    //System.out.println("in the space");
                    //fDocumentHandler.ignorableWhitespace(getCharacterData(), null);
                    break;
                case XMLStreamConstants.ENTITY_REFERENCE :
                    fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
                    //entity reference callback are given in startEntity
                    break;
                case XMLStreamConstants.PROCESSING_INSTRUCTION :
                    fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
                    fDocumentHandler.processingInstruction(getPITarget(),getPIData(),null);
                    break;
                case XMLStreamConstants.COMMENT :
                    fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
                    fDocumentHandler.comment(getCharacterData(),null);
                    break;
                case XMLStreamConstants.DTD :
                    //all DTD related callbacks are handled in DTDScanner.
                    //1. Stax doesn't define DTD states as it does for XML Document.
                    //therefore we don't need to take care of anything here. So Just break;
                    break;
                case XMLStreamConstants.CDATA:
                    fEntityScanner.checkNodeCount(fEntityScanner.fCurrentEntity);
                    fDocumentHandler.startCDATA(null);
                    //xxx: check if CDATA values comes from getCharacterData() function
                    fDocumentHandler.characters(getCharacterData(),null);
                    fDocumentHandler.endCDATA(null);
                    //System.out.println(" in CDATA of the XMLNSDocumentScannerImpl");
                    break;
                case XMLStreamConstants.NOTATION_DECLARATION :
                    break;
                case XMLStreamConstants.ENTITY_DECLARATION :
                    break;
                case XMLStreamConstants.NAMESPACE :
                    break;
                case XMLStreamConstants.ATTRIBUTE :
                    break;
                case XMLStreamConstants.END_ELEMENT :
                    //do not give callback here.
                    //this callback is given in scanEndElement function.
                    //fDocumentHandler.endElement(getElementQName(),null);
                    break;
                default :
                    throw new InternalError("processing event: " + event);

            }
            //System.out.println("here in before calling next");
            event = next();
            //System.out.println("here in after calling next");
        } while (event!=XMLStreamConstants.END_DOCUMENT && complete);

        if(event == XMLStreamConstants.END_DOCUMENT) {
            fDocumentHandler.endDocument(null);
            return false;
        }

        return true;

    } // scanDocument(boolean):boolean



    public com.sun.org.apache.xerces.internal.xni.QName getElementQName(){
        if(fScannerLastState == XMLEvent.END_ELEMENT){
            fElementQName.setValues(fElementStack.getLastPoppedElement());
        }
        return fElementQName ;
    }

    /** return the next state on the input
     * @return int
     */

    public int next() throws IOException, XNIException {
        return fDriver.next();
    }

    //
    // XMLComponent methods
    //

    /**
     * Resets the component. The component can query the component manager
     * about any features and properties that affect the operation of the
     * component.
     *
     * @param componentManager The component manager.
     *
     * @throws SAXException Thrown by component on initialization error.
     *                      For example, if a feature or property is
     *                      required for the operation of the component, the
     *                      component manager may throw a
     *                      SAXNotRecognizedException or a
     *                      SAXNotSupportedException.
     */

    public void reset(XMLComponentManager componentManager)
    throws XMLConfigurationException {

        super.reset(componentManager);

        // other settings
        // fDocumentSystemId = null;

        // sax features
        //fAttributes.setNamespaces(fNamespaces);

        // xerces features
        fReportCdataEvent = componentManager.getFeature(Constants.STAX_REPORT_CDATA_EVENT, true);
        fSecurityManager = (XMLSecurityManager)componentManager.getProperty(Constants.SECURITY_MANAGER, null);
        fNotifyBuiltInRefs = componentManager.getFeature(NOTIFY_BUILTIN_REFS, false);

        Object resolver = componentManager.getProperty(ENTITY_RESOLVER, null);
        fExternalSubsetResolver = (resolver instanceof ExternalSubsetResolver) ?
                (ExternalSubsetResolver) resolver : null;

        //attribute
        fReadingAttributes = false;
        //xxx: external entities are supported in Xerces
        // it would be good to define feature for this case
        fSupportExternalEntities = true;
        fReplaceEntityReferences = true;
        fIsCoalesce = false;

        // setup Driver
        setScannerState(SCANNER_STATE_CONTENT);
        setDriver(fContentDriver);

        // JAXP 1.5 features and properties
        XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager)
                componentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER, null);
        fAccessExternalDTD = spm.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD);

        fStrictURI = componentManager.getFeature(STANDARD_URI_CONFORMANT, false);

        resetCommon();
        //fEntityManager.test();
    } // reset(XMLComponentManager)


    public void reset(PropertyManager propertyManager){

        super.reset(propertyManager);

        // other settings
        // fDocumentSystemId = null;
        fNamespaces = ((Boolean)propertyManager.getProperty(XMLInputFactory.IS_NAMESPACE_AWARE)).booleanValue();
        fNotifyBuiltInRefs = false ;

        //fElementStack2.clear();
        //fReplaceEntityReferences = true;
        //fSupportExternalEntities = true;
        Boolean bo = (Boolean)propertyManager.getProperty(XMLInputFactory.IS_REPLACING_ENTITY_REFERENCES);
        fReplaceEntityReferences = bo.booleanValue();
        bo = (Boolean)propertyManager.getProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES);
        fSupportExternalEntities = bo.booleanValue();
        Boolean cdata = (Boolean)propertyManager.getProperty(Constants.ZEPHYR_PROPERTY_PREFIX + Constants.STAX_REPORT_CDATA_EVENT) ;
        if(cdata != null)
            fReportCdataEvent = cdata.booleanValue() ;
        Boolean coalesce = (Boolean)propertyManager.getProperty(XMLInputFactory.IS_COALESCING) ;
        if(coalesce != null)
            fIsCoalesce = coalesce.booleanValue();
        fReportCdataEvent = fIsCoalesce ? false : (fReportCdataEvent && true) ;
        //if fIsCoalesce is set to true, set the value of fReplaceEntityReferences to true,
        //if fIsCoalesce is set to false, take the value of fReplaceEntityReferences as set by application
        fReplaceEntityReferences = fIsCoalesce ? true : fReplaceEntityReferences;
        // setup Driver
        //we dont need to do this -- nb.
        //setScannerState(SCANNER_STATE_CONTENT);
        //setDriver(fContentDriver);
        //fEntityManager.test();

         // JAXP 1.5 features and properties
        XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager)
                propertyManager.getProperty(XML_SECURITY_PROPERTY_MANAGER);
        fAccessExternalDTD = spm.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD);

        fSecurityManager = (XMLSecurityManager)propertyManager.getProperty(Constants.SECURITY_MANAGER);
        resetCommon();
    } // reset(XMLComponentManager)

    void resetCommon() {
        // initialize vars
        fMarkupDepth = 0;
        fCurrentElement = null;
        fElementStack.clear();
        fHasExternalDTD = false;
        fStandaloneSet = false;
        fStandalone = false;
        fInScanContent = false;
        //skipping algorithm
        fShouldSkip = false;
        fAdd = false;
        fSkip = false;

        fEntityStore = fEntityManager.getEntityStore();
        dtdGrammarUtil = null;

        if (fSecurityManager != null) {
            fElementAttributeLimit = fSecurityManager.getLimit(XMLSecurityManager.Limit.ELEMENT_ATTRIBUTE_LIMIT);
            fXMLNameLimit = fSecurityManager.getLimit(XMLSecurityManager.Limit.MAX_NAME_LIMIT);
        } else {
            fElementAttributeLimit = 0;
            fXMLNameLimit = XMLSecurityManager.Limit.MAX_NAME_LIMIT.defaultValue();
        }
        fLimitAnalyzer = fEntityManager.fLimitAnalyzer;
    }

    /**
     * Returns a list of feature identifiers that are recognized by
     * this component. This method may return null if no features
     * are recognized by this component.
     */
    public String[] getRecognizedFeatures() {
        return (String[])(RECOGNIZED_FEATURES.clone());
    } // getRecognizedFeatures():String[]

    /**
     * Sets the state of a feature. This method is called by the component
     * manager any time after reset when a feature changes state.
     * <p>
     * <strong>Note:</strong> Components should silently ignore features
     * that do not affect the operation of the component.
     *
     * @param featureId The feature identifier.
     * @param state     The state of the feature.
     *
     * @throws SAXNotRecognizedException The component should not throw
     *                                   this exception.
     * @throws SAXNotSupportedException The component should not throw
     *                                  this exception.
     */
    public void setFeature(String featureId, boolean state)
    throws XMLConfigurationException {

        super.setFeature(featureId, state);

        // Xerces properties
        if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
            String feature = featureId.substring(Constants.XERCES_FEATURE_PREFIX.length());
            if (feature.equals(Constants.NOTIFY_BUILTIN_REFS_FEATURE)) {
                fNotifyBuiltInRefs = state;
            }
        }

    } // setFeature(String,boolean)

    /**
     * Returns a list of property identifiers that are recognized by
     * this component. This method may return null if no properties
     * are recognized by this component.
     */
    public String[] getRecognizedProperties() {
        return (String[])(RECOGNIZED_PROPERTIES.clone());
    } // getRecognizedProperties():String[]

    /**
     * Sets the value of a property. This method is called by the component
     * manager any time after reset when a property changes value.
     * <p>
     * <strong>Note:</strong> Components should silently ignore properties
     * that do not affect the operation of the component.
     *
     * @param propertyId The property identifier.
     * @param value      The value of the property.
     *
     * @throws SAXNotRecognizedException The component should not throw
     *                                   this exception.
     * @throws SAXNotSupportedException The component should not throw
     *                                  this exception.
     */
    public void setProperty(String propertyId, Object value)
    throws XMLConfigurationException {

        super.setProperty(propertyId, value);

        // Xerces properties
        if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
            final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
            if (suffixLength == Constants.ENTITY_MANAGER_PROPERTY.length() &&
                    propertyId.endsWith(Constants.ENTITY_MANAGER_PROPERTY)) {
                fEntityManager = (XMLEntityManager)value;
                return;
            }
            if (suffixLength == Constants.ENTITY_RESOLVER_PROPERTY.length() &&
                    propertyId.endsWith(Constants.ENTITY_RESOLVER_PROPERTY)) {
                fExternalSubsetResolver = (value instanceof ExternalSubsetResolver) ?
                    (ExternalSubsetResolver) value : null;
                return;
            }
        }


                // Xerces properties
        if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
            String property = propertyId.substring(Constants.XERCES_PROPERTY_PREFIX.length());
            if (property.equals(Constants.ENTITY_MANAGER_PROPERTY)) {
                fEntityManager = (XMLEntityManager)value;
            }
            return;
        }

        //JAXP 1.5 properties
        if (propertyId.equals(XML_SECURITY_PROPERTY_MANAGER))
        {
            XMLSecurityPropertyManager spm = (XMLSecurityPropertyManager)value;
            fAccessExternalDTD = spm.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD);
        }

    } // setProperty(String,Object)

    /**
     * Returns the default state for a feature, or null if this
     * component does not want to report a default value for this
     * feature.
     *
     * @param featureId The feature identifier.
     *
     * @since Xerces 2.2.0
     */
    public Boolean getFeatureDefault(String featureId) {
        for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
            if (RECOGNIZED_FEATURES[i].equals(featureId)) {
                return FEATURE_DEFAULTS[i];
            }
        }
        return null;
    } // getFeatureDefault(String):Boolean

    /**
     * Returns the default state for a property, or null if this
     * component does not want to report a default value for this
     * property.
     *
     * @param propertyId The property identifier.
     *
     * @since Xerces 2.2.0
     */
    public Object getPropertyDefault(String propertyId) {
        for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
            if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
                return PROPERTY_DEFAULTS[i];
            }
        }
        return null;
    } // getPropertyDefault(String):Object

    //
    // XMLDocumentSource methods
    //

    /**
     * setDocumentHandler
     *
     * @param documentHandler
     */
    public void setDocumentHandler(XMLDocumentHandler documentHandler) {
        fDocumentHandler = documentHandler;
        //System.out.println(" In Set DOCUMENT HANDLER" + fDocumentHandler + " scanner =" + this);
    } // setDocumentHandler(XMLDocumentHandler)


    /** Returns the document handler */
    public XMLDocumentHandler getDocumentHandler(){
        return fDocumentHandler;
    }

    //
    // XMLEntityHandler 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 entities are just specified by their name.
     *
     * @param name     The name of the entity.
     * @param identifier The resource identifier.
     * @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).
     * @param augs     Additional information that may include infoset augmentations
     *
     * @throws XNIException Thrown by handler to signal an error.
     */
    public void startEntity(String name,
            XMLResourceIdentifier identifier,
            String encoding, Augmentations augs) throws XNIException {

        // keep track of this entity before fEntityDepth is increased
        if (fEntityDepth == fEntityStack.length) {
            int[] entityarray = new int[fEntityStack.length * 2];
            System.arraycopy(fEntityStack, 0, entityarray, 0, fEntityStack.length);
            fEntityStack = entityarray;
        }
        fEntityStack[fEntityDepth] = fMarkupDepth;

        super.startEntity(name, identifier, encoding, augs);

        // WFC:  entity declared in external subset in standalone doc
        if(fStandalone && fEntityStore.isEntityDeclInExternalSubset(name)) {
            reportFatalError("MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE",
                    new Object[]{name});
        }

        /** we are not calling the handlers yet.. */
        // call handler
        if (fDocumentHandler != null && !fScanningAttribute) {
            if (!name.equals("[xml]")) {
                fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
            }
        }

    } // startEntity(String,XMLResourceIdentifier,String)

    /**
     * This method notifies the end of an entity. The DTD has the pseudo-name
     * of "[dtd]" parameter entity names start with '%'; and general entities
     * are just specified by their name.
     *
     * @param name The name of the entity.
     * @param augs Additional information that may include infoset augmentations
     *
     * @throws XNIException Thrown by handler to signal an error.
     */
    public void endEntity(String name, Augmentations augs) throws IOException, XNIException {

        /**
         * // flush possible pending output buffer - see scanContent
         * if (fInScanContent && fStringBuffer.length != 0
         * && fDocumentHandler != null) {
         * fDocumentHandler.characters(fStringBuffer, null);
         * fStringBuffer.length = 0; // make sure we know it's been flushed
         * }
         */
        super.endEntity(name, augs);

        // make sure markup is properly balanced
        if (fMarkupDepth != fEntityStack[fEntityDepth]) {
            reportFatalError("MarkupEntityMismatch", null);
        }

        /**/
        // call handler
        if (fDocumentHandler != null && !fScanningAttribute) {
            if (!name.equals("[xml]")) {
                fDocumentHandler.endGeneralEntity(name, augs);
            }
        }


    } // endEntity(String)

    //
    // Protected methods
    //

    // Driver factory methods

    /** Creates a content Driver. */
    protected Driver createContentDriver() {
        return new FragmentContentDriver();
    } // createContentDriver():Driver

    // scanning methods

    /**
     * Scans an XML or text declaration.
     * <p>
     * <pre>
     * [23] XMLDecl ::= '&lt;?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
     * [24] VersionInfo ::= S 'version' Eq (' VersionNum ' | " VersionNum ")
     * [80] EncodingDecl ::= S 'encoding' Eq ('"' EncName '"' |  "'" EncName "'" )
     * [81] EncName ::= [A-Za-z] ([A-Za-z0-9._] | '-')*
     * [32] SDDecl ::= S 'standalone' Eq (("'" ('yes' | 'no') "'")
     *                 | ('"' ('yes' | 'no') '"'))
     *
     * [77] TextDecl ::= '&lt;?xml' VersionInfo? EncodingDecl S? '?>'
     * </pre>
     *
     * @param scanningTextDecl True if a text declaration is to
     *                         be scanned instead of an XML
     *                         declaration.
     */
    protected void scanXMLDeclOrTextDecl(boolean scanningTextDecl)
    throws IOException, XNIException {

        // scan decl
        super.scanXMLDeclOrTextDecl(scanningTextDecl, fStrings);
        fMarkupDepth--;

        // pseudo-attribute values
        String version = fStrings[0];
        String encoding = fStrings[1];
        String standalone = fStrings[2];
        fDeclaredEncoding = encoding;
        // set standalone
        fStandaloneSet = standalone != null;
        fStandalone = fStandaloneSet && standalone.equals("yes");
        ///xxx see where its used.. this is not used anywhere. it may be useful for entity to store this information
        //but this information is only related with Document Entity.
        fEntityManager.setStandalone(fStandalone);


        // call handler
        if (fDocumentHandler != null) {
            if (scanningTextDecl) {
                fDocumentHandler.textDecl(version, encoding, null);
            } else {
                fDocumentHandler.xmlDecl(version, encoding, standalone, null);
            }
        }

        if(version != null){
            fEntityScanner.setVersion(version);
            fEntityScanner.setXMLVersion(version);
        }
        // set encoding on reader, only if encoding was not specified by the application explicitly
        if (encoding != null && !fEntityScanner.getCurrentEntity().isEncodingExternallySpecified()) {
             fEntityScanner.setEncoding(encoding);
        }

    } // scanXMLDeclOrTextDecl(boolean)

    public String getPITarget(){
        return fPITarget ;
    }

    public XMLStringBuffer getPIData(){
        return fContentBuffer ;
    }

    //XXX: why not this function behave as per the state of the parser?
    public XMLString getCharacterData(){
        if(fUsebuffer){
            return fContentBuffer ;
        }else{
            return fTempString;
        }

    }


    /**
     * Scans a processing data. This is needed to handle the situation
     * where a document starts with a processing instruction whose
     * target name <em>starts with</em> "xml". (e.g. xmlfoo)
     *
     * @param target The PI target
     * @param data The XMLStringBuffer to fill in with the data
     */
    protected void scanPIData(String target, XMLStringBuffer data)
    throws IOException, XNIException {

        super.scanPIData(target, data);

        //set the PI target and values
        fPITarget = target ;

        fMarkupDepth--;

    } // scanPIData(String)

    /**
     * Scans a comment.
     * <p>
     * <pre>
     * [15] Comment ::= '&lt!--' ((Char - '-') | ('-' (Char - '-')))* '-->'
     * </pre>
     * <p>
     * <strong>Note:</strong> Called after scanning past '&lt;!--'
     */
    protected void scanComment() throws IOException, XNIException {
        fContentBuffer.clear();
        scanComment(fContentBuffer);
        //getTextCharacters can also be called for reading comments
        fUsebuffer = true;
        fMarkupDepth--;

    } // scanComment()

    //xxx value returned by this function may not remain valid if another event is scanned.
    public String getComment(){
        return fContentBuffer.toString();
    }

    void addElement(String rawname){
        if(fElementPointer < ELEMENT_ARRAY_LENGTH){
            //storing element raw name in a linear list of array
            fElementArray[fElementPointer] = rawname ;
            //storing elemnetPointer for particular element depth

            if(DEBUG_SKIP_ALGORITHM){
                StringBuffer sb = new StringBuffer() ;
                sb.append(" Storing element information ") ;
                sb.append(" fElementPointer = " + fElementPointer) ;
                sb.append(" fElementRawname = " + fElementQName.rawname) ;
                sb.append(" fElementStack.fDepth = " + fElementStack.fDepth);
                System.out.println(sb.toString()) ;
            }

            //store pointer information only when element depth is less MAX_DEPTH_LIMIT
            if(fElementStack.fDepth < MAX_DEPTH_LIMIT){
                short column = storePointerForADepth(fElementPointer);
                if(column > 0){
                    short pointer = getElementPointer((short)fElementStack.fDepth, (short)(column - 1) );
                    //identity comparison shouldn't take much time and we can rely on this
                    //since its guaranteed to have same object id for same string.
                    if(rawname == fElementArray[pointer]){
                        fShouldSkip = true ;
                        fLastPointerLocation = pointer ;
                        //reset the things and return.
                        resetPointer((short)fElementStack.fDepth , column) ;
                        fElementArray[fElementPointer] = null ;
                        return ;
                    }else{
                        fShouldSkip = false ;
                    }
                }
            }
            fElementPointer++ ;
        }
    }


    void resetPointer(short depth, short column){
        fPointerInfo[depth] [column] = (short)0;
    }

    //returns column information at which pointer was stored.
    short storePointerForADepth(short elementPointer){
        short depth = (short) fElementStack.fDepth ;

        //Stores element pointer locations at particular depth , only 4 pointer locations
        //are stored at particular depth for now.
        for(short i = 0 ; i < MAX_POINTER_AT_A_DEPTH ; i++){

            if(canStore(depth, i)){
                fPointerInfo[depth][i] = elementPointer ;
                if(DEBUG_SKIP_ALGORITHM){
                    StringBuffer sb = new StringBuffer() ;
                    sb.append(" Pointer information ") ;
                    sb.append(" fElementPointer = " + fElementPointer) ;
                    sb.append(" fElementStack.fDepth = " + fElementStack.fDepth);
                    sb.append(" column = " + i ) ;
                    System.out.println(sb.toString()) ;
                }
                return i;
            }
            //else
            //pointer was not stored because we reached the limit
        }
        return -1 ;
    }

    boolean canStore(short depth, short column){
        //colum = 0 , means first element at particular depth
        //column = 1, means second element at particular depth
        //        calle should make sure that it doesn't call for value outside allowed co-ordinates
        return fPointerInfo[depth][column] == 0 ? true : false ;
    }


    short getElementPointer(short depth, short column){
        //colum = 0 , means first element at particular depth
        //column = 1, means second element at particular depth
        //        calle should make sure that it doesn't call for value outside allowed co-ordinates
        return fPointerInfo[depth][column] ;
    }

    //this function assumes that string passed is not null and skips
    //the following string from the buffer this makes sure
    boolean skipFromTheBuffer(String rawname) throws IOException{
        if(fEntityScanner.skipString(rawname)){
            char c = (char)fEntityScanner.peekChar() ;
            //If the start element was completely skipped we should encounter either ' '(space),
            //or '/' (in case of empty element)  or '>'
            if( c == ' ' || c == '/' || c == '>'){
                fElementRawname = rawname ;
                return true ;
            } else{
                return false;
            }
        } else
            return false ;
    }

    boolean skipQElement(String rawname) throws IOException{

        final int c = fEntityScanner.getChar(rawname.length());
        //if this character is still valid element name -- this means string can't match
        if(XMLChar.isName(c)){
            return false;
        }else{
            return fEntityScanner.skipString(rawname);
        }
    }

    protected boolean skipElement() throws IOException {

        if(!fShouldSkip) return false ;

        if(fLastPointerLocation != 0){
            //Look at the next element stored in the array list.. we might just get a match.
            String rawname = fElementArray[fLastPointerLocation + 1] ;
            if(rawname != null && skipFromTheBuffer(rawname)){
                fLastPointerLocation++ ;
                if(DEBUG_SKIP_ALGORITHM){
                    System.out.println("Element " + fElementRawname + " was SKIPPED at pointer location = " + fLastPointerLocation);
                }
                return true ;
            } else{
                //reset it back to zero... we haven't got the correct subset yet.
                fLastPointerLocation = 0 ;

            }
        }
        //xxx: we can put some logic here as from what column it should start looking
        //for now we always start at 0
        //fallback to tolerant algorithm, it would look for differnt element stored at different
        //depth and get us the pointer location.
        return fShouldSkip && skipElement((short)0);

    }

    //start of the column at which it should try searching
    boolean skipElement(short column) throws IOException {
        short depth = (short)fElementStack.fDepth ;

        if(depth > MAX_DEPTH_LIMIT){
            return fShouldSkip = false ;
        }
        for(short i = column ; i < MAX_POINTER_AT_A_DEPTH ; i++){
            short pointer = getElementPointer(depth , i ) ;

            if(pointer == 0){
                return fShouldSkip = false ;
            }

            if(fElementArray[pointer] != null && skipFromTheBuffer(fElementArray[pointer])){
                if(DEBUG_SKIP_ALGORITHM){
                    System.out.println();
                    System.out.println("Element " + fElementRawname + " was SKIPPED at depth = " + fElementStack.fDepth + " column = " + column );
                    System.out.println();
                }
                fLastPointerLocation = pointer ;
                return fShouldSkip = true ;
            }
        }
        return fShouldSkip = false ;
    }

    /**
     * Scans a start element. This method will handle the binding of
     * namespace information and notifying the handler of the start
     * of the element.
     * <p>
     * <pre>
     * [44] EmptyElemTag ::= '&lt;' Name (S Attribute)* S? '/>'
     * [40] STag ::= '&lt;' Name (S Attribute)* S? '>'
     * </pre>
     * <p>
     * <strong>Note:</strong> This method assumes that the leading
     * '&lt;' character has been consumed.
     * <p>
     * <strong>Note:</strong> This method uses the fElementQName and
     * fAttributes variables. The contents of these variables will be
     * destroyed. The caller should copy important information out of
     * these variables before calling this method.
     * NB: Content in fAttributes is valid only till the state of the parser is XMLEvent.START_ELEMENT
     *
     * @return True if element is empty. (i.e. It matches
     *          production [44].
     */
    // fElementQName will have the details of element just read..
    // fAttributes will have the details of all the attributes.
    protected boolean scanStartElement()
    throws IOException, XNIException {

        if (DEBUG_START_END_ELEMENT) System.out.println( this.getClass().toString() + ">>> scanStartElement()");
        //when skipping is true and no more elements should be added
        if(fSkip && !fAdd){
            //get the stored element -- if everything goes right this should match the
            //token in the buffer

            QName name = fElementStack.getNext();

            if(DEBUG_SKIP_ALGORITHM){
                System.out.println("Trying to skip String = " + name.rawname);
            }

            //Be conservative -- if skipping fails -- stop.
            fSkip = fEntityScanner.skipString(name.rawname);

            if(fSkip){
                if(DEBUG_SKIP_ALGORITHM){
                    System.out.println("Element SUCESSFULLY skipped = " + name.rawname);
                }
                fElementStack.push();
                fElementQName = name;
            }else{
                //if skipping fails reposition the stack or fallback to normal way of processing
                fElementStack.reposition();
                if(DEBUG_SKIP_ALGORITHM){
                    System.out.println("Element was NOT skipped, REPOSITIONING stack" );
                }
            }
        }

        //we are still at the stage of adding elements
        //the elements were not matched or
        //fSkip is not set to true
        if(!fSkip || fAdd){
            //get the next element from the stack
            fElementQName = fElementStack.nextElement();
            // name
            if (fNamespaces) {
                fEntityScanner.scanQName(fElementQName, NameType.ELEMENTSTART);
            } else {
                String name = fEntityScanner.scanName(NameType.ELEMENTSTART);
                fElementQName.setValues(null, name, name, null);
            }

            if(DEBUG)System.out.println("Element scanned in start element is " + fElementQName.toString());
            if(DEBUG_SKIP_ALGORITHM){
                if(fAdd){
                    System.out.println("Elements are being ADDED -- elemet added is = " + fElementQName.rawname + " at count = " + fElementStack.fCount);
                }
            }

        }

        //when the elements are being added , we need to check if we are set for skipping the elements
        if(fAdd){
            //this sets the value of fAdd variable
            fElementStack.matchElement(fElementQName);
        }


        //xxx: We dont need another pointer, fCurrentElement, we can use fElementQName
        fCurrentElement = fElementQName;

        String rawname = fElementQName.rawname;

        fEmptyElement = false;

        fAttributes.removeAllAttributes();

        checkDepth(rawname);
        if(!seekCloseOfStartTag()){
            fReadingAttributes = true;
            fAttributeCacheUsedCount =0;
            fStringBufferIndex =0;
            fAddDefaultAttr = true;
            do {
                scanAttribute(fAttributes);
                if (fSecurityManager != null && !fSecurityManager.isNoLimit(fElementAttributeLimit) &&
                        fAttributes.getLength() > fElementAttributeLimit){
                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                                 "ElementAttributeLimit",
                                                 new Object[]{rawname, fElementAttributeLimit },
                                                 XMLErrorReporter.SEVERITY_FATAL_ERROR );
                }

            } while (!seekCloseOfStartTag());
            fReadingAttributes=false;
        }

        if (fEmptyElement) {
            //decrease the markup depth..
            fMarkupDepth--;

            // check that this element was opened in the same entity
            if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
                reportFatalError("ElementEntityMismatch",
                        new Object[]{fCurrentElement.rawname});
            }
            // call handler
            if (fDocumentHandler != null) {
                fDocumentHandler.emptyElement(fElementQName, fAttributes, null);
            }

            //We should not be popping out the context here in endELement becaause the namespace context is still
            //valid when parser is at the endElement state.
            //if (fNamespaces) {
            //  fNamespaceContext.popContext();
            //}

            //pop the element off the stack..
            fElementStack.popElement();

        } else {

            if(dtdGrammarUtil != null)
                dtdGrammarUtil.startElement(fElementQName, fAttributes);
            if(fDocumentHandler != null){
                //complete element and attributes are traversed in this function so we can send a callback
                //here.
                //<strong>we shouldn't be sending callback in scanDocument()</strong>
                fDocumentHandler.startElement(fElementQName, fAttributes, null);
            }
        }


        if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() + "<<< scanStartElement(): "+fEmptyElement);
        return fEmptyElement;

    } // scanStartElement():boolean

    /**
     * Looks for the close of start tag, i.e. if it finds '>' or '/>'
     * Characters are consumed.
     */
    protected boolean seekCloseOfStartTag() throws IOException, XNIException {
        // spaces
        boolean sawSpace = fEntityScanner.skipSpaces();

        // end tag?
        final int c = fEntityScanner.peekChar();
        if (c == '>') {
            fEntityScanner.scanChar(null);
            return true;
        } else if (c == '/') {
            fEntityScanner.scanChar(null);
            if (!fEntityScanner.skipChar('>', NameType.ELEMENTEND)) {
                reportFatalError("ElementUnterminated",
                        new Object[]{fElementQName.rawname});
            }
            fEmptyElement = true;
            return true;
        } else if (!isValidNameStartChar(c) || !sawSpace) {
            // Second chance. Check if this character is a high
            // surrogate of a valid name start character.
            if (!isValidNameStartHighSurrogate(c) || !sawSpace) {
                reportFatalError("ElementUnterminated",
                        new Object[]{fElementQName.rawname});
            }
        }

        return false;
    }

    public boolean hasAttributes(){
        return fAttributes.getLength() > 0 ? true : false ;
    }


    /**
     * Scans an attribute.
     * <p>
     * <pre>
     * [41] Attribute ::= Name Eq AttValue
     * </pre>
     * <p>
     * <strong>Note:</strong> This method assumes that the next
     * character on the stream is the first character of the attribute
     * name.
     * <p>
     * <strong>Note:</strong> This method uses the fAttributeQName and
     * fQName variables. The contents of these variables will be
     * destroyed.
     *
     * @param attributes The attributes list for the scanned attribute.
     */

    /**
     * protected void scanAttribute(AttributeIteratorImpl attributes)
     * throws IOException, XNIException {
     * if (DEBUG_START_END_ELEMENT) System.out.println(">>> scanAttribute()");
     *
     *
     * // name
     * if (fNamespaces) {
     * fEntityScanner.scanQName(fAttributeQName);
     * }
     * else {
     * String name = fEntityScanner.scanName();
     * fAttributeQName.setValues(null, name, name, null);
     * }
     *
     * // equals
     * fEntityScanner.skipSpaces();
     * if (!fEntityScanner.skipChar('=')) {
     * reportFatalError("EqRequiredInAttribute",
     * new Object[]{fAttributeQName.rawname});
     * }
     * fEntityScanner.skipSpaces();
     *
     *
     * // content
     * int oldLen = attributes.getLength();
     */
    /**xxx there is one check of duplicate attribute that has been removed.
     * attributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, null);
     *
     * // WFC: Unique Att Spec
     * if (oldLen == attributes.getLength()) {
     * reportFatalError("AttributeNotUnique",
     * new Object[]{fCurrentElement.rawname,
     * fAttributeQName.rawname});
     * }
     */

    /*
        //REVISIT: one more case needs to be included: external PE and standalone is no
        boolean isVC =  fHasExternalDTD && !fStandalone;
        scanAttributeValue(fTempString, fTempString2,
                           fAttributeQName.rawname, attributes,
                           oldLen, isVC);

        //attributes.setValue(oldLen, fTempString.toString());
        //attributes.setNonNormalizedValue(oldLen, fTempString2.toString());
        //attributes.setSpecified(oldLen, true);

        AttributeImpl attribute = new AttributeImpl(fAttributeQName.prefix,fAttributeQName.localpart,fAttributeQName.uri,fTempString.toString(),fTempString2.toString(),XMLSymbols.fCDATASymbol,true);
        fAttributes.addAttribute(attribute);
        if (DEBUG_START_END_ELEMENT) System.out.println("<<< scanAttribute()");
    } // scanAttribute(XMLAttributes)

     */

    /** return the attribute iterator implementation */
    public XMLAttributesIteratorImpl getAttributeIterator(){
        if(dtdGrammarUtil != null && fAddDefaultAttr){
            dtdGrammarUtil.addDTDDefaultAttrs(fElementQName,fAttributes);
            fAddDefaultAttr = false;
        }
        return fAttributes;
    }

    /** return if standalone is set */
    public boolean standaloneSet(){
        return fStandaloneSet;
    }
    /** return if the doucment is standalone */
    public boolean isStandAlone(){
        return fStandalone ;
    }
    /**
     * Scans an attribute name value pair.
     * <p>
     * <pre>
     * [41] Attribute ::= Name Eq AttValue
     * </pre>
     * <p>
     * <strong>Note:</strong> This method assumes that the next
     * character on the stream is the first character of the attribute
     * name.
     * <p>
     * <strong>Note:</strong> This method uses the fAttributeQName and
     * fQName variables. The contents of these variables will be
     * destroyed.
     *
     * @param attributes The attributes list for the scanned attribute.
     */

    protected void scanAttribute(XMLAttributes attributes)
    throws IOException, XNIException {
        if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +">>> scanAttribute()");

        // name
        if (fNamespaces) {
            fEntityScanner.scanQName(fAttributeQName, NameType.ATTRIBUTENAME);
        } else {
            String name = fEntityScanner.scanName(NameType.ATTRIBUTENAME);
            fAttributeQName.setValues(null, name, name, null);
        }

        // equals
        fEntityScanner.skipSpaces();
        if (!fEntityScanner.skipChar('=', NameType.ATTRIBUTE)) {
            reportFatalError("EqRequiredInAttribute",
                new Object[] {fCurrentElement.rawname, fAttributeQName.rawname});
        }
        fEntityScanner.skipSpaces();

        int attIndex = 0 ;
        //REVISIT: one more case needs to be included: external PE and standalone is no
        boolean isVC =  fHasExternalDTD && !fStandalone;
        //fTempString would store attribute value
        ///fTempString2 would store attribute non-normalized value

        //this function doesn't use 'attIndex'. We are adding the attribute later
        //after we have figured out that current attribute is not namespace declaration
        //since scanAttributeValue doesn't use attIndex parameter therefore we
        //can safely add the attribute later..
        XMLString tmpStr = getString();

        scanAttributeValue(tmpStr, fTempString2, fAttributeQName.rawname, attributes,
                attIndex, isVC, fCurrentElement.rawname, false);

        // content
        int oldLen = attributes.getLength();
        //if the attribute name already exists.. new value is replaced with old value
        attIndex = attributes.addAttribute(fAttributeQName, XMLSymbols.fCDATASymbol, null);

        // WFC: Unique Att Spec
        //attributes count will be same if the current attribute  name already exists for this element name.
        //this means there are two duplicate attributes.
        if (oldLen == attributes.getLength()) {
            reportFatalError("AttributeNotUnique",
                    new Object[]{fCurrentElement.rawname,
                            fAttributeQName.rawname});
        }

        //tmpString contains attribute value
        //we are passing null as the attribute value
        attributes.setValue(attIndex, null, tmpStr);

        ///xxx: nonNormalizedValue is not being set as it is not required by SAX & DOM
        //attributes.setNonNormalizedValue(oldLen, fTempString2.toString());
        attributes.setSpecified(attIndex, true);

        if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +"<<< scanAttribute()");

    } // scanAttribute(XMLAttributes)

    /**
     * Scans element content.
     *
     * @return Returns the next character on the stream.
     */
    //CHANGED:
    //EARLIER: scanContent()
    //NOW: scanContent(XMLStringBuffer)
    //It makes things easy if this functions takes XMLStringBuffer as parameter..
    //this function appends the data to the buffer.
    protected int scanContent(XMLStringBuffer content) throws IOException, XNIException {
        //set the fTempString length to 0 before passing it on to scanContent
        //scanContent sets the correct co-ordinates as per the content read
        fTempString.length = 0;
        int c = fEntityScanner.scanContent(fTempString);
        content.append(fTempString);
        fTempString.length = 0;
        if (c == '\r') {
            // happens when there is the character reference &#13;
            //xxx: We know the next chracter.. we should just skip it and add ']' directlry
            fEntityScanner.scanChar(null);
            content.append((char)c);
            c = -1;
        } else if (c == ']') {
            //fStringBuffer.clear();
            //xxx: We know the next chracter.. we should just skip it and add ']' directlry
            content.append((char)fEntityScanner.scanChar(null));
            // remember where we are in case we get an endEntity before we
            // could flush the buffer out - this happens when we're parsing an
            // entity which ends with a ]
            fInScanContent = true;
            //
            // We work on a single character basis to handle cases such as:
            // ']]]>' which we might otherwise miss.
            //
            if (fEntityScanner.skipChar(']', null)) {
                content.append(']');
                while (fEntityScanner.skipChar(']', null)) {
                    content.append(']');
                }
                if (fEntityScanner.skipChar('>', null)) {
                    reportFatalError("CDEndInContent", null);
                }
            }
            fInScanContent = false;
            c = -1;
        }
        if (fDocumentHandler != null && content.length > 0) {
            //fDocumentHandler.characters(content, null);
        }
        return c;

    } // scanContent():int


    /**
     * Scans a CDATA section.
     * <p>
     * <strong>Note:</strong> This method uses the fTempString and
     * fStringBuffer variables.
     *
     * @param complete True if the CDATA section is to be scanned
     *                 completely.
     *
     * @return True if CDATA is completely scanned.
     */
    //CHANGED:
    protected boolean scanCDATASection(XMLStringBuffer contentBuffer, boolean complete)
    throws IOException, XNIException {

        // call handler
        if (fDocumentHandler != null) {
            //fDocumentHandler.startCDATA(null);
        }

        while (true) {
            //scanData will fill the contentBuffer
            if (!fEntityScanner.scanData("]]>", contentBuffer)) {
                break ;
                /** We dont need all this code if we pass ']]>' as delimeter..
                 * int brackets = 2;
                 * while (fEntityScanner.skipChar(']')) {
                 * brackets++;
                 * }
                 *
                 * //When we find more than 2 square brackets
                 * if (fDocumentHandler != null && brackets > 2) {
                 * //we dont need to clear the buffer..
                 * //contentBuffer.clear();
                 * for (int i = 2; i < brackets; i++) {
                 * contentBuffer.append(']');
                 * }
                 * fDocumentHandler.characters(contentBuffer, null);
                 * }
                 *
                 * if (fEntityScanner.skipChar('>')) {
                 * break;
                 * }
                 * if (fDocumentHandler != null) {
                 * //we dont need to clear the buffer now..
                 * //contentBuffer.clear();
                 * contentBuffer.append("]]");
                 * fDocumentHandler.characters(contentBuffer, null);
                 * }
                 **/
            } else {
                int c = fEntityScanner.peekChar();
                if (c != -1 && isInvalidLiteral(c)) {
                    if (XMLChar.isHighSurrogate(c)) {
                        //contentBuffer.clear();
                        //scan surrogates if any....
                        scanSurrogates(contentBuffer);
                    } else {
                        reportFatalError("InvalidCharInCDSect",
                                new Object[]{Integer.toString(c,16)});
                                fEntityScanner.scanChar(null);
                    }
                }
                //by this time we have also read surrogate contents if any...
                if (fDocumentHandler != null) {
                    //fDocumentHandler.characters(contentBuffer, null);
                }
            }
        }
        fMarkupDepth--;

        if (fDocumentHandler != null && contentBuffer.length > 0) {
            //fDocumentHandler.characters(contentBuffer, null);
        }

        // call handler
        if (fDocumentHandler != null) {
            //fDocumentHandler.endCDATA(null);
        }

        return true;

    } // scanCDATASection(XMLStringBuffer, boolean):boolean

    /**
     * Scans an end element.
     * <p>
     * <pre>
     * [42] ETag ::= '&lt;/' Name S? '>'
     * </pre>
     * <p>
     * <strong>Note:</strong> This method uses the fElementQName variable.
     * The contents of this variable will be destroyed. The caller should
     * copy the needed information out of this variable before calling
     * this method.
     *
     * @return The element depth.
     */
    protected int scanEndElement() throws IOException, XNIException {
        if (DEBUG_START_END_ELEMENT) System.out.println(this.getClass().toString() +">>> scanEndElement()");

        // pop context
        QName endElementName = fElementStack.popElement();

        String rawname = endElementName.rawname;
        if(DEBUG)System.out.println("endElementName = " + endElementName.toString());
        // Take advantage of the fact that next string _should_ be "fElementQName.rawName",
        //In scanners most of the time is consumed on checks done for XML characters, we can
        // optimize on it and avoid the checks done for endElement,
        //we will also avoid symbol table lookup - neeraj.bajaj@sun.com

        // this should work both for namespace processing true or false...

        //REVISIT: if the string is not the same as expected.. we need to do better error handling..
        //We can skip this for now... In any case if the string doesn't match -- document is not well formed.

        if (!fEntityScanner.skipString(endElementName.rawname)) {
             reportFatalError("ETagRequired", new Object[]{rawname});
        }

        // end
        fEntityScanner.skipSpaces();
        if (!fEntityScanner.skipChar('>', NameType.ELEMENTEND)) {
            reportFatalError("ETagUnterminated",
                    new Object[]{rawname});
        }
        fMarkupDepth--;

        //we have increased the depth for two markup "<" characters
        fMarkupDepth--;

        // check that this element was opened in the same entity
        if (fMarkupDepth < fEntityStack[fEntityDepth - 1]) {
            reportFatalError("ElementEntityMismatch",
                    new Object[]{rawname});
        }

        //We should not be popping out the context here in endELement becaause the namespace context is still
        //valid when parser is at the endElement state.

        //if (fNamespaces) {
        //  fNamespaceContext.popContext();
        //}

        // call handler
        if (fDocumentHandler != null ) {
            //end element is scanned in this function so we can send a callback
            //here.
            //<strong>we shouldn't be sending callback in scanDocument()</strong>

            fDocumentHandler.endElement(endElementName, null);
        }
        if(dtdGrammarUtil != null)
            dtdGrammarUtil.endElement(endElementName);

        return fMarkupDepth;

    } // scanEndElement():int

    /**
     * Scans a character reference.
     * <p>
     * <pre>
     * [66] CharRef ::= '&#' [0-9]+ ';' | '&#x' [0-9a-fA-F]+ ';'
     * </pre>
     */
    protected void scanCharReference()
    throws IOException, XNIException {

        fStringBuffer2.clear();
        int ch = scanCharReferenceValue(fStringBuffer2, null);
        fMarkupDepth--;
        if (ch != -1) {
            // call handler

            if (fDocumentHandler != null) {
                if (fNotifyCharRefs) {
                    fDocumentHandler.startGeneralEntity(fCharRefLiteral, null, null, null);
                }
                Augmentations augs = null;
                if (fValidation && ch <= 0x20) {
                    if (fTempAugmentations != null) {
                        fTempAugmentations.removeAllItems();
                    }
                    else {
                        fTempAugmentations = new AugmentationsImpl();
                    }
                    augs = fTempAugmentations;
                    augs.putItem(Constants.CHAR_REF_PROBABLE_WS, Boolean.TRUE);
                }
                //xxx: How do we deal with this - how to return charReferenceValues
                //now this is being commented because this is taken care in scanDocument()
                //fDocumentHandler.characters(fStringBuffer2, null);
                if (fNotifyCharRefs) {
                    fDocumentHandler.endGeneralEntity(fCharRefLiteral, null);
                }
            }
        }

    } // scanCharReference()


    /**
     * Scans an entity reference.
     *
     * @return returns true if the new entity is started. If it was built-in entity
     *         'false' is returned.
     * @throws IOException  Thrown if i/o error occurs.
     * @throws XNIException Thrown if handler throws exception upon
     *                      notification.
     */
    protected void scanEntityReference(XMLStringBuffer content) throws IOException, XNIException {
        String name = fEntityScanner.scanName(NameType.REFERENCE);
        if (name == null) {
            reportFatalError("NameRequiredInReference", null);
            return;
        }
        if (!fEntityScanner.skipChar(';', NameType.REFERENCE)) {
            reportFatalError("SemicolonRequiredInReference", new Object []{name});
        }
        if (fEntityStore.isUnparsedEntity(name)) {
            reportFatalError("ReferenceToUnparsedEntity", new Object[]{name});
        }
        fMarkupDepth--;
        fCurrentEntityName = name;

        // handle built-in entities
        if (name == fAmpSymbol) {
            handleCharacter('&', fAmpSymbol, content);
            fScannerState = SCANNER_STATE_BUILT_IN_REFS;
            return ;
        } else if (name == fLtSymbol) {
            handleCharacter('<', fLtSymbol, content);
            fScannerState = SCANNER_STATE_BUILT_IN_REFS;
            return ;
        } else if (name == fGtSymbol) {
            handleCharacter('>', fGtSymbol, content);
            fScannerState = SCANNER_STATE_BUILT_IN_REFS;
            return ;
        } else if (name == fQuotSymbol) {
            handleCharacter('"', fQuotSymbol, content);
            fScannerState = SCANNER_STATE_BUILT_IN_REFS;
            return ;
        } else if (name == fAposSymbol) {
            handleCharacter('\'', fAposSymbol, content);
            fScannerState = SCANNER_STATE_BUILT_IN_REFS;
            return ;
        }

        //1. if the entity is external and support to external entities is not required
        // 2. or entities should not be replaced
        //3. or if it is built in entity reference.
        boolean isEE = fEntityStore.isExternalEntity(name);
        if((isEE && !fSupportExternalEntities) || (!isEE && !fReplaceEntityReferences) || foundBuiltInRefs){
            fScannerState = SCANNER_STATE_REFERENCE;
            return ;
        }
        // start general entity
        if (!fEntityStore.isDeclaredEntity(name)) {
            //SUPPORT_DTD=false && ReplaceEntityReferences should throw exception
            if (!fSupportDTD && fReplaceEntityReferences) {
                reportFatalError("EntityNotDeclared", new Object[]{name});
                return;
            }
            //REVISIT: one more case needs to be included: external PE and standalone is no
            if ( fHasExternalDTD && !fStandalone) {
                if (fValidation)
                    fErrorReporter.reportError(fEntityScanner, XMLMessageFormatter.XML_DOMAIN,"EntityNotDeclared",
                            new Object[]{name}, XMLErrorReporter.SEVERITY_ERROR);
            } else
                reportFatalError("EntityNotDeclared", new Object[]{name});
        }
        //we are starting the entity even if the entity was not declared
        //if that was the case it its taken care in XMLEntityManager.startEntity()
        //we immediately call the endEntity. Application gets to know if there was
        //any entity that was not declared.
        fEntityManager.startEntity(true, name, false);
        //set the scaner state to content.. parser will automatically revive itself at any point of time.
        //setScannerState(SCANNER_STATE_CONTENT);
        //return true ;
    } // scanEntityReference()

    // utility methods

    /**
     * Check if the depth exceeds the maxElementDepth limit
     * @param elementName name of the current element
     */
    void checkDepth(String elementName) {
        fLimitAnalyzer.addValue(Limit.MAX_ELEMENT_DEPTH_LIMIT, elementName, fElementStack.fDepth);
        if (fSecurityManager.isOverLimit(Limit.MAX_ELEMENT_DEPTH_LIMIT,fLimitAnalyzer)) {
            fSecurityManager.debugPrint(fLimitAnalyzer);
            reportFatalError("MaxElementDepthLimit", new Object[]{elementName,
                fLimitAnalyzer.getTotalValue(Limit.MAX_ELEMENT_DEPTH_LIMIT),
                fSecurityManager.getLimit(Limit.MAX_ELEMENT_DEPTH_LIMIT),
                "maxElementDepth"});
        }
    }

    /**
     * Calls document handler with a single character resulting from
     * built-in entity resolution.
     *
     * @param c
     * @param entity built-in name
     * @param XMLStringBuffer append the character to buffer
     *
     * we really dont need to call this function -- this function is only required when
     * we integrate with rest of Xerces2. SO maintaining the current behavior and still
     * calling this function to hanlde built-in entity reference.
     *
     */
    private void handleCharacter(char c, String entity, XMLStringBuffer content) throws XNIException {
        foundBuiltInRefs = true;
        checkEntityLimit(false, fEntityScanner.fCurrentEntity.name, 1);
        content.append(c);
        if (fDocumentHandler != null) {
            fSingleChar[0] = c;
            if (fNotifyBuiltInRefs) {
                fDocumentHandler.startGeneralEntity(entity, null, null, null);
            }
            fTempString.setValues(fSingleChar, 0, 1);
            //fDocumentHandler.characters(fTempString, null);

            if (fNotifyBuiltInRefs) {
                fDocumentHandler.endGeneralEntity(entity, null);
            }
        }
    } // handleCharacter(char)

    // helper methods

    /**
     * Sets the scanner state.
     *
     * @param state The new scanner state.
     */
    protected final void setScannerState(int state) {

        fScannerState = state;
        if (DEBUG_SCANNER_STATE) {
            System.out.print("### setScannerState: ");
            //System.out.print(fScannerState);
            System.out.print(getScannerStateName(state));
            System.out.println();
        }

    } // setScannerState(int)


    /**
     * Sets the Driver.
     *
     * @param Driver The new Driver.
     */
    protected final void setDriver(Driver driver) {
        fDriver = driver;
        if (DEBUG_DISPATCHER) {
            System.out.print("%%% setDriver: ");
            System.out.print(getDriverName(driver));
            System.out.println();
        }
    }

    //
    // Private methods
    //

    /** Returns the scanner state name. */
    protected String getScannerStateName(int state) {

        switch (state) {
            case SCANNER_STATE_DOCTYPE: return "SCANNER_STATE_DOCTYPE";
            case SCANNER_STATE_ROOT_ELEMENT: return "SCANNER_STATE_ROOT_ELEMENT";
            case SCANNER_STATE_START_OF_MARKUP: return "SCANNER_STATE_START_OF_MARKUP";
            case SCANNER_STATE_COMMENT: return "SCANNER_STATE_COMMENT";
            case SCANNER_STATE_PI: return "SCANNER_STATE_PI";
            case SCANNER_STATE_CONTENT: return "SCANNER_STATE_CONTENT";
            case SCANNER_STATE_REFERENCE: return "SCANNER_STATE_REFERENCE";
            case SCANNER_STATE_END_OF_INPUT: return "SCANNER_STATE_END_OF_INPUT";
            case SCANNER_STATE_TERMINATED: return "SCANNER_STATE_TERMINATED";
            case SCANNER_STATE_CDATA: return "SCANNER_STATE_CDATA";
            case SCANNER_STATE_TEXT_DECL: return "SCANNER_STATE_TEXT_DECL";
            case SCANNER_STATE_ATTRIBUTE: return "SCANNER_STATE_ATTRIBUTE";
            case SCANNER_STATE_ATTRIBUTE_VALUE: return "SCANNER_STATE_ATTRIBUTE_VALUE";
            case SCANNER_STATE_START_ELEMENT_TAG: return "SCANNER_STATE_START_ELEMENT_TAG";
            case SCANNER_STATE_END_ELEMENT_TAG: return "SCANNER_STATE_END_ELEMENT_TAG";
            case SCANNER_STATE_CHARACTER_DATA: return "SCANNER_STATE_CHARACTER_DATA" ;
        }

        return "??? ("+state+')';

    } // getScannerStateName(int):String
    public String getEntityName(){
        //return the cached name
        return fCurrentEntityName;
    }

    /** Returns the driver name. */
    public String getDriverName(Driver driver) {

        if (DEBUG_DISPATCHER) {
            if (driver != null) {
                String name = driver.getClass().getName();
                int index = name.lastIndexOf('.');
                if (index != -1) {
                    name = name.substring(index + 1);
                    index = name.lastIndexOf('$');
                    if (index != -1) {
                        name = name.substring(index + 1);
                    }
                }
                return name;
            }
        }
        return "null";

    } // getDriverName():String

    /**
     * Check the protocol used in the systemId against allowed protocols
     *
     * @param systemId the Id of the URI
     * @param allowedProtocols a list of allowed protocols separated by comma
     * @return the name of the protocol if rejected, null otherwise
     */
    String checkAccess(String systemId, String allowedProtocols) throws IOException {
        String baseSystemId = fEntityScanner.getBaseSystemId();
        String expandedSystemId = XMLEntityManager.expandSystemId(systemId, baseSystemId, fStrictURI);
        return SecuritySupport.checkAccess(expandedSystemId, allowedProtocols, Constants.ACCESS_EXTERNAL_ALL);
    }

    //
    // Classes
    //

    /**
     * @author Neeraj Bajaj, Sun Microsystems.
     */
    protected static final class Element {

        //
        // Data
        //

        /** Symbol. */
        public QName qname;

        //raw name stored as characters
        public char[] fRawname;

        /** The next Element entry. */
        public Element next;

        //
        // Constructors
        //

        /**
         * Constructs a new Element from the given QName and next Element
         * reference.
         */
        public Element(QName qname, Element next) {
            this.qname.setValues(qname);
            this.fRawname = qname.rawname.toCharArray();
            this.next = next;
        }

    } // class Element

    /**
     * Element stack.
     *
     * @author Neeraj Bajaj, Sun Microsystems.
     */
    protected class ElementStack2 {

        //
        // Data
        //

        /** The stack data. */
        protected QName [] fQName = new QName[20];

        //Element depth
        protected int fDepth;
        //total number of elements
        protected int fCount;
        //current position
        protected int fPosition;
        //Mark refers to the position
        protected int fMark;

        protected int fLastDepth ;

        //
        // Constructors
        //

        /** Default constructor. */
        public ElementStack2() {
            for (int i = 0; i < fQName.length; i++) {
                fQName[i] = new QName();
            }
            fMark = fPosition = 1;
        } // <init>()

        public void resize(){
            /**
             * int length = fElements.length;
             * Element [] temp = new Element[length * 2];
             * System.arraycopy(fElements, 0, temp, 0, length);
             * fElements = temp;
             */
            //resize QNames
            int oldLength = fQName.length;
            QName [] tmp = new QName[oldLength * 2];
            System.arraycopy(fQName, 0, tmp, 0, oldLength);
            fQName = tmp;

            for (int i = oldLength; i < fQName.length; i++) {
                fQName[i] = new QName();
            }

        }


        //
        // Public methods
        //

        /** Check if the element scanned during the start element
         *matches the stored element.
         *
         *@return true if the match suceeds.
         */
        public boolean matchElement(QName element) {
            //last depth is the depth when last elemnt was pushed
            //if last depth is greater than current depth
            if(DEBUG_SKIP_ALGORITHM){
                System.out.println("fLastDepth = " + fLastDepth);
                System.out.println("fDepth = " + fDepth);
            }
            boolean match = false;
            if(fLastDepth > fDepth && fDepth <= 2){
                if(DEBUG_SKIP_ALGORITHM){
                    System.out.println("Checking if the elements match " + element.rawname + " , " + fQName[fDepth].rawname);
                }
                if(element.rawname == fQName[fDepth].rawname){
                    fAdd = false;
                    //mark this position
                    //decrease the depth by 1 as arrays are 0 based
                    fMark = fDepth - 1;
                    //we found the match and from next element skipping will start, add 1
                    fPosition = fMark + 1 ;
                    match = true;
                    //Once we get match decrease the count -- this was increased by nextElement()
                    --fCount;
                    if(DEBUG_SKIP_ALGORITHM){
                        System.out.println("fAdd FALSE -- NOW ELEMENT SHOULD NOT BE ADDED");
                        System.out.println("fMark = " + fMark);
                        System.out.println("fPosition = " + fPosition);
                        System.out.println("fDepth = " + fDepth);
                        System.out.println("fCount = " + fCount);
                    }
                }else{
                    fAdd = true;
                    if(DEBUG_SKIP_ALGORITHM)System.out.println("fAdd is " + fAdd);
                }
            }
            //store the last depth
            fLastDepth = fDepth++;
            return match;
        } // pushElement(QName):QName

        /**
         * This function doesn't increase depth. The function in this function is
         *broken down into two functions for efficiency. <@see>matchElement</see>.
         * This function just returns the pointer to the object and its values are set.
         *
         *@return QName reference to the next element in the list
         */
        public QName nextElement() {

            //if number of elements becomes equal to the length of array -- stop the skipping
            if (fCount == fQName.length) {
                fShouldSkip = false;
                fAdd = false;
                if(DEBUG_SKIP_ALGORITHM)System.out.println("SKIPPING STOPPED, fShouldSkip = " + fShouldSkip);
                //xxx: this is not correct, we are returning the last element
                //this wont make any difference since flag has been set to 'false'
                return fQName[--fCount];
            }
            if(DEBUG_SKIP_ALGORITHM){
                System.out.println("fCount = " + fCount);
            }
            return fQName[fCount++];

        }

        /** Note that this function is considerably different than nextElement()
         * This function just returns the previously stored elements
         */
        public QName getNext(){
            //when position reaches number of elements in the list..
            //set the position back to mark,  making it a circular linked list.
            if(fPosition == fCount){
                fPosition = fMark;
            }
            return fQName[fPosition++];
        }

        /** returns the current depth
         */
        public int popElement(){
            return fDepth--;
        }


        /** Clears the stack without throwing away existing QName objects. */
        public void clear() {
            fLastDepth = 0;
            fDepth = 0;
            fCount = 0 ;
            fPosition = fMark = 1;
        } // clear()

    } // class ElementStack

    /**
     * Element stack. This stack operates without synchronization, error
     * checking, and it re-uses objects instead of throwing popped items
     * away.
     *
     * @author Andy Clark, IBM
     */
    protected class ElementStack {

        //
        // Data
        //

        /** The stack data. */
        protected QName[] fElements;
        protected int []  fInt = new int[20];


        //Element depth
        protected int fDepth;
        //total number of elements
        protected int fCount;
        //current position
        protected int fPosition;
        //Mark refers to the position
        protected int fMark;

        protected int fLastDepth ;

        //
        // Constructors
        //

        /** Default constructor. */
        public ElementStack() {
            fElements = new QName[20];
            for (int i = 0; i < fElements.length; i++) {
                fElements[i] = new QName();
            }
        } // <init>()

        //
        // Public methods
        //

        /**
         * Pushes an element on the stack.
         * <p>
         * <strong>Note:</strong> The QName values are copied into the
         * stack. In other words, the caller does <em>not</em> orphan
         * the element to the stack. Also, the QName object returned
         * is <em>not</em> orphaned to the caller. It should be
         * considered read-only.
         *
         * @param element The element to push onto the stack.
         *
         * @return Returns the actual QName object that stores the
         */
        //XXX: THIS FUNCTION IS NOT USED
        public QName pushElement(QName element) {
            if (fDepth == fElements.length) {
                QName[] array = new QName[fElements.length * 2];
                System.arraycopy(fElements, 0, array, 0, fDepth);
                fElements = array;
                for (int i = fDepth; i < fElements.length; i++) {
                    fElements[i] = new QName();
                }
            }
            fElements[fDepth].setValues(element);
            return fElements[fDepth++];
        } // pushElement(QName):QName


        /** Note that this function is considerably different than nextElement()
         * This function just returns the previously stored elements
         */
        public QName getNext(){
            //when position reaches number of elements in the list..
            //set the position back to mark,  making it a circular linked list.
            if(fPosition == fCount){
                fPosition = fMark;
            }
            //store the position of last opened tag at particular depth
            //fInt[++fDepth] = fPosition;
            if(DEBUG_SKIP_ALGORITHM){
                System.out.println("Element at fPosition = " + fPosition + " is " + fElements[fPosition].rawname);
            }
            //return fElements[fPosition++];
            return fElements[fPosition];
        }

        /** This function should be called only when element was skipped sucessfully.
         * 1. Increase the depth - because element was sucessfully skipped.
         *2. Store the position of the element token in array  "last opened tag" at depth.
         *3. increase the position counter so as to point to the next element in the array
         */
        public void push(){

            fInt[++fDepth] = fPosition++;
        }

        /** Check if the element scanned during the start element
         *matches the stored element.
         *
         *@return true if the match suceeds.
         */
        public boolean matchElement(QName element) {
            //last depth is the depth when last elemnt was pushed
            //if last depth is greater than current depth
            //if(DEBUG_SKIP_ALGORITHM){
            //   System.out.println("Check if the element " + element.rawname + " matches");
            //  System.out.println("fLastDepth = " + fLastDepth);
            // System.out.println("fDepth = " + fDepth);
            //}
            boolean match = false;
            if(fLastDepth > fDepth && fDepth <= 3){
                if(DEBUG_SKIP_ALGORITHM){
                    System.out.println("----------ENTERED THE LOOP WHERE WE CHECK FOR MATCHING OF ELMENT-----");
                    System.out.println("Depth = " + fDepth + " Checking if INCOMING element " + element.rawname + " match STORED ELEMENT " + fElements[fDepth - 1].rawname);
                }
                if(element.rawname == fElements[fDepth - 1].rawname){
                    fAdd = false;
                    //mark this position
                    //decrease the depth by 1 as arrays are 0 based
                    fMark = fDepth - 1;
                    //we found the match
                    fPosition = fMark;
                    match = true;
                    //Once we get match decrease the count -- this was increased by nextElement()
                    --fCount;
                    if(DEBUG_SKIP_ALGORITHM){
                        System.out.println("NOW ELEMENT SHOULD NOT BE ADDED, fAdd is set to false");
                        System.out.println("fMark = " + fMark);
                        System.out.println("fPosition = " + fPosition);
                        System.out.println("fDepth = " + fDepth);
                        System.out.println("fCount = " + fCount);
                        System.out.println("---------MATCH SUCEEDED-----------------");
                        System.out.println("");
                    }
                }else{
                    fAdd = true;
                    if(DEBUG_SKIP_ALGORITHM)System.out.println("fAdd is " + fAdd);
                }
            }
            //store the position for the current depth
            //when we are adding the elements, when skipping
            //starts even then this should be tracked ie. when
            //calling getNext()
            if(match){
                //from next element skipping will start, add 1
                fInt[fDepth] = fPosition++;
            } else{
                if(DEBUG_SKIP_ALGORITHM){
                    System.out.println("At depth = " + fDepth + "array position is = " + (fCount - 1));
                }
                //sicne fInt[fDepth] contains pointer to the element array which are 0 based.
                fInt[fDepth] = fCount - 1;
            }

            //if number of elements becomes equal to the length of array -- stop the skipping
            //xxx: should we do "fCount == fInt.length"
            if (fCount == fElements.length) {
                fSkip = false;
                fAdd = false;
                //reposition the stack -- it seems to be too complex document and there is no symmerty in structure
                reposition();
                if(DEBUG_SKIP_ALGORITHM){
                    System.out.println("ALL THE ELMENTS IN ARRAY HAVE BEEN FILLED");
                    System.out.println("REPOSITIONING THE STACK");
                    System.out.println("-----------SKIPPING STOPPED----------");
                    System.out.println("");
                }
                return false;
            }
            if(DEBUG_SKIP_ALGORITHM){
                if(match){
                    System.out.println("Storing fPosition = " + fInt[fDepth] + " at fDepth = " + fDepth);
                }else{
                    System.out.println("Storing fCount = " + fInt[fDepth] + " at fDepth = " + fDepth);
                }
            }
            //store the last depth
            fLastDepth = fDepth;
            return match;
        } // matchElement(QName):QName


        /**
         * Returns the next element on the stack.
         *
         * @return Returns the actual QName object. Callee should
         * use this object to store the details of next element encountered.
         */
        public QName nextElement() {
            if(fSkip){
                fDepth++;
                //boundary checks are done in matchElement()
                return fElements[fCount++];
            } else if (fDepth == fElements.length) {
                QName[] array = new QName[fElements.length * 2];
                System.arraycopy(fElements, 0, array, 0, fDepth);
                fElements = array;
                for (int i = fDepth; i < fElements.length; i++) {
                    fElements[i] = new QName();
                }
            }

            return fElements[fDepth++];

        } // pushElement(QName):QName


        /**
         * Pops an element off of the stack by setting the values of
         * the specified QName.
         * <p>
         * <strong>Note:</strong> The object returned is <em>not</em>
         * orphaned to the caller. Therefore, the caller should consider
         * the object to be read-only.
         */
        public QName popElement() {
            //return the same object that was pushed -- this would avoid
            //setting the values for every end element.
            //STRONG: this object is read only -- this object reference shouldn't be stored.
            if(fSkip || fAdd ){
                if(DEBUG_SKIP_ALGORITHM){
                    System.out.println("POPPING Element, at position " + fInt[fDepth] + " element at that count is = " + fElements[fInt[fDepth]].rawname);
                    System.out.println("");
                }
                return fElements[fInt[fDepth--]];
            } else{
                if(DEBUG_SKIP_ALGORITHM){
                    System.out.println("Retrieveing element at depth = " + fDepth + " is " + fElements[fDepth].rawname );
                }
                return fElements[--fDepth] ;
            }
            //element.setValues(fElements[--fDepth]);
        } // popElement(QName)

        /** Reposition the stack. fInt [] contains all the opened tags at particular depth.
         * Transfer all the opened tags starting from depth '2' to the current depth and reposition them
         *as per the depth.
         */
        public void reposition(){
            for( int i = 2 ; i <= fDepth ; i++){
                fElements[i-1] = fElements[fInt[i]];
            }
            if(DEBUG_SKIP_ALGORITHM){
                for( int i = 0 ; i < fDepth ; i++){
                    System.out.println("fElements[" + i + "]" + " = " + fElements[i].rawname);
                }
            }
        }

        /** Clears the stack without throwing away existing QName objects. */
        public void clear() {
            fDepth = 0;
            fLastDepth = 0;
            fCount = 0 ;
            fPosition = fMark = 1;

        } // clear()

        /**
         * This function is as a result of optimization done for endElement --
         * we dont need to set the value for every end element encouterd.
         * For Well formedness checks we can have the same QName object that was pushed.
         * the values will be set only if application need to know about the endElement
         * -- neeraj.bajaj@sun.com
         */

        public QName getLastPoppedElement(){
            return fElements[fDepth];
        }
    } // class ElementStack

    /**
     * Drives the parser to the next state/event on the input. Parser is guaranteed
     * to stop at the next state/event.
     *
     * Internally XML document is divided into several states. Each state represents
     * a sections of XML document. When this functions returns normally, it has read
     * the section of XML document and returns the state corresponding to section of
     * document which has been read. For optimizations, a particular driver
     * can read ahead of the section of document (state returned) just read and
     * can maintain a different internal state.
     *
     *
     * @author Neeraj Bajaj, Sun Microsystems
     */
    protected interface Driver {


        /**
         * Drives the parser to the next state/event on the input. Parser is guaranteed
         * to stop at the next state/event.
         *
         * Internally XML document is divided into several states. Each state represents
         * a sections of XML document. When this functions returns normally, it has read
         * the section of XML document and returns the state corresponding to section of
         * document which has been read. For optimizations, a particular driver
         * can read ahead of the section of document (state returned) just read and
         * can maintain a different internal state.
         *
         * @return state representing the section of document just read.
         *
         * @throws IOException  Thrown on i/o error.
         * @throws XNIException Thrown on parse error.
         */

        public int next() throws IOException, XNIException;

    } // interface Driver

    /**
     * Driver to handle content scanning. This driver is capable of reading
     * the fragment of XML document. When it has finished reading fragment
     * of XML documents, it can pass the job of reading to another driver.
     *
     * This class has been modified as per the new design which is more suited to
     * efficiently build pull parser. Lot of performance improvements have been done and
     * the code has been added to support stax functionality/features.
     *
     * @author Neeraj Bajaj, Sun Microsystems
     *
     *
     * @author Andy Clark, IBM
     * @author Eric Ye, IBM
     */
    protected class FragmentContentDriver
            implements Driver {

        //
        // Driver methods
        //

        /**
         *  decides the appropriate state of the parser
         */
        private void startOfMarkup() throws IOException {
            fMarkupDepth++;
            final int ch = fEntityScanner.peekChar();

            if (isValidNameStartChar(ch) || isValidNameStartHighSurrogate(ch)) {
                setScannerState(SCANNER_STATE_START_ELEMENT_TAG);
            } else {
                switch(ch){
                    case '?' :{
                        setScannerState(SCANNER_STATE_PI);
                        fEntityScanner.skipChar(ch, null);
                        break;
                    }
                    case '!' :{
                        fEntityScanner.skipChar(ch, null);
                        if (fEntityScanner.skipChar('-', null)) {
                            if (!fEntityScanner.skipChar('-', NameType.COMMENT)) {
                                reportFatalError("InvalidCommentStart",
                                        null);
                            }
                            setScannerState(SCANNER_STATE_COMMENT);
                        } else if (fEntityScanner.skipString(cdata)) {
                            setScannerState(SCANNER_STATE_CDATA );
                        } else if (!scanForDoctypeHook()) {
                            reportFatalError("MarkupNotRecognizedInContent",
                                    null);
                        }
                        break;
                    }
                    case '/' :{
                        setScannerState(SCANNER_STATE_END_ELEMENT_TAG);
                        fEntityScanner.skipChar(ch, NameType.ELEMENTEND);
                        break;
                    }
                    default :{
                        reportFatalError("MarkupNotRecognizedInContent", null);
                    }
                }
            }

        }//startOfMarkup

        private void startOfContent() throws IOException {
            if (fEntityScanner.skipChar('<', null)) {
                setScannerState(SCANNER_STATE_START_OF_MARKUP);
            } else if (fEntityScanner.skipChar('&', NameType.REFERENCE)) {
                setScannerState(SCANNER_STATE_REFERENCE) ; //XMLEvent.ENTITY_REFERENCE ); //SCANNER_STATE_REFERENCE
            } else {
                //element content is there..
                setScannerState(SCANNER_STATE_CHARACTER_DATA);
            }
        }//startOfContent


        /**
         *
         * SCANNER_STATE_CONTENT and SCANNER_STATE_START_OF_MARKUP are two super states of the parser.
         * At any point of time when in doubt over the current state of the parser, the state should be
         * set to SCANNER_STATE_CONTENT. Parser will automatically revive itself and will set state of
         * the parser to one of its sub state.
         * sub states are defined in the parser on the basis of different XML component like
         * SCANNER_STATE_ENTITY_REFERENCE , SCANNER_STATE_START_ELEMENT, SCANNER_STATE_CDATA etc..
         * These sub states help the parser to have fine control over the parsing. These are the
         * different milepost, parser stops at each sub state (milepost). Based on this state it is
         * decided if paresr needs to stop at next milepost ??
         *
         */
        public void decideSubState() throws IOException {
            while( fScannerState == SCANNER_STATE_CONTENT || fScannerState == SCANNER_STATE_START_OF_MARKUP){

                switch (fScannerState) {

                    case SCANNER_STATE_CONTENT: {
                        startOfContent() ;
                        break;
                    }

                    case SCANNER_STATE_START_OF_MARKUP: {
                        startOfMarkup() ;
                        break;
                    }
                }
            }
        }//decideSubState

        /**
         * Drives the parser to the next state/event on the input. Parser is guaranteed
         * to stop at the next state/event. Internally XML document
         * is divided into several states. Each state represents a sections of XML
         * document. When this functions returns normally, it has read the section
         * of XML document and returns the state corresponding to section of
         * document which has been read. For optimizations, a particular driver
         * can read ahead of the section of document (state returned) just read and
         * can maintain a different internal state.
         *
         * State returned corresponds to Stax states.
         *
         * @return state representing the section of document just read.
         *
         * @throws IOException  Thrown on i/o error.
         * @throws XNIException Thrown on parse error.
         */

        public int next() throws IOException, XNIException {
            while (true) {
            try {
                if(DEBUG_NEXT){
                    System.out.println("NOW IN FragmentContentDriver");
                    System.out.println("Entering the FragmentContentDriver with = " + getScannerStateName(fScannerState));
                }

                //decide the actual sub state of the scanner.For more information refer to the javadoc of
                //decideSubState.

                switch (fScannerState) {
                    case SCANNER_STATE_CONTENT: {
                        final int ch = fEntityScanner.peekChar();
                        if (ch == '<') {
                            fEntityScanner.scanChar(null);
                            setScannerState(SCANNER_STATE_START_OF_MARKUP);
                        } else if (ch == '&') {
                            fEntityScanner.scanChar(NameType.REFERENCE);
                            setScannerState(SCANNER_STATE_REFERENCE) ; //XMLEvent.ENTITY_REFERENCE ); //SCANNER_STATE_REFERENCE
                            break;
                        } else {
                            //element content is there..
                            setScannerState(SCANNER_STATE_CHARACTER_DATA);
                            break;
                        }
                    }

                    case SCANNER_STATE_START_OF_MARKUP: {
                        startOfMarkup();
                        break;
                    }//case: SCANNER_STATE_START_OF_MARKUP

                }//end of switch
                //decideSubState() ;

                //do some special handling if isCoalesce is set to true.
                if(fIsCoalesce){
                    fUsebuffer = true ;
                    //if the last section was character data
                    if(fLastSectionWasCharacterData){

                        //if we dont encounter any CDATA or ENITY REFERENCE and current state is also not SCANNER_STATE_CHARACTER_DATA
                        //return the last scanned charactrer data.
                        if((fScannerState != SCANNER_STATE_CDATA) && (fScannerState != SCANNER_STATE_REFERENCE)
                        && (fScannerState != SCANNER_STATE_CHARACTER_DATA)){
                            fLastSectionWasCharacterData = false;
                            return XMLEvent.CHARACTERS;
                        }
                    }//if last section was CDATA or ENTITY REFERENCE
                    //xxx: there might be another entity reference or CDATA after this
                    //<foo>blah blah &amp;&lt;<![CDATA[[aa]]>blah blah</foo>
                    else if((fLastSectionWasCData || fLastSectionWasEntityReference)){
                        //and current state is not SCANNER_STATE_CHARACTER_DATA
                        //or SCANNER_STATE_CDATA or SCANNER_STATE_REFERENCE
                        //this means there is nothing more to be coalesced.
                        //return the CHARACTERS event.
                        if((fScannerState != SCANNER_STATE_CDATA) && (fScannerState != SCANNER_STATE_REFERENCE)
                        && (fScannerState != SCANNER_STATE_CHARACTER_DATA)){

                            fLastSectionWasCData = false;
                            fLastSectionWasEntityReference = false;
                            return XMLEvent.CHARACTERS;
                        }
                    }
                }


                if(DEBUG_NEXT){
                    System.out.println("Actual scanner state set by decideSubState is = " + getScannerStateName(fScannerState));
                }

                switch(fScannerState){

                    case XMLEvent.START_DOCUMENT :
                        return XMLEvent.START_DOCUMENT;

                    case SCANNER_STATE_START_ELEMENT_TAG :{

                        //xxx this function returns true when element is empty.. can be linked to end element event.
                        //returns true if the element is empty
                        fEmptyElement = scanStartElement() ;
                        //if the element is empty the next event is "end element"
                        if(fEmptyElement){
                            setScannerState(SCANNER_STATE_END_ELEMENT_TAG);
                        }else{
                            //set the next possible state
                            setScannerState(SCANNER_STATE_CONTENT);
                        }
                        return XMLEvent.START_ELEMENT ;
                    }

                    case SCANNER_STATE_CHARACTER_DATA: {
                        if(DEBUG_COALESCE){
                            System.out.println("fLastSectionWasCData = " + fLastSectionWasCData);
                            System.out.println("fIsCoalesce = " + fIsCoalesce);
                        }
                        //if last section was either entity reference or cdata or character data we should be using buffer
                        fUsebuffer = fLastSectionWasEntityReference || fLastSectionWasCData || fLastSectionWasCharacterData ;

                        //When coalesce is set to true and last state was REFERENCE or CDATA or CHARACTER_DATA, buffer should not be cleared.
                        if( fIsCoalesce && (fLastSectionWasEntityReference || fLastSectionWasCData || fLastSectionWasCharacterData) ){
                            fLastSectionWasEntityReference = false;
                            fLastSectionWasCData = false;
                            fLastSectionWasCharacterData = true ;
                            fUsebuffer = true;
                        }else{
                            //clear the buffer
                            fContentBuffer.clear();
                        }

                        //set the fTempString length to 0 before passing it on to scanContent
                        //scanContent sets the correct co-ordinates as per the content read
                        fTempString.length = 0;
                        int c = fEntityScanner.scanContent(fTempString);
                        if(DEBUG){
                            System.out.println("fTempString = " + fTempString);
                        }
                        if(fEntityScanner.skipChar('<', null)){
                            //check if we have reached end of element
                            if(fEntityScanner.skipChar('/', NameType.ELEMENTEND)){
                                //increase the mark up depth
                                fMarkupDepth++;
                                fLastSectionWasCharacterData = false;
                                setScannerState(SCANNER_STATE_END_ELEMENT_TAG);
                                //check if its start of new element
                            }else if(XMLChar.isNameStart(fEntityScanner.peekChar())){
                                fMarkupDepth++;
                                fLastSectionWasCharacterData = false;
                                setScannerState(SCANNER_STATE_START_ELEMENT_TAG);
                            }else{
                                setScannerState(SCANNER_STATE_START_OF_MARKUP);
                                //there can be cdata ahead if coalesce is true we should call again
                                if(fIsCoalesce){
                                    fUsebuffer = true;
                                    fLastSectionWasCharacterData = true;
                                    fContentBuffer.append(fTempString);
                                    fTempString.length = 0;
                                    continue;
                                }
                            }
                            //in case last section was either entity reference or cdata or character data -- we should be using buffer
                            if(fUsebuffer){
                                fContentBuffer.append(fTempString);
                                fTempString.length = 0;
                            }
                            if(DEBUG){
                                System.out.println("NOT USING THE BUFFER, STRING = " + fTempString.toString());
                            }
                            if(dtdGrammarUtil!= null && dtdGrammarUtil.isIgnorableWhiteSpace(fContentBuffer)){
                                if(DEBUG)System.out.println("Return SPACE EVENT");
                                return XMLEvent.SPACE;
                            }else
                                return XMLEvent.CHARACTERS;

                        } else{
                            fUsebuffer = true ;
                            if(DEBUG){
                                System.out.println("fContentBuffer = " + fContentBuffer);
                                System.out.println("fTempString = " + fTempString);
                            }
                            fContentBuffer.append(fTempString);
                            fTempString.length = 0;
                        }
                        if (c == '\r') {
                            if(DEBUG){
                                System.out.println("'\r' character found");
                            }
                            // happens when there is the character reference &#13;
                            //xxx: We know the next chracter.. we should just skip it and add ']' directlry
                            fEntityScanner.scanChar(null);
                            fUsebuffer = true;
                            fContentBuffer.append((char)c);
                            c = -1 ;
                        } else if (c == ']') {
                            //fStringBuffer.clear();
                            //xxx: We know the next chracter.. we should just skip it and add ']' directlry
                            fUsebuffer = true;
                            fContentBuffer.append((char)fEntityScanner.scanChar(null));
                            // remember where we are in case we get an endEntity before we
                            // could flush the buffer out - this happens when we're parsing an
                            // entity which ends with a ]
                            fInScanContent = true;

                            // We work on a single character basis to handle cases such as:
                            // ']]]>' which we might otherwise miss.
                            //
                            if (fEntityScanner.skipChar(']', null)) {
                                fContentBuffer.append(']');
                                while (fEntityScanner.skipChar(']', null)) {
                                    fContentBuffer.append(']');
                                }
                                if (fEntityScanner.skipChar('>', null)) {
                                    reportFatalError("CDEndInContent", null);
                                }
                            }
                            c = -1 ;
                            fInScanContent = false;
                        }

                        do{
                            //xxx: we should be using only one buffer..
                            // we need not to grow the buffer only when isCoalesce() is not true;

                            if (c == '<') {
                                fEntityScanner.scanChar(null);
                                setScannerState(SCANNER_STATE_START_OF_MARKUP);
                                break;
                            }//xxx what should be the behavior if entity reference is present in the content ?
                            else if (c == '&') {
                                fEntityScanner.scanChar(NameType.REFERENCE);
                                setScannerState(SCANNER_STATE_REFERENCE);
                                break;
                            }///xxx since this part is also characters, it should be merged...
                            else if (c != -1 && isInvalidLiteral(c)) {
                                if (XMLChar.isHighSurrogate(c)) {
                                    // special case: surrogates
                                    scanSurrogates(fContentBuffer) ;
                                    setScannerState(SCANNER_STATE_CONTENT);
                                } else {
                                    reportFatalError("InvalidCharInContent",
                                            new Object[] {
                                        Integer.toString(c, 16)});
                                        fEntityScanner.scanChar(null);
                                }
                                break;
                            }
                            //xxx: scanContent also gives character callback.
                            c = scanContent(fContentBuffer) ;
                            //we should not be iterating again if fIsCoalesce is not set to true

                            if(!fIsCoalesce){
                                setScannerState(SCANNER_STATE_CONTENT);
                                break;
                            }

                        }while(true);

                        //if (fDocumentHandler != null) {
                        //  fDocumentHandler.characters(fContentBuffer, null);
                        //}
                        if(DEBUG)System.out.println("USING THE BUFFER, STRING START=" + fContentBuffer.toString() +"=END");
                        //if fIsCoalesce is true there might be more data so call fDriver.next()
                        if(fIsCoalesce){
                            fLastSectionWasCharacterData = true ;
                            continue;
                        }else{
                            if(dtdGrammarUtil!= null && dtdGrammarUtil.isIgnorableWhiteSpace(fContentBuffer)){
                                if(DEBUG)System.out.println("Return SPACE EVENT");
                                return XMLEvent.SPACE;
                            } else
                                return XMLEvent.CHARACTERS ;
                        }
                    }

                    case SCANNER_STATE_END_ELEMENT_TAG :{
                        if(fEmptyElement){
                            //set it back to false.
                            fEmptyElement = false;
                            setScannerState(SCANNER_STATE_CONTENT);
                            //check the case when there is comment after single element document
                            //<foo/> and some comment after this
                            return (fMarkupDepth == 0 && elementDepthIsZeroHook() ) ? XMLEvent.END_ELEMENT : XMLEvent.END_ELEMENT ;

                        } else if(scanEndElement() == 0) {
                            //It is last element of the document
                            if (elementDepthIsZeroHook()) {
                                //if element depth is zero , it indicates the end of the document
                                //the state shouldn't be set, because it is set by elementDepthIsZeroHook() function
                                //xxx understand this point once again..
                                return XMLEvent.END_ELEMENT ;
                            }

                        }
                        setScannerState(SCANNER_STATE_CONTENT);
                        return XMLEvent.END_ELEMENT ;
                    }

                    case SCANNER_STATE_COMMENT: { //SCANNER_STATE_COMMENT:
                        scanComment();
                        setScannerState(SCANNER_STATE_CONTENT);
                        return XMLEvent.COMMENT;
                        //break;
                    }
                    case SCANNER_STATE_PI:{ //SCANNER_STATE_PI: {
                        //clear the buffer first
                        fContentBuffer.clear() ;
                        //xxx: which buffer should be passed. Ideally we shouldn't have
                        //more than two buffers --
                        //xxx: where should we add the switch for buffering.
                        scanPI(fContentBuffer);
                        setScannerState(SCANNER_STATE_CONTENT);
                        return XMLEvent.PROCESSING_INSTRUCTION;
                        //break;
                    }
                    case SCANNER_STATE_CDATA :{ //SCANNER_STATE_CDATA: {
                        //xxx: What if CDATA is the first event
                        //<foo><![CDATA[hello<><>]]>append</foo>

                        //we should not clear the buffer only when the last state was either SCANNER_STATE_REFERENCE or
                        //SCANNER_STATE_CHARACTER_DATA or SCANNER_STATE_REFERENCE
                        if(fIsCoalesce && ( fLastSectionWasEntityReference || fLastSectionWasCData || fLastSectionWasCharacterData)){
                            fLastSectionWasCData = true ;
                            fLastSectionWasEntityReference = false;
                            fLastSectionWasCharacterData = false;
                        }//if we dont need to coalesce clear the buffer
                        else{
                            fContentBuffer.clear();
                        }
                        fUsebuffer = true;
                        //CDATA section is completely read in all the case.
                        scanCDATASection(fContentBuffer , true);
                        setScannerState(SCANNER_STATE_CONTENT);
                        //1. if fIsCoalesce is set to true we set the variable fLastSectionWasCData to true
                        //and just call fDispatche.next(). Since we have set the scanner state to
                        //SCANNER_STATE_CONTENT (super state) parser will automatically recover and
                        //behave appropriately. When isCoalesce is set to true we dont need to reportCDATA event
                        //2. Check if application has set for reporting CDATA event
                        //3. if the application has neither set the fIsCoalesce to true nor fReportCdataEvent
                        //return the cdata event as characters.
                        if(fIsCoalesce){
                            fLastSectionWasCData = true ;
                            //there might be more data to coalesce.
                            continue;
                        }else if(fReportCdataEvent){
                            return XMLEvent.CDATA;
                        } else{
                            return XMLEvent.CHARACTERS;
                        }
                    }

                    case SCANNER_STATE_REFERENCE :{
                        fMarkupDepth++;
                        foundBuiltInRefs = false;

                        //we should not clear the buffer only when the last state was either CDATA or
                        //SCANNER_STATE_CHARACTER_DATA or SCANNER_STATE_REFERENCE
                        if(fIsCoalesce && ( fLastSectionWasEntityReference || fLastSectionWasCData || fLastSectionWasCharacterData)){
                            //fLastSectionWasEntityReference or fLastSectionWasCData are only
                            //used when fIsCoalesce is set to true.
                            fLastSectionWasEntityReference = true ;
                            fLastSectionWasCData = false;
                            fLastSectionWasCharacterData = false;
                        }//if we dont need to coalesce clear the buffer
                        else{
                            fContentBuffer.clear();
                        }
                        fUsebuffer = true ;
                        //take care of character reference
                        if (fEntityScanner.skipChar('#', NameType.REFERENCE)) {
                            scanCharReferenceValue(fContentBuffer, null);
                            fMarkupDepth--;
                            if(!fIsCoalesce){
                                setScannerState(SCANNER_STATE_CONTENT);
                                return XMLEvent.CHARACTERS;
                            }
                        } else {
                            // this function also starts new entity
                            scanEntityReference(fContentBuffer);
                            //if there was built-in entity reference & coalesce is not true
                            //return CHARACTERS
                            if(fScannerState == SCANNER_STATE_BUILT_IN_REFS && !fIsCoalesce){
                                setScannerState(SCANNER_STATE_CONTENT);
                                return XMLEvent.CHARACTERS;
                            }

                            //if there was a text declaration, call next() it will be taken care.
                            if(fScannerState == SCANNER_STATE_TEXT_DECL){
                                fLastSectionWasEntityReference = true ;
                                continue;
                            }

                            if(fScannerState == SCANNER_STATE_REFERENCE){
                                setScannerState(SCANNER_STATE_CONTENT);
                                if (fReplaceEntityReferences && fEntityStore.isDeclaredEntity(fCurrentEntityName)) {
                                    // Skip the entity reference, we don't care
                                    continue;
                                }
                                return XMLEvent.ENTITY_REFERENCE;
                            }
                        }
                        //Wether it was character reference, entity reference or built-in entity
                        //set the next possible state to SCANNER_STATE_CONTENT
                        setScannerState(SCANNER_STATE_CONTENT);
                        fLastSectionWasEntityReference = true ;
                        continue;
                    }

                    case SCANNER_STATE_TEXT_DECL: {
                        // scan text decl
                        if (fEntityScanner.skipString("<?xml")) {
                            fMarkupDepth++;
                            // NOTE: special case where entity starts with a PI
                            //       whose name starts with "xml" (e.g. "xmlfoo")
                            if (isValidNameChar(fEntityScanner.peekChar())) {
                                fStringBuffer.clear();
                                fStringBuffer.append("xml");

                                if (fNamespaces) {
                                    while (isValidNCName(fEntityScanner.peekChar())) {
                                        fStringBuffer.append((char)fEntityScanner.scanChar(null));
                                    }
                                } else {
                                    while (isValidNameChar(fEntityScanner.peekChar())) {
                                        fStringBuffer.append((char)fEntityScanner.scanChar(null));
                                    }
                                }
                                String target = fSymbolTable.addSymbol(fStringBuffer.ch, fStringBuffer.offset, fStringBuffer.length);
                                fContentBuffer.clear();
                                scanPIData(target, fContentBuffer);
                            }

                            // standard text declaration
                            else {
                                //xxx: this function gives callback
                                scanXMLDeclOrTextDecl(true);
                            }
                        }
                        // now that we've straightened out the readers, we can read in chunks:
                        fEntityManager.fCurrentEntity.mayReadChunks = true;
                        setScannerState(SCANNER_STATE_CONTENT);
                        //xxx: we don't return any state, so how do we get to know about TEXT declarations.
                        //it seems we have to careful when to allow function issue a callback
                        //and when to allow adapter issue a callback.
                        continue;
                    }


                    case SCANNER_STATE_ROOT_ELEMENT: {
                        if (scanRootElementHook()) {
                            fEmptyElement = true;
                            //rest would be taken care by fTrailingMiscDriver set by scanRootElementHook
                            return XMLEvent.START_ELEMENT;
                        }
                        setScannerState(SCANNER_STATE_CONTENT);
                        return XMLEvent.START_ELEMENT ;
                    }
                    case SCANNER_STATE_CHAR_REFERENCE : {
                        fContentBuffer.clear();
                        scanCharReferenceValue(fContentBuffer, null);
                        fMarkupDepth--;
                        setScannerState(SCANNER_STATE_CONTENT);
                        return XMLEvent.CHARACTERS;
                    }
                    default:
                        throw new XNIException("Scanner State " + fScannerState + " not Recognized ");

                }//switch
            }
            // premature end of file
            catch (EOFException e) {
                endOfFileHook(e);
                return -1;
            }
            } //while loop
        }//next

        //
        // Protected methods
        //

        // hooks

        // NOTE: These hook methods are added so that the full document
        //       scanner can share the majority of code with this class.

        /**
         * Scan for DOCTYPE hook. This method is a hook for subclasses
         * to add code to handle scanning for a the "DOCTYPE" string
         * after the string "<!" has been scanned.
         *
         * @return True if the "DOCTYPE" was scanned; false if "DOCTYPE"
         *          was not scanned.
         */
        protected boolean scanForDoctypeHook()
        throws IOException, XNIException {
            return false;
        } // scanForDoctypeHook():boolean

        /**
         * Element depth iz zero. This methos is a hook for subclasses
         * to add code to handle when the element depth hits zero. When
         * scanning a document fragment, an element depth of zero is
         * normal. However, when scanning a full XML document, the
         * scanner must handle the trailing miscellanous section of
         * the document after the end of the document's root element.
         *
         * @return True if the caller should stop and return true which
         *          allows the scanner to switch to a new scanning
         *          driver. A return value of false indicates that
         *          the content driver should continue as normal.
         */
        protected boolean elementDepthIsZeroHook()
        throws IOException, XNIException {
            return false;
        } // elementDepthIsZeroHook():boolean

        /**
         * Scan for root element hook. This method is a hook for
         * subclasses to add code that handles scanning for the root
         * element. When scanning a document fragment, there is no
         * "root" element. However, when scanning a full XML document,
         * the scanner must handle the root element specially.
         *
         * @return True if the caller should stop and return true which
         *          allows the scanner to switch to a new scanning
         *          driver. A return value of false indicates that
         *          the content driver should continue as normal.
         */
        protected boolean scanRootElementHook()
        throws IOException, XNIException {
            return false;
        } // scanRootElementHook():boolean

        /**
         * End of file hook. This method is a hook for subclasses to
         * add code that handles the end of file. The end of file in
         * a document fragment is OK if the markup depth is zero.
         * However, when scanning a full XML document, an end of file
         * is always premature.
         */
        protected void endOfFileHook(EOFException e)
        throws IOException, XNIException {

            // NOTE: An end of file is only only an error if we were
            //       in the middle of scanning some markup. -Ac
            if (fMarkupDepth != 0) {
                reportFatalError("PrematureEOF", null);
            }

        } // endOfFileHook()

    } // class FragmentContentDriver

    static void pr(String str) {
        System.out.println(str) ;
    }

    protected boolean fUsebuffer ;

    /** this function gets an XMLString (which is used to store the attribute value) from the special pool
     *  maintained for attributes.
     *  fAttributeCacheUsedCount tracks the number of attributes that has been consumed from the pool.
     *  if all the attributes has been consumed, it adds a new XMLString inthe pool and returns the same
     *  XMLString.
     *
     * @return XMLString XMLString used to store an attribute value.
     */

    protected XMLString getString(){
        if(fAttributeCacheUsedCount < initialCacheCount || fAttributeCacheUsedCount < attributeValueCache.size()){
            return attributeValueCache.get(fAttributeCacheUsedCount++);
        } else{
            XMLString str = new XMLString();
            fAttributeCacheUsedCount++;
            attributeValueCache.add(str);
            return str;
        }
    }

    /**
     * Implements XMLBufferListener interface.
     */

    public void refresh(){
        refresh(0);
    }

    /**
     * receives callbacks from {@link XMLEntityReader } when buffer
     * is being changed.
     * @param refreshPosition
     */
    public void refresh(int refreshPosition){
        //If you are reading attributes and you got a callback
        //cache available attributes.
        if(fReadingAttributes){
            fAttributes.refresh();
        }
        if(fScannerState == SCANNER_STATE_CHARACTER_DATA){
            //since fTempString directly matches to the underlying main buffer
            //store the data into buffer
            fContentBuffer.append(fTempString);
            //clear the XMLString so that data can't be added again.
            fTempString.length = 0;
            fUsebuffer = true;
        }
    }

} // class XMLDocumentFragmentScannerImpl
