FileDocCategorySizeDatePackage
XMLDTDValidator.javaAPI DocApache Xerces 3.0.187024Fri Sep 14 20:33:52 BST 2007org.apache.xerces.impl.dtd

XMLDTDValidator

public class XMLDTDValidator extends Object implements org.apache.xerces.impl.RevalidationHandler, org.apache.xerces.xni.parser.XMLDocumentFilter, XMLDTDValidatorFilter, org.apache.xerces.xni.parser.XMLComponent
The DTD validator. The validator implements a document filter: receiving document events from the scanner; validating the content and structure; augmenting the InfoSet, if applicable; and notifying the parser of the information resulting from the validation process.

Formerly, this component also handled DTD events and grammar construction. To facilitate the development of a meaningful DTD grammar caching/preparsing framework, this functionality has been moved into the XMLDTDLoader class. Therefore, this class no longer implements the DTDFilter or DTDContentModelFilter interfaces.

This component requires the following features and properties from the component manager that uses it:

  • http://xml.org/sax/features/namespaces
  • http://xml.org/sax/features/validation
  • http://apache.org/xml/features/validation/dynamic
  • http://apache.org/xml/properties/internal/symbol-table
  • http://apache.org/xml/properties/internal/error-reporter
  • http://apache.org/xml/properties/internal/grammar-pool
  • http://apache.org/xml/properties/internal/datatype-validator-factory
xerces.internal
author
Eric Ye, IBM
author
Andy Clark, IBM
author
Jeffrey Rodriguez IBM
author
Neil Graham, IBM
version
$Id: XMLDTDValidator.java 572055 2007-09-02 17:55:43Z mrglavas $

Fields Summary
private static final int
TOP_LEVEL_SCOPE
Top level scope (-1).
protected static final String
NAMESPACES
Feature identifier: namespaces.
protected static final String
VALIDATION
Feature identifier: validation.
protected static final String
DYNAMIC_VALIDATION
Feature identifier: dynamic validation.
protected static final String
BALANCE_SYNTAX_TREES
Feature identifier: balance syntax trees.
protected static final String
WARN_ON_DUPLICATE_ATTDEF
Feature identifier: warn on duplicate attdef
protected static final String
PARSER_SETTINGS
protected static final String
SYMBOL_TABLE
Property identifier: symbol table.
protected static final String
ERROR_REPORTER
Property identifier: error reporter.
protected static final String
GRAMMAR_POOL
Property identifier: grammar pool.
protected static final String
DATATYPE_VALIDATOR_FACTORY
Property identifier: datatype validator factory.
protected static final String
VALIDATION_MANAGER
private static final String[]
RECOGNIZED_FEATURES
Recognized features.
private static final Boolean[]
FEATURE_DEFAULTS
Feature defaults.
private static final String[]
RECOGNIZED_PROPERTIES
Recognized properties.
private static final Object[]
PROPERTY_DEFAULTS
Property defaults.
private static final boolean
DEBUG_ATTRIBUTES
Compile to true to debug attributes.
private static final boolean
DEBUG_ELEMENT_CHILDREN
Compile to true to debug element children.
protected org.apache.xerces.impl.validation.ValidationManager
fValidationManager
protected final org.apache.xerces.impl.validation.ValidationState
fValidationState
protected boolean
fNamespaces
Namespaces.
protected boolean
fValidation
Validation.
protected boolean
fDTDValidation
Validation against only DTD
protected boolean
fDynamicValidation
Dynamic validation. This state of this feature is only useful when the validation feature is set to true.
protected boolean
fBalanceSyntaxTrees
Controls whether the DTD grammar produces balanced syntax trees.
protected boolean
fWarnDuplicateAttdef
warn on duplicate attribute definition, this feature works only when validation is true
protected org.apache.xerces.util.SymbolTable
fSymbolTable
Symbol table.
protected org.apache.xerces.impl.XMLErrorReporter
fErrorReporter
Error reporter.
protected org.apache.xerces.xni.grammars.XMLGrammarPool
fGrammarPool
protected DTDGrammarBucket
fGrammarBucket
Grammar bucket.
protected org.apache.xerces.xni.XMLLocator
fDocLocation
protected org.apache.xerces.xni.NamespaceContext
fNamespaceContext
Namespace support.
protected org.apache.xerces.impl.dv.DTDDVFactory
fDatatypeValidatorFactory
Datatype validator factory.
protected org.apache.xerces.xni.XMLDocumentHandler
fDocumentHandler
Document handler.
protected org.apache.xerces.xni.parser.XMLDocumentSource
fDocumentSource
protected DTDGrammar
fDTDGrammar
DTD Grammar.
protected boolean
fSeenDoctypeDecl
True if seen DOCTYPE declaration.
private boolean
fPerformValidation
Perform validation.
private String
fSchemaType
Schema type: None, DTD, Schema
private final org.apache.xerces.xni.QName
fCurrentElement
Current element name.
private int
fCurrentElementIndex
Current element index.
private int
fCurrentContentSpecType
Current content spec type.
private final org.apache.xerces.xni.QName
fRootElement
The root element name.
private boolean
fInCDATASection
private int[]
fElementIndexStack
Element index stack.
private int[]
fContentSpecTypeStack
Content spec type stack.
private org.apache.xerces.xni.QName[]
fElementQNamePartsStack
Element name stack.
private org.apache.xerces.xni.QName[]
fElementChildren
Element children. This data structure is a growing stack that holds the children of elements from the root to the current element depth. This structure never gets "deeper" than the deepest element. Space is re-used once each element is closed.

Note: This is much more efficient use of memory than creating new arrays for each element depth.

Note: The use of this data structure is for validation "on the way out". If the validation model changes to "on the way in", then this data structure is not needed.

private int
fElementChildrenLength
Element children count.
private int[]
fElementChildrenOffsetStack
Element children offset stack. This stack refers to offsets into the fElementChildren array.
private int
fElementDepth
Element depth.
private boolean
fSeenRootElement
True if seen the root element.
private boolean
fInElementContent
True if inside of element content.
private XMLElementDecl
fTempElementDecl
Temporary element declaration.
private XMLAttributeDecl
fTempAttDecl
Temporary atribute declaration.
private XMLEntityDecl
fEntityDecl
Temporary entity declaration.
private org.apache.xerces.xni.QName
fTempQName
Temporary qualified name.
private StringBuffer
fBuffer
Temporary string buffers.
protected org.apache.xerces.impl.dv.DatatypeValidator
fValID
Datatype validator: ID.
protected org.apache.xerces.impl.dv.DatatypeValidator
fValIDRef
Datatype validator: IDREF.
protected org.apache.xerces.impl.dv.DatatypeValidator
fValIDRefs
Datatype validator: IDREFS.
protected org.apache.xerces.impl.dv.DatatypeValidator
fValENTITY
Datatype validator: ENTITY.
protected org.apache.xerces.impl.dv.DatatypeValidator
fValENTITIES
Datatype validator: ENTITIES.
protected org.apache.xerces.impl.dv.DatatypeValidator
fValNMTOKEN
Datatype validator: NMTOKEN.
protected org.apache.xerces.impl.dv.DatatypeValidator
fValNMTOKENS
Datatype validator: NMTOKENS.
protected org.apache.xerces.impl.dv.DatatypeValidator
fValNOTATION
Datatype validator: NOTATION.
Constructors Summary
public XMLDTDValidator()
Default constructor.


    // to check for duplicate ID or ANNOTATION attribute declare in
    // ATTLIST, and misc VCs

    //
    // Constructors
    //

       
      

        // initialize data
        for (int i = 0; i < fElementQNamePartsStack.length; i++) {
            fElementQNamePartsStack[i] = new QName();
        }
        fGrammarBucket = new DTDGrammarBucket();

    
Methods Summary
protected voidaddDTDDefaultAttrsAndValidate(org.apache.xerces.xni.QName elementName, int elementIndex, org.apache.xerces.xni.XMLAttributes attributes)
Add default attributes and validate.


        // is there anything to do?
        if (elementIndex == -1 || fDTDGrammar == null) {
            return;
        }

        //
        // Check after all specified attrs are scanned
        // (1) report error for REQUIRED attrs that are missing (V_TAGc)
        // (2) add default attrs (FIXED and NOT_FIXED)
        //
        int attlistIndex = fDTDGrammar.getFirstAttributeDeclIndex(elementIndex);

        while (attlistIndex != -1) {

            fDTDGrammar.getAttributeDecl(attlistIndex, fTempAttDecl);

            if (DEBUG_ATTRIBUTES) {
                if (fTempAttDecl != null) {
                    XMLElementDecl elementDecl = new XMLElementDecl();
                    fDTDGrammar.getElementDecl(elementIndex, elementDecl);
                    System.out.println("element: "+(elementDecl.name.localpart));
                    System.out.println("attlistIndex " + attlistIndex + "\n"+
                                       "attName : '"+(fTempAttDecl.name.localpart) + "'\n"
                                       + "attType : "+fTempAttDecl.simpleType.type + "\n"
                                       + "attDefaultType : "+fTempAttDecl.simpleType.defaultType + "\n"
                                       + "attDefaultValue : '"+fTempAttDecl.simpleType.defaultValue + "'\n"
                                       + attributes.getLength() +"\n"
                                      );
                }
            }
            String attPrefix = fTempAttDecl.name.prefix;
            String attLocalpart = fTempAttDecl.name.localpart;
            String attRawName = fTempAttDecl.name.rawname;
            String attType = getAttributeTypeName(fTempAttDecl);
            int attDefaultType =fTempAttDecl.simpleType.defaultType;
            String attValue = null;
                            
            if (fTempAttDecl.simpleType.defaultValue != null) {
                attValue = fTempAttDecl.simpleType.defaultValue;
            }
            
            boolean specified = false;
            boolean required = attDefaultType == XMLSimpleType.DEFAULT_TYPE_REQUIRED;
            boolean cdata = attType == XMLSymbols.fCDATASymbol;

            if (!cdata || required || attValue != null) {
                int attrCount = attributes.getLength();
                for (int i = 0; i < attrCount; i++) {
                    if (attributes.getQName(i) == attRawName) {
                        specified = true;
                        break;
                    }
                }
            }

            if (!specified) {
                if (required) {
                    if (fPerformValidation) {
                        Object[] args = {elementName.localpart, attRawName};
                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                                   "MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED", args,
                                                   XMLErrorReporter.SEVERITY_ERROR);
                    }
                }
                else if (attValue != null) {
                    if (fPerformValidation && fGrammarBucket.getStandalone()) {
                        if (fDTDGrammar.getAttributeDeclIsExternal(attlistIndex)) {

                            Object[] args = { elementName.localpart, attRawName};
                            fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                                       "MSG_DEFAULTED_ATTRIBUTE_NOT_SPECIFIED", args,
                                                       XMLErrorReporter.SEVERITY_ERROR);
                        }
                    }

                    // add namespace information
                    if (fNamespaces) {
                        int index = attRawName.indexOf(':");
                        if (index != -1) {
                            attPrefix = attRawName.substring(0, index);
                            attPrefix = fSymbolTable.addSymbol(attPrefix);
                            attLocalpart = attRawName.substring(index + 1);
                            attLocalpart = fSymbolTable.addSymbol(attLocalpart);
                        }
                    }

                    // add attribute
                    fTempQName.setValues(attPrefix, attLocalpart, attRawName, fTempAttDecl.name.uri);
                    int newAttr = attributes.addAttribute(fTempQName, attType, attValue);
                }
            }
            // get next att decl in the Grammar for this element
            attlistIndex = fDTDGrammar.getNextAttributeDeclIndex(attlistIndex);
        }

        // now iterate through the expanded attributes for
        // 1. if every attribute seen is declared in the DTD
        // 2. check if the VC: default_fixed holds
        // 3. validate every attribute.
        int attrCount = attributes.getLength();
        for (int i = 0; i < attrCount; i++) {
            String attrRawName = attributes.getQName(i);
            boolean declared = false;
            if (fPerformValidation) {
                if (fGrammarBucket.getStandalone()) {
                    // check VC: Standalone Document Declaration, entities
                    // references appear in the document.
                    // REVISIT: this can be combined to a single check in
                    // startEntity if we add one more argument in
                    // startEnity, inAttrValue
                    String nonNormalizedValue = attributes.getNonNormalizedValue(i);
                    if (nonNormalizedValue != null) {
                        String entityName = getExternalEntityRefInAttrValue(nonNormalizedValue);
                        if (entityName != null) {
                            fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                                       "MSG_REFERENCE_TO_EXTERNALLY_DECLARED_ENTITY_WHEN_STANDALONE",
                                                       new Object[]{entityName},
                                                       XMLErrorReporter.SEVERITY_ERROR);
                        }
                    }
                }
            }
            int attDefIndex = -1;
            int position =
            fDTDGrammar.getFirstAttributeDeclIndex(elementIndex);
            while (position != -1) {
                fDTDGrammar.getAttributeDecl(position, fTempAttDecl);
                if (fTempAttDecl.name.rawname == attrRawName) {
                    // found the match att decl, 
                    attDefIndex = position;
                    declared = true;
                    break;
                }
                position = fDTDGrammar.getNextAttributeDeclIndex(position);
            }
            if (!declared) {
                if (fPerformValidation) {
                    // REVISIT - cache the elem/attr tuple so that we only
                    // give this error once for each unique occurrence
                    Object[] args = { elementName.rawname, attrRawName};

                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                               "MSG_ATTRIBUTE_NOT_DECLARED",
                                               args,XMLErrorReporter.SEVERITY_ERROR);   
                }
                continue;
            }
            // attribute is declared

            // fTempAttDecl should have the right value set now, so
            // the following is not needed
            // fGrammar.getAttributeDecl(attDefIndex,fTempAttDecl);

            String type = getAttributeTypeName(fTempAttDecl);
            attributes.setType(i, type);
            attributes.getAugmentations(i).putItem(Constants.ATTRIBUTE_DECLARED, Boolean.TRUE);

            boolean changedByNormalization = false;
            String oldValue = attributes.getValue(i);
            String attrValue = oldValue;
            if (attributes.isSpecified(i) && type != XMLSymbols.fCDATASymbol) {
                changedByNormalization = normalizeAttrValue(attributes, i);
                attrValue = attributes.getValue(i);
                if (fPerformValidation && fGrammarBucket.getStandalone()
                    && changedByNormalization 
                    && fDTDGrammar.getAttributeDeclIsExternal(position)
                   ) {
                    // check VC: Standalone Document Declaration
                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                               "MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE",
                                               new Object[]{attrRawName, oldValue, attrValue},
                                               XMLErrorReporter.SEVERITY_ERROR);
                }
            }
            if (!fPerformValidation) {
                continue;
            }
            if (fTempAttDecl.simpleType.defaultType ==
                XMLSimpleType.DEFAULT_TYPE_FIXED) {
                String defaultValue = fTempAttDecl.simpleType.defaultValue;

                if (!attrValue.equals(defaultValue)) {
                    Object[] args = {elementName.localpart,
                        attrRawName,
                        attrValue,
                        defaultValue};
                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                               "MSG_FIXED_ATTVALUE_INVALID",
                                               args, XMLErrorReporter.SEVERITY_ERROR);
                }
            }

            if (fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ENTITY ||
                fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ENUMERATION ||
                fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_ID ||
                fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_IDREF ||
                fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_NMTOKEN ||
                fTempAttDecl.simpleType.type == XMLSimpleType.TYPE_NOTATION
               ) {
                validateDTDattribute(elementName, attrValue, fTempAttDecl);
            }
        } // for all attributes

    
private voidcharDataInContent()
Character data in content.


        if (DEBUG_ELEMENT_CHILDREN) {
            System.out.println("charDataInContent()");
        }
        if (fElementChildren.length <= fElementChildrenLength) {
            QName[] newarray = new QName[fElementChildren.length * 2];
            System.arraycopy(fElementChildren, 0, newarray, 0, fElementChildren.length);
            fElementChildren = newarray;
        }
        QName qname = fElementChildren[fElementChildrenLength];
        if (qname == null) {
            for (int i = fElementChildrenLength; i < fElementChildren.length; i++) {
                fElementChildren[i] = new QName();
            }
            qname = fElementChildren[fElementChildrenLength];
        }
        qname.clear();
        fElementChildrenLength++;

    
public booleancharacterData(java.lang.String data, org.apache.xerces.xni.Augmentations augs)

       
        characters(new XMLString(data.toCharArray(), 0, data.length()), augs);
        return true;
    
public voidcharacters(org.apache.xerces.xni.XMLString text, org.apache.xerces.xni.Augmentations augs)
Character content.

param
text The content.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.


        boolean callNextCharacters = true;

        // REVISIT: [Q] Is there a more efficient way of doing this?
        //          Perhaps if the scanner told us so we don't have to
        //          look at the characters again. -Ac
        boolean allWhiteSpace = true;
        for (int i=text.offset; i< text.offset+text.length; i++) {
            if (!isSpace(text.ch[i])) {
                allWhiteSpace = false;
                break;
            }
        }
        // call the ignoreableWhiteSpace callback
        // never call ignorableWhitespace if we are in cdata section
        if (fInElementContent && allWhiteSpace && !fInCDATASection) {
            if (fDocumentHandler != null) {
                fDocumentHandler.ignorableWhitespace(text, augs);
                callNextCharacters = false;
            }
        }

        // validate
        if (fPerformValidation) {
            if (fInElementContent) {
                if (fGrammarBucket.getStandalone() &&
                    fDTDGrammar.getElementDeclIsExternal(fCurrentElementIndex)) {
                    if (allWhiteSpace) {
                        fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
                                                    "MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE",
                                                    null, XMLErrorReporter.SEVERITY_ERROR);
                    }
                }
                if (!allWhiteSpace) {
                    charDataInContent();
                }
                
                // For E15.2
                if (augs != null && augs.getItem(Constants.CHAR_REF_PROBABLE_WS) == Boolean.TRUE) {
                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 
                                               "MSG_CONTENT_INVALID_SPECIFIED",
                                               new Object[]{ fCurrentElement.rawname, 
                                                   fDTDGrammar.getContentSpecAsString(fElementDepth),
                                                   "character reference"},
                                               XMLErrorReporter.SEVERITY_ERROR);                
                }
            }

            if (fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
                charDataInContent();
            }
        }

        // call handlers
        if (callNextCharacters && fDocumentHandler != null) {
            fDocumentHandler.characters(text, augs);
        }

    
private intcheckContent(int elementIndex, org.apache.xerces.xni.QName[] children, int childOffset, int childCount)
Check that the content of an element is valid.

This is the method of primary concern to the validator. This method is called upon the scanner reaching the end tag of an element. At that time, the element's children must be structurally validated, so it calls this method. The index of the element being checked (in the decl pool), is provided as well as an array of element name indexes of the children. The validator must confirm that this element can have these children in this order.

This can also be called to do 'what if' testing of content models just to see if they would be valid.

Note that the element index is an index into the element decl pool, whereas the children indexes are name indexes, i.e. into the string pool.

A value of -1 in the children array indicates a PCDATA node. All other indexes will be positive and represent child elements. The count can be zero, since some elements have the EMPTY content model and that must be confirmed.

param
elementIndex The index within the ElementDeclPool of this element.
param
childCount The number of entries in the children array.
param
children The children of this element.
return
The value -1 if fully valid, else the 0 based index of the child that first failed. If the value returned is equal to the number of children, then additional content is required to reach a valid ending state.
exception
Exception Thrown on error.


        fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);

        // Get the element name index from the element
        final String elementType = fCurrentElement.rawname;

        // Get out the content spec for this element
        final int contentType = fCurrentContentSpecType;


        //
        //  Deal with the possible types of content. We try to optimized here
        //  by dealing specially with content models that don't require the
        //  full DFA treatment.
        //
        if (contentType == XMLElementDecl.TYPE_EMPTY) {
            //
            //  If the child count is greater than zero, then this is
            //  an error right off the bat at index 0.
            //
            if (childCount != 0) {
                return 0;
            }
        }
        else if (contentType == XMLElementDecl.TYPE_ANY) {
            //
            //  This one is open game so we don't pass any judgement on it
            //  at all. Its assumed to fine since it can hold anything.
            //
        }
        else if (contentType == XMLElementDecl.TYPE_MIXED ||  
                 contentType == XMLElementDecl.TYPE_CHILDREN) {
            // Get the content model for this element, faulting it in if needed
            ContentModelValidator cmElem = null;
            cmElem = fTempElementDecl.contentModelValidator;
            int result = cmElem.validate(children, childOffset, childCount);
            return result;
        }
        else if (contentType == -1) {
            //REVISIT
            /****
            reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_NOT_DECLARED,
                                      XMLMessages.VC_ELEMENT_VALID,
                                      elementType);
            /****/
        }
        else if (contentType == XMLElementDecl.TYPE_SIMPLE) {

            //REVISIT
            // this should never be reached in the case of DTD validation.

        }
        else {
            //REVISIT
            /****
            fErrorReporter.reportError(fErrorReporter.getLocator(),
                                       ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
                                       ImplementationMessages.VAL_CST,
                                       0,
                                       null,
                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
            /****/
        }

        // We succeeded
        return -1;

    
public voidcomment(org.apache.xerces.xni.XMLString text, org.apache.xerces.xni.Augmentations augs)
A comment.

param
text The text in the comment.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by application to signal an error.

        // fixes E15.1
        if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
            fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
            if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 
                                               "MSG_CONTENT_INVALID_SPECIFIED",
                                               new Object[]{ fCurrentElement.rawname,
                                                             "EMPTY",
                                                             "comment"},
                                               XMLErrorReporter.SEVERITY_ERROR);                
            }
        }
        // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.comment(text, augs);
        }

    
public voiddoctypeDecl(java.lang.String rootElement, java.lang.String publicId, java.lang.String systemId, org.apache.xerces.xni.Augmentations augs)
Notifies of the presence of the DOCTYPE line in the document.

param
rootElement The name of the root element.
param
publicId The public identifier if an external DTD or null if the external DTD is specified using SYSTEM.
param
systemId The system identifier if an external DTD, null otherwise.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.


        // save root element state
        fSeenDoctypeDecl = true;
        fRootElement.setValues(null, rootElement, rootElement, null);
        // find or create grammar:
        String eid = null;
        try {
            eid = XMLEntityManager.expandSystemId(systemId, fDocLocation.getExpandedSystemId(), false);
        } catch (java.io.IOException e) {
        }
        XMLDTDDescription grammarDesc = new XMLDTDDescription(publicId, systemId, fDocLocation.getExpandedSystemId(), eid, rootElement);
        fDTDGrammar = fGrammarBucket.getGrammar(grammarDesc);
        if(fDTDGrammar == null) {
            // give grammar pool a chance...
            //
            // Do not bother checking the pool if no public or system identifier was provided. 
            // Since so many different DTDs have roots in common, using only a root name as the 
            // key may cause an unexpected grammar to be retrieved from the grammar pool. This scenario
            // would occur when an ExternalSubsetResolver has been queried and the
            // XMLInputSource returned contains an input stream but no external identifier.
            // This can never happen when the instance document specified a DOCTYPE. -- mrglavas
            if (fGrammarPool != null && (systemId != null || publicId != null)) {
                fDTDGrammar = (DTDGrammar)fGrammarPool.retrieveGrammar(grammarDesc);
            }
        }
        if(fDTDGrammar == null) {
            // we'll have to create it...
            if (!fBalanceSyntaxTrees) {
                fDTDGrammar = new DTDGrammar(fSymbolTable, grammarDesc);
            }
            else {
                fDTDGrammar = new BalancedDTDGrammar(fSymbolTable, grammarDesc);
            }
        } else {
            // we've found a cached one;so let's make sure not to read
            // any external subset!
            fValidationManager.setCachedDTD(true);
        }
        fGrammarBucket.setActiveGrammar(fDTDGrammar);

        // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
        }

    
public voidemptyElement(org.apache.xerces.xni.QName element, org.apache.xerces.xni.XMLAttributes attributes, org.apache.xerces.xni.Augmentations augs)
An empty element.

param
element The name of the element.
param
attributes The element attributes.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.


        boolean removed = handleStartElement(element, attributes, augs);

        if (fDocumentHandler !=null) {
            fDocumentHandler.emptyElement(element, attributes, augs);
        }
        if (!removed) {
            handleEndElement(element, augs, true);
        }
        

    
public voidendCDATA(org.apache.xerces.xni.Augmentations augs)
The end of a CDATA section.

param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.


        fInCDATASection = false;
        // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.endCDATA(augs);
        }

    
public voidendDocument(org.apache.xerces.xni.Augmentations augs)
The end of the document.

param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.


        // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.endDocument(augs);
        }

    
public voidendElement(org.apache.xerces.xni.QName element, org.apache.xerces.xni.Augmentations augs)
The end of an element.

param
element The name of the element.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.


        handleEndElement(element,  augs, false);

    
public voidendGeneralEntity(java.lang.String name, org.apache.xerces.xni.Augmentations augs)
This method notifies the end of a general entity.

Note: This method is not called for entity references appearing as part of attribute values.

param
name The name of the entity.
param
augs Additional information that may include infoset augmentations
exception
XNIException Thrown by handler to signal an error.

        // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.endGeneralEntity(name, augs);
        }
    
protected voidendNamespaceScope(org.apache.xerces.xni.QName element, org.apache.xerces.xni.Augmentations augs, boolean isEmpty)


        // call handlers
        if (fDocumentHandler != null && !isEmpty) {
            // NOTE: The binding of the element doesn't actually happen
            //       yet because the namespace binder does that. However,
            //       if it does it before this point, then the endPrefix-
            //       Mapping calls get made too soon! As long as the
            //       rawnames match, we know it'll have a good binding,
            //       so we can just use the current element. -Ac
            fDocumentHandler.endElement(fCurrentElement, augs);
        }
    
private voidensureStackCapacity(int newElementDepth)
ensure element stack capacity

        if (newElementDepth == fElementQNamePartsStack.length) {

            QName[] newStackOfQueue = new QName[newElementDepth * 2];
            System.arraycopy(this.fElementQNamePartsStack, 0, newStackOfQueue, 0, newElementDepth );
            fElementQNamePartsStack = newStackOfQueue;

            QName qname = fElementQNamePartsStack[newElementDepth];
            if (qname == null) {
                for (int i = newElementDepth; i < fElementQNamePartsStack.length; i++) {
                    fElementQNamePartsStack[i] = new QName();
                }
            }

            int[] newStack = new int[newElementDepth * 2];
            System.arraycopy(fElementIndexStack, 0, newStack, 0, newElementDepth);
            fElementIndexStack = newStack;

            newStack = new int[newElementDepth * 2];
            System.arraycopy(fContentSpecTypeStack, 0, newStack, 0, newElementDepth);
            fContentSpecTypeStack = newStack;

        }
    
private java.lang.StringgetAttributeTypeName(XMLAttributeDecl attrDecl)
convert attribute type from ints to strings


        switch (attrDecl.simpleType.type) {
        case XMLSimpleType.TYPE_ENTITY: {
                return attrDecl.simpleType.list ? XMLSymbols.fENTITIESSymbol : XMLSymbols.fENTITYSymbol;
            }
        case XMLSimpleType.TYPE_ENUMERATION: {
                StringBuffer buffer = new StringBuffer();
                buffer.append('(");
                for (int i=0; i<attrDecl.simpleType.enumeration.length ; i++) {
                    if (i > 0) {
                        buffer.append("|");
                    }
                    buffer.append(attrDecl.simpleType.enumeration[i]);
                }
                buffer.append(')");
                return fSymbolTable.addSymbol(buffer.toString());
            }
        case XMLSimpleType.TYPE_ID: {
                return XMLSymbols.fIDSymbol;
            }
        case XMLSimpleType.TYPE_IDREF: {
                return attrDecl.simpleType.list ? XMLSymbols.fIDREFSSymbol : XMLSymbols.fIDREFSymbol;
            }
        case XMLSimpleType.TYPE_NMTOKEN: {
                return attrDecl.simpleType.list ? XMLSymbols.fNMTOKENSSymbol : XMLSymbols.fNMTOKENSymbol;
            }
        case XMLSimpleType.TYPE_NOTATION: {
                return XMLSymbols.fNOTATIONSymbol;
            }
        }
        return XMLSymbols.fCDATASymbol;

    
private intgetContentSpecType(int elementIndex)
Returns the content spec type for an element index.


        int contentSpecType = -1;
        if (elementIndex > -1) {
            if (fDTDGrammar.getElementDecl(elementIndex,fTempElementDecl)) {
                contentSpecType = fTempElementDecl.type;
            }
        }
        return contentSpecType;
    
public org.apache.xerces.xni.XMLDocumentHandlergetDocumentHandler()
Returns the document handler

        return fDocumentHandler;
    
public org.apache.xerces.xni.parser.XMLDocumentSourcegetDocumentSource()
Returns the document source

        return fDocumentSource;
    
protected java.lang.StringgetExternalEntityRefInAttrValue(java.lang.String nonNormalizedValue)
Checks entities in attribute values for standalone VC.

        int valLength = nonNormalizedValue.length();
        int ampIndex = nonNormalizedValue.indexOf('&");
        while (ampIndex != -1) {
            if (ampIndex + 1 < valLength &&
                nonNormalizedValue.charAt(ampIndex+1) != '#") {
                int semicolonIndex = nonNormalizedValue.indexOf(';", ampIndex+1);
                String entityName = nonNormalizedValue.substring(ampIndex+1, semicolonIndex);
                entityName = fSymbolTable.addSymbol(entityName);
                int entIndex = fDTDGrammar.getEntityDeclIndex(entityName);
                if (entIndex > -1) {
                    fDTDGrammar.getEntityDecl(entIndex, fEntityDecl);
                    if (fEntityDecl.inExternal || 
                        (entityName = getExternalEntityRefInAttrValue(fEntityDecl.value)) != null) {
                        return entityName;
                    }
                }
            }
            ampIndex = nonNormalizedValue.indexOf('&", ampIndex+1);
        }
        return null;
    
public java.lang.BooleangetFeatureDefault(java.lang.String featureId)
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

        for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
            if (RECOGNIZED_FEATURES[i].equals(featureId)) {
                return FEATURE_DEFAULTS[i];
            }
        }
        return null;
    
DTDGrammarBucketgetGrammarBucket()

        return fGrammarBucket;
    
public java.lang.ObjectgetPropertyDefault(java.lang.String propertyId)
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

        for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
            if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
                return PROPERTY_DEFAULTS[i];
            }
        }
        return null;
    
public java.lang.String[]getRecognizedFeatures()
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.

        return (String[])(RECOGNIZED_FEATURES.clone());
    
public java.lang.String[]getRecognizedProperties()
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.

        return (String[])(RECOGNIZED_PROPERTIES.clone());
    
protected voidhandleEndElement(org.apache.xerces.xni.QName element, org.apache.xerces.xni.Augmentations augs, boolean isEmpty)
Handle end element.


        // decrease element depth
        fElementDepth--;

        // validate
        if (fPerformValidation) {
            int elementIndex = fCurrentElementIndex;
            if (elementIndex != -1 && fCurrentContentSpecType != -1) {
                QName children[] = fElementChildren;
                int childrenOffset = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
                int childrenLength = fElementChildrenLength - childrenOffset;
                int result = checkContent(elementIndex, 
                                          children, childrenOffset, childrenLength);

                if (result != -1) {
                    fDTDGrammar.getElementDecl(elementIndex, fTempElementDecl);
                    if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 
                                                   "MSG_CONTENT_INVALID",
                                                   new Object[]{ element.rawname, "EMPTY"},
                                                   XMLErrorReporter.SEVERITY_ERROR);
                    }
                    else {
                        String messageKey = result != childrenLength ? 
                                            "MSG_CONTENT_INVALID" : "MSG_CONTENT_INCOMPLETE";
                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 
                                                   messageKey,
                                                   new Object[]{ element.rawname, 
                                                       fDTDGrammar.getContentSpecAsString(elementIndex)},
                                                   XMLErrorReporter.SEVERITY_ERROR);
                    }
                }
            }
            fElementChildrenLength = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
        }
        
        endNamespaceScope(fCurrentElement, augs, isEmpty);
        
        // now pop this element off the top of the element stack
        if (fElementDepth < -1) {
            throw new RuntimeException("FWK008 Element stack underflow");
        }
        if (fElementDepth < 0) {
            fCurrentElement.clear();
            fCurrentElementIndex = -1;
            fCurrentContentSpecType = -1;
            fInElementContent = false;

            // TO DO : fix this
            //
            // Check after document is fully parsed
            // (1) check that there was an element with a matching id for every
            //   IDREF and IDREFS attr (V_IDREF0)
            //
            if (fPerformValidation) {
                String value = fValidationState.checkIDRefID();
                if (value != null) {
                    fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN,
                                                "MSG_ELEMENT_WITH_ID_REQUIRED",
                                                new Object[]{value},
                                                XMLErrorReporter.SEVERITY_ERROR );
                }
            }
            return;
        }

        // If Namespace enable then localName != rawName
        fCurrentElement.setValues(fElementQNamePartsStack[fElementDepth]);

        fCurrentElementIndex = fElementIndexStack[fElementDepth];
        fCurrentContentSpecType = fContentSpecTypeStack[fElementDepth];
        fInElementContent = (fCurrentContentSpecType == XMLElementDecl.TYPE_CHILDREN);

    
protected booleanhandleStartElement(org.apache.xerces.xni.QName element, org.apache.xerces.xni.XMLAttributes attributes, org.apache.xerces.xni.Augmentations augs)
Handle element

return
true if validator is removed from the pipeline



        // VC: Root Element Type
        // see if the root element's name matches the one in DoctypeDecl 
        if (!fSeenRootElement) {
            // REVISIT: Here are current assumptions about validation features
            //          given that XMLSchema validator is in the pipeline
            //
            // http://xml.org/sax/features/validation = true
            // http://apache.org/xml/features/validation/schema = true
            //
            // [1] XML instance document only has reference to a DTD 
            //  Outcome: report validation errors only against dtd.
            //
            // [2] XML instance document has only XML Schema grammars:
            //  Outcome: report validation errors only against schemas (no errors produced from DTD validator)
            //
            // [3] XML instance document has DTD and XML schemas:
            // [a] if schema language is not set outcome - validation errors reported against both grammars: DTD and schemas.
            // [b] if schema language is set to XML Schema - do not report validation errors
            //         
            // if dynamic validation is on
            //            validate only against grammar we've found (depending on settings
            //            for schema feature)
            // 
            // 
            fPerformValidation = validate();
            fSeenRootElement = true;
            fValidationManager.setEntityState(fDTDGrammar);
            fValidationManager.setGrammarFound(fSeenDoctypeDecl);
            rootElementSpecified(element);
        }
        if (fDTDGrammar == null) {

            if (!fPerformValidation) {
                fCurrentElementIndex = -1;
                fCurrentContentSpecType = -1;
                fInElementContent = false;
            }
            if (fPerformValidation) {
                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 
                                           "MSG_GRAMMAR_NOT_FOUND",
                                           new Object[]{ element.rawname},
                                           XMLErrorReporter.SEVERITY_ERROR);
            }
            // modify pipeline
            if (fDocumentSource !=null ) {
                fDocumentSource.setDocumentHandler(fDocumentHandler);
                if (fDocumentHandler != null)
                    fDocumentHandler.setDocumentSource(fDocumentSource);
                return true;
            }
        }
        else {
            //  resolve the element
            fCurrentElementIndex = fDTDGrammar.getElementDeclIndex(element);
            //changed here.. new function for getContentSpecType
            fCurrentContentSpecType = fDTDGrammar.getContentSpecType(fCurrentElementIndex);
            if (fCurrentContentSpecType == -1 && fPerformValidation) {
                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 
                                           "MSG_ELEMENT_NOT_DECLARED",
                                           new Object[]{ element.rawname},
                                           XMLErrorReporter.SEVERITY_ERROR);
            }
            
            //  0. insert default attributes
            //  1. normalize the attributes
            //  2. validate the attrivute list.
            // TO DO: 
            //changed here.. also pass element name,
            addDTDDefaultAttrsAndValidate(element, fCurrentElementIndex, attributes);
        }

        // set element content state
        fInElementContent = fCurrentContentSpecType == XMLElementDecl.TYPE_CHILDREN;

        // increment the element depth, add this element's 
        // QName to its enclosing element 's children list
        fElementDepth++;
        if (fPerformValidation) {
            // push current length onto stack
            if (fElementChildrenOffsetStack.length <= fElementDepth) {
                int newarray[] = new int[fElementChildrenOffsetStack.length * 2];
                System.arraycopy(fElementChildrenOffsetStack, 0, newarray, 0, fElementChildrenOffsetStack.length);
                fElementChildrenOffsetStack = newarray;
            }
            fElementChildrenOffsetStack[fElementDepth] = fElementChildrenLength;

            // add this element to children
            if (fElementChildren.length <= fElementChildrenLength) {
                QName[] newarray = new QName[fElementChildrenLength * 2];
                System.arraycopy(fElementChildren, 0, newarray, 0, fElementChildren.length);
                fElementChildren = newarray;
            }
            QName qname = fElementChildren[fElementChildrenLength];
            if (qname == null) {
                for (int i = fElementChildrenLength; i < fElementChildren.length; i++) {
                    fElementChildren[i] = new QName();
                }
                qname = fElementChildren[fElementChildrenLength];
            }
            qname.setValues(element);
            fElementChildrenLength++;
        }

        // save current element information
        fCurrentElement.setValues(element);
        ensureStackCapacity(fElementDepth);
        fElementQNamePartsStack[fElementDepth].setValues(fCurrentElement); 
        fElementIndexStack[fElementDepth] = fCurrentElementIndex;
        fContentSpecTypeStack[fElementDepth] = fCurrentContentSpecType;
        startNamespaceScope(element, attributes, augs);
        return false;

    
public final booleanhasGrammar()

        
        return (fDTDGrammar != null);
    
public voidignorableWhitespace(org.apache.xerces.xni.XMLString text, org.apache.xerces.xni.Augmentations augs)
Ignorable whitespace. For this method to be called, the document source must have some way of determining that the text containing only whitespace characters should be considered ignorable. For example, the validator can determine if a length of whitespace characters in the document are ignorable based on the element content model.

param
text The ignorable whitespace.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.


        // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.ignorableWhitespace(text, augs);
        }

    
protected voidinit()
initialization


        // datatype validators
        if (fValidation || fDynamicValidation) {
            try {
                //REVISIT: datatypeRegistry + initialization of datatype 
                //         why do we cast to ListDatatypeValidator?
                fValID       = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDSymbol);
                fValIDRef    = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDREFSymbol);
                fValIDRefs   = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fIDREFSSymbol);
                fValENTITY   = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fENTITYSymbol);
                fValENTITIES = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fENTITIESSymbol);
                fValNMTOKEN  = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNMTOKENSymbol);
                fValNMTOKENS = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNMTOKENSSymbol);
                fValNOTATION = fDatatypeValidatorFactory.getBuiltInDV(XMLSymbols.fNOTATIONSymbol);

            }
            catch (Exception e) {
                // should never happen
                e.printStackTrace(System.err);
            }

        }

    
protected booleaninvalidStandaloneAttDef(org.apache.xerces.xni.QName element, org.apache.xerces.xni.QName attribute)
Returns true if invalid standalone attribute definition.

        // REVISIT: This obviously needs to be fixed! -Ac
        boolean state = true;
        /*
       if (fStandaloneReader == -1) {
          return false;
       }
       // we are normalizing a default att value...  this ok?
       if (element.rawname == -1) {
          return false;
       }
       return getAttDefIsExternal(element, attribute);
       */
        return state;
    
protected booleanisSpace(int c)

        return XMLChar.isSpace(c);
    
private booleannormalizeAttrValue(org.apache.xerces.xni.XMLAttributes attributes, int index)
Normalize the attribute value of a non CDATA attributes collapsing sequences of space characters (x20)

param
attributes The list of attributes
param
index The index of the attribute to normalize

        // vars
        boolean leadingSpace = true;
        boolean spaceStart = false;
        boolean readingNonSpace = false;
        int count = 0;
        int eaten = 0;
        String attrValue = attributes.getValue(index);
        char[] attValue = new char[attrValue.length()];

        fBuffer.setLength(0);
        attrValue.getChars(0, attrValue.length(), attValue, 0);
        for (int i = 0; i < attValue.length; i++) {

            if (attValue[i] == ' ") {

                // now the tricky part
                if (readingNonSpace) {
                    spaceStart = true;
                    readingNonSpace = false;
                }

                if (spaceStart && !leadingSpace) {
                    spaceStart = false;
                    fBuffer.append(attValue[i]);
                    count++;
                }
                else {
                    if (leadingSpace || !spaceStart) {
                        eaten ++;
                        /*** BUG #3512 ***
                        int entityCount = attributes.getEntityCount(index);
                        for (int j = 0;  j < entityCount; j++) {
                            int offset = attributes.getEntityOffset(index, j);
                            int length = attributes.getEntityLength(index, j);
                            if (offset <= i-eaten+1) {
                                if (offset+length >= i-eaten+1) {
                                    if (length > 0)
                                        length--;
                                }
                            } 
                            else {
                                if (offset > 0)
                                    offset--;
                            }
                            attributes.setEntityOffset(index, j, offset);
                            attributes.setEntityLength(index, j, length);
                        }
                        /***/
                    }
                }

            }
            else {
                readingNonSpace = true;
                spaceStart = false;
                leadingSpace = false;
                fBuffer.append(attValue[i]);
                count++;
            }
        }

        // check if the last appended character is a space.
        if (count > 0 && fBuffer.charAt(count-1) == ' ") {
            fBuffer.setLength(count-1);
            /*** BUG #3512 ***
            int entityCount = attributes.getEntityCount(index);
            for (int j=0;  j < entityCount; j++) {
                int offset = attributes.getEntityOffset(index, j);
                int length = attributes.getEntityLength(index, j);
                if (offset < count-1) {
                    if (offset+length == count) {
                        length--;
                    }
                } 
                else {
                    offset--;
                }
                attributes.setEntityOffset(index, j, offset);
                attributes.setEntityLength(index, j, length);
            }
            /***/
        }
        String newValue = fBuffer.toString();
        attributes.setValue(index, newValue);
        return ! attrValue.equals(newValue);
    
public voidprocessingInstruction(java.lang.String target, org.apache.xerces.xni.XMLString data, org.apache.xerces.xni.Augmentations augs)
A processing instruction. Processing instructions consist of a target name and, optionally, text data. The data is only meaningful to the application.

Typically, a processing instruction's data will contain a series of pseudo-attributes. These pseudo-attributes follow the form of element attributes but are not parsed or presented to the application as anything other than text. The application is responsible for parsing the data.

param
target The target.
param
data The data or null if none specified.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.


        // fixes E15.1
        if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
            fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
            if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 
                                               "MSG_CONTENT_INVALID_SPECIFIED",
                                               new Object[]{ fCurrentElement.rawname,
                                                             "EMPTY",
                                                             "processing instruction"},
                                               XMLErrorReporter.SEVERITY_ERROR);                
            }
        }
        // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.processingInstruction(target, data, augs);
        }
    
public voidreset(org.apache.xerces.xni.parser.XMLComponentManager componentManager)


        // clear grammars
        fDTDGrammar = null;
        fSeenDoctypeDecl = false;
        fInCDATASection = false;
        // initialize state
        fSeenRootElement = false;
        fInElementContent = false;
        fCurrentElementIndex = -1;
        fCurrentContentSpecType = -1;

        fRootElement.clear();

		fValidationState.resetIDTables();
		
		fGrammarBucket.clear();
		fElementDepth = -1;                      
		fElementChildrenLength = 0;
        
        boolean parser_settings;
        try {
        	parser_settings = componentManager.getFeature(PARSER_SETTINGS);  	
        }
        catch (XMLConfigurationException e){
        	parser_settings = true;
        }
        
        if (!parser_settings){
        	// parser settings have not been changed
			fValidationManager.addValidationState(fValidationState);
        	return;
        }

        // sax features
        try {
            fNamespaces = componentManager.getFeature(NAMESPACES);
        }
        catch (XMLConfigurationException e) {
            fNamespaces = true;
        }
        try {
            fValidation = componentManager.getFeature(VALIDATION);
        }
        catch (XMLConfigurationException e) {
            fValidation = false;
        }
        try {
            fDTDValidation = !(componentManager.getFeature(Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE));
        }
        catch (XMLConfigurationException e) {
            // must be in a schema-less configuration!
            fDTDValidation = true;
        }

        // Xerces features
        try {
            fDynamicValidation = componentManager.getFeature(DYNAMIC_VALIDATION);
        }
        catch (XMLConfigurationException e) {
            fDynamicValidation = false;
        }
        
        try {
            fBalanceSyntaxTrees = componentManager.getFeature(BALANCE_SYNTAX_TREES);
        }
        catch (XMLConfigurationException e) {
            fBalanceSyntaxTrees = false;
        }
        
        try {
            fWarnDuplicateAttdef = componentManager.getFeature(WARN_ON_DUPLICATE_ATTDEF);
        }
        catch (XMLConfigurationException e) {
            fWarnDuplicateAttdef = false;
        }
        
        try {
            fSchemaType = (String)componentManager.getProperty (Constants.JAXP_PROPERTY_PREFIX 
            + Constants.SCHEMA_LANGUAGE);           
        }
        catch (XMLConfigurationException e){
            fSchemaType = null;
        }

        fValidationManager= (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER);
        fValidationManager.addValidationState(fValidationState);      
        fValidationState.setUsingNamespaces(fNamespaces);
        
        // get needed components
        fErrorReporter = (XMLErrorReporter)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX+Constants.ERROR_REPORTER_PROPERTY);
        fSymbolTable = (SymbolTable)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX+Constants.SYMBOL_TABLE_PROPERTY);
        try {
            fGrammarPool= (XMLGrammarPool)componentManager.getProperty(GRAMMAR_POOL);
        } catch (XMLConfigurationException e) {
            fGrammarPool = null;
        }

        fDatatypeValidatorFactory = (DTDDVFactory)componentManager.getProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY);
		init();

    
private final voidrootElementSpecified(org.apache.xerces.xni.QName rootElement)
Root element specified.

        if (fPerformValidation) {
            String root1 = fRootElement.rawname;
            String root2 = rootElement.rawname;
            if (root1 == null || !root1.equals(root2)) {
                fErrorReporter.reportError( XMLMessageFormatter.XML_DOMAIN, 
                                            "RootElementTypeMustMatchDoctypedecl", 
                                            new Object[]{root1, root2}, 
                                            XMLErrorReporter.SEVERITY_ERROR);
            }
        }
    
public voidsetDocumentHandler(org.apache.xerces.xni.XMLDocumentHandler documentHandler)
Sets the document handler to receive information about the document.

        fDocumentHandler = documentHandler;
    
public voidsetDocumentSource(org.apache.xerces.xni.parser.XMLDocumentSource source)
Sets the document source

        fDocumentSource = source;
    
public voidsetFeature(java.lang.String featureId, boolean state)
Sets the state of a feature. This method is called by the component manager any time after reset when a feature changes state.

Note: 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 voidsetProperty(java.lang.String propertyId, java.lang.Object value)
Sets the value of a property. This method is called by the component manager any time after reset when a property changes value.

Note: 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 voidstartCDATA(org.apache.xerces.xni.Augmentations augs)
The start of a CDATA section.

param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.


        if (fPerformValidation && fInElementContent) {
            charDataInContent();
        }
        fInCDATASection = true;
        // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.startCDATA(augs);
        }

    
public voidstartDocument(org.apache.xerces.xni.XMLLocator locator, java.lang.String encoding, org.apache.xerces.xni.NamespaceContext namespaceContext, org.apache.xerces.xni.Augmentations augs)
The start of the document.

param
locator The system identifier of the entity if the entity is external, null otherwise.
param
encoding The auto-detected IANA encoding name of the entity stream. This value will be null in those situations where the entity encoding is not auto-detected (e.g. internal entities or a document entity that is parsed from a java.io.Reader).
param
namespaceContext The namespace context in effect at the start of this document. This object represents the current context. Implementors of this class are responsible for copying the namespace bindings from the the current context (and its parent contexts) if that information is important.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.


        // call handlers
        // get initial grammars
        if(fGrammarPool != null) {
            Grammar [] grammars = fGrammarPool.retrieveInitialGrammarSet(XMLGrammarDescription.XML_DTD);
            for(int i = 0; i<grammars.length; i++) {
                fGrammarBucket.putGrammar((DTDGrammar)grammars[i]);
            }
        }
        fDocLocation = locator;
        fNamespaceContext = namespaceContext;
   
        if (fDocumentHandler != null) {
            fDocumentHandler.startDocument(locator, encoding, namespaceContext, augs);
        }

    
public voidstartElement(org.apache.xerces.xni.QName element, org.apache.xerces.xni.XMLAttributes attributes, org.apache.xerces.xni.Augmentations augs)
The start of an element.

param
element The name of the element.
param
attributes The element attributes.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.


        handleStartElement(element, attributes, augs);
        // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.startElement(element, attributes, augs);

        }

    
public voidstartGeneralEntity(java.lang.String name, org.apache.xerces.xni.XMLResourceIdentifier identifier, java.lang.String encoding, org.apache.xerces.xni.Augmentations augs)
This method notifies the start of a general entity.

Note: This method is not called for entity references appearing as part of attribute values.

param
name The name of the general 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
exception
XNIException Thrown by handler to signal an error.

        if (fPerformValidation && fElementDepth >= 0 && fDTDGrammar != null) {
            fDTDGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
            // fixes E15.1
            if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
                fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 
                                           "MSG_CONTENT_INVALID_SPECIFIED",
                                           new Object[]{ fCurrentElement.rawname,
                                                         "EMPTY", "ENTITY"},
                                           XMLErrorReporter.SEVERITY_ERROR);                
            }
            if (fGrammarBucket.getStandalone()) {
                XMLDTDLoader.checkStandaloneEntityRef(name, fDTDGrammar, fEntityDecl, fErrorReporter);
            }
        }
        if (fDocumentHandler != null) {
            fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
        }
    
protected voidstartNamespaceScope(org.apache.xerces.xni.QName element, org.apache.xerces.xni.XMLAttributes attributes, org.apache.xerces.xni.Augmentations augs)

    
public voidtextDecl(java.lang.String version, java.lang.String encoding, org.apache.xerces.xni.Augmentations augs)
Notifies of the presence of a TextDecl line in an entity. If present, this method will be called immediately following the startParameterEntity call.

Note: This method is only called for external parameter entities referenced in the DTD.

param
version The XML version, or null if not specified.
param
encoding The IANA encoding name of the entity.
param
augs Additional information that may include infoset augmentations.
throws
XNIException Thrown by handler to signal an error.


        // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.textDecl(version, encoding, augs);
        }
    
public final booleanvalidate()

        // Do validation if all of the following are true:
        // 1. The JAXP Schema Language property is not XML Schema
        //    REVISIT: since only DTD and Schema are supported at this time,
        //             such checking is sufficient. but if more schema types
        //             are introduced in the future, we'll need to change it
        //             to something like
        //             (fSchemaType == null || fSchemaType == NS_XML_DTD)
        // 2. One of the following is true (validation features)
        // 2.1 Dynamic validation is off, and validation is on
        // 2.2 Dynamic validation is on, and DOCTYPE was seen
        // 3 Xerces schema validation feature is off, or DOCTYPE was seen.
        return (fSchemaType != Constants.NS_XMLSCHEMA) && 
               (!fDynamicValidation && fValidation ||
                fDynamicValidation && fSeenDoctypeDecl) &&
               (fDTDValidation || fSeenDoctypeDecl);
    
protected voidvalidateDTDattribute(org.apache.xerces.xni.QName element, java.lang.String attValue, XMLAttributeDecl attributeDecl)
Validate attributes in DTD fashion.


        switch (attributeDecl.simpleType.type) {
        case XMLSimpleType.TYPE_ENTITY: {                            
                // NOTE: Save this information because invalidStandaloneAttDef
                boolean isAlistAttribute = attributeDecl.simpleType.list;

                try {
                    if (isAlistAttribute) {
                        fValENTITIES.validate(attValue, fValidationState);
                    }
                    else {
                        fValENTITY.validate(attValue, fValidationState);
                    }
                }
                catch (InvalidDatatypeValueException ex) {
                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                               ex.getKey(),
                                               ex.getArgs(),
                                               XMLErrorReporter.SEVERITY_ERROR );

                }
                break;
            }

        case XMLSimpleType.TYPE_NOTATION:
        case XMLSimpleType.TYPE_ENUMERATION: {
                boolean found = false;
                String [] enumVals = attributeDecl.simpleType.enumeration;
                if (enumVals == null) {
                    found = false;
                }
                else
                    for (int i = 0; i < enumVals.length; i++) {
                        if (attValue == enumVals[i] || attValue.equals(enumVals[i])) {
                            found = true;
                            break;
                        }
                    }

                if (!found) {
                    StringBuffer enumValueString = new StringBuffer();
                    if (enumVals != null)
                        for (int i = 0; i < enumVals.length; i++) {
                            enumValueString.append(enumVals[i]+" ");
                        }
                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN, 
                                               "MSG_ATTRIBUTE_VALUE_NOT_IN_LIST",
                                               new Object[]{attributeDecl.name.rawname, attValue, enumValueString},
                                               XMLErrorReporter.SEVERITY_ERROR);
                }
                break;
            }

        case XMLSimpleType.TYPE_ID: {
                try {
                    fValID.validate(attValue, fValidationState);
                }
                catch (InvalidDatatypeValueException ex) {
                    fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                               ex.getKey(),
                                               ex.getArgs(),
                                               XMLErrorReporter.SEVERITY_ERROR );
                }
                break;
            }

        case XMLSimpleType.TYPE_IDREF: {
                boolean isAlistAttribute = attributeDecl.simpleType.list;//Caveat - Save this information because invalidStandaloneAttDef

                try {
                    if (isAlistAttribute) {
                        fValIDRefs.validate(attValue, fValidationState);
                    }
                    else {
                        fValIDRef.validate(attValue, fValidationState);
                    }
                }
                catch (InvalidDatatypeValueException ex) {
                    if (isAlistAttribute) {
                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                                   "IDREFSInvalid",
                                                   new Object[]{attValue},
                                                   XMLErrorReporter.SEVERITY_ERROR );
                    }
                    else {
                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                                   ex.getKey(),
                                                   ex.getArgs(),
                                                   XMLErrorReporter.SEVERITY_ERROR );
                    }

                }
                break;
            }

        case XMLSimpleType.TYPE_NMTOKEN: {
                boolean isAlistAttribute = attributeDecl.simpleType.list;//Caveat - Save this information because invalidStandaloneAttDef
                //changes fTempAttDef
                try {
                    if (isAlistAttribute) {
                        fValNMTOKENS.validate(attValue, fValidationState);
                    }
                    else {
                        fValNMTOKEN.validate(attValue, fValidationState);
                    }
                }
                catch (InvalidDatatypeValueException ex) {
                    if (isAlistAttribute) {
                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                                   "NMTOKENSInvalid",
                                                   new Object[] { attValue},
                                                   XMLErrorReporter.SEVERITY_ERROR);
                    }
                    else {
                        fErrorReporter.reportError(XMLMessageFormatter.XML_DOMAIN,
                                                   "NMTOKENInvalid",
                                                   new Object[] { attValue},
                                                   XMLErrorReporter.SEVERITY_ERROR);
                    }
                }
                break;
            }

        } // switch

    
public voidxmlDecl(java.lang.String version, java.lang.String encoding, java.lang.String standalone, org.apache.xerces.xni.Augmentations augs)
Notifies of the presence of an XMLDecl line in the document. If present, this method will be called immediately following the startDocument call.

param
version The XML version.
param
encoding The IANA encoding name of the document, or null if not specified.
param
standalone The standalone value, or null if not specified.
param
augs Additional information that may include infoset augmentations
throws
XNIException Thrown by handler to signal an error.


        // save standalone state
        fGrammarBucket.setStandalone(standalone != null && standalone.equals("yes"));

        // call handlers
        if (fDocumentHandler != null) {
            fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
        }