Package org.apache.xerces.validators.common

Source Code of org.apache.xerces.validators.common.XMLValidator

/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 1999,2000 The Apache Software Foundation.  All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution,
*    if any, must include the following acknowledgment: 
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowledgment may appear in the software itself,
*    if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Xerces" and "Apache Software Foundation" must
*    not be used to endorse or promote products derived from this
*    software without prior written permission. For written
*    permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
*    nor may "Apache" appear in their name, without prior written
*    permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation and was
* originally based on software copyright (c) 1999, International
* Business Machines, Inc., http://www.apache.org.  For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/

package org.apache.xerces.validators.common;

import org.apache.xerces.framework.XMLAttrList;
import org.apache.xerces.framework.XMLContentSpec;
import org.apache.xerces.framework.XMLDocumentHandler;
import org.apache.xerces.framework.XMLDocumentScanner;
import org.apache.xerces.framework.XMLErrorReporter;
import org.apache.xerces.readers.DefaultEntityHandler;
import org.apache.xerces.readers.XMLEntityHandler;
import org.apache.xerces.utils.ChunkyCharArray;
import org.apache.xerces.utils.Hash2intTable;
import org.apache.xerces.utils.NamespacesScope;
import org.apache.xerces.utils.QName;
import org.apache.xerces.utils.StringPool;
import org.apache.xerces.utils.XMLCharacterProperties;
import org.apache.xerces.utils.XMLMessages;
import org.apache.xerces.utils.ImplementationMessages;

import org.apache.xerces.parsers.DOMParser;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import org.xml.sax.InputSource;
import org.xml.sax.EntityResolver;
import org.xml.sax.Locator;
import org.xml.sax.helpers.LocatorImpl;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import java.io.IOException;

import java.util.Enumeration;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.util.Vector;

import org.apache.xerces.validators.dtd.DTDGrammar;

import org.apache.xerces.validators.schema.EquivClassComparator;
import org.apache.xerces.validators.schema.SchemaGrammar;
import org.apache.xerces.validators.schema.SchemaMessageProvider;
import org.apache.xerces.validators.schema.SchemaSymbols;
import org.apache.xerces.validators.schema.TraverseSchema;

import org.apache.xerces.validators.datatype.DatatypeValidatorFactoryImpl;
import org.apache.xerces.validators.datatype.DatatypeValidator;
import org.apache.xerces.validators.datatype.InvalidDatatypeValueException;
import org.apache.xerces.validators.datatype.StateMessageDatatype;
import org.apache.xerces.validators.datatype.IDREFDatatypeValidator;
import org.apache.xerces.validators.datatype.IDDatatypeValidator;
import org.apache.xerces.validators.datatype.ENTITYDatatypeValidator;

/**
* This class is the super all-in-one validator used by the parser.
*
* @version $Id: XMLValidator.java,v 1.87 2000/10/17 22:16:45 jeffreyr Exp $
*/
public final class XMLValidator
implements DefaultEntityHandler.EventHandler,
XMLEntityHandler.CharDataHandler,
XMLDocumentScanner.EventHandler,
NamespacesScope.NamespacesHandler {

   //
   // Constants
   //

   // debugging

   private static final boolean PRINT_EXCEPTION_STACK_TRACE = false;
   private static final boolean DEBUG_PRINT_ATTRIBUTES = false;
   private static final boolean DEBUG_PRINT_CONTENT = false;
   private static final boolean DEBUG_SCHEMA_VALIDATION = false;
   private static final boolean DEBUG_ELEMENT_CHILDREN = false;

   // Chunk size constants

   private static final int CHUNK_SHIFT = 8;           // 2^8 = 256
   private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
   private static final int CHUNK_MASK = CHUNK_SIZE - 1;
   private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT));   // 2^10 = 1k

   private Hashtable fIdDefs = null;


   private  StateMessageDatatype fStoreIDRef = new StateMessageDatatype() {
      private Hashtable fIdDefs;
      public Object getDatatypeObject(){
         return(Object) fIdDefs;
      }
      public int    getDatatypeState(){
         return IDREFDatatypeValidator.IDREF_STORE;
      }
      public void setDatatypeObject( Object data ){
         fIdDefs = (Hashtable) data;
      }
   };

   private StateMessageDatatype fResetID = new StateMessageDatatype() {
      public Object getDatatypeObject(){
         return(Object) null;
      }
      public int    getDatatypeState(){
         return IDDatatypeValidator.ID_CLEAR;
      }
      public void setDatatypeObject( Object data ){
      }
   };


   private StateMessageDatatype fResetIDRef = new StateMessageDatatype() {
      public Object getDatatypeObject(){
         return(Object) null;
      }
      public int    getDatatypeState(){
         return IDREFDatatypeValidator.IDREF_CLEAR;
      }
      public void setDatatypeObject( Object data ){
      }
   };

   private  StateMessageDatatype fValidateIDRef = new StateMessageDatatype() {
      public Object getDatatypeObject(){
         return(Object) null;
      }
      public int    getDatatypeState(){
         return IDREFDatatypeValidator.IDREF_VALIDATE;
      }
      public void setDatatypeObject( Object data ){
      }
   };


   private  StateMessageDatatype fValidateENTITYMsg = new StateMessageDatatype() {
      private  Object  packagedMessage = null;
      public Object getDatatypeObject(){
         return packagedMessage;
      }
      public int    getDatatypeState(){
         return ENTITYDatatypeValidator.ENTITY_INITIALIZE;//No state
      }
      public void setDatatypeObject( Object data ){
         packagedMessage = data;// Set Entity Handler
      }
   };

   /*
   private  StateMessageDatatype fValidateNOTATIONMsg = new StateMessageDatatype() {
       private  Object  packagedMessage = null;
       public Object getDatatypeObject(){
           return packagedMessage;
       }
       public int    getDatatypeState(){
           return NOTATIONDatatypeValidator.ENTITY_INITIALIZE;//No state
       }
       public void setDatatypeObject( Object data ){
           packagedMessage = data;// Set Entity Handler
       }
   };
   */





   //
   // Data
   //

   // REVISIT: The data should be regrouped and re-organized so that
   //          it's easier to find a meaningful field.

   // debugging

//    private static boolean DEBUG = false;

   // other

   // attribute validators

   private AttributeValidator fAttValidatorNOTATION = new AttValidatorNOTATION();
   private AttributeValidator fAttValidatorENUMERATION = new AttValidatorENUMERATION();
   private AttributeValidator fAttValidatorDATATYPE = null;

   // Package access for use by AttributeValidator classes.

   StringPool fStringPool = null;
   boolean fValidating = false;
   boolean fInElementContent = false;
   int fStandaloneReader = -1;


   // settings

   private boolean fValidationEnabled = false;
   private boolean fDynamicValidation = false;
   private boolean fSchemaValidation = true;
   private boolean fValidationEnabledByDynamic = false;
   private boolean fDynamicDisabledByValidation = false;
   private boolean fWarningOnDuplicateAttDef = false;
   private boolean fWarningOnUndeclaredElements = false;
   private boolean fLoadDTDGrammar = true;

   // declarations

   private int fDeclaration[];
   private XMLErrorReporter fErrorReporter = null;
   private DefaultEntityHandler fEntityHandler = null;
   private QName fCurrentElement = new QName();

   private ContentLeafNameTypeVector[] fContentLeafStack = new ContentLeafNameTypeVector[8];
   private int[] fValidationFlagStack = new int[8];

   private int[] fScopeStack = new int[8];
   private int[] fGrammarNameSpaceIndexStack = new int[8];

   private int[] fElementEntityStack = new int[8];
   private int[] fElementIndexStack = new int[8];
   private int[] fContentSpecTypeStack = new int[8];

   private static final int sizeQNameParts      = 8;
   private QName[] fElementQNamePartsStack      = new QName[sizeQNameParts];

   private QName[] fElementChildren = new QName[32];
   private int fElementChildrenLength = 0;
   private int[] fElementChildrenOffsetStack = new int[32];
   private int fElementDepth = -1;

   private boolean fNamespacesEnabled = false;
   private NamespacesScope fNamespacesScope = null;
   private int fNamespacesPrefix = -1;
   private QName fRootElement = new QName();
   private int fAttrListHandle = -1;
   private int fCurrentElementEntity = -1;
   private int fCurrentElementIndex = -1;
   private int fCurrentContentSpecType = -1;
   private boolean fSeenDoctypeDecl = false;

   private final int TOP_LEVEL_SCOPE = -1;
   private int fCurrentScope = TOP_LEVEL_SCOPE;
   private int fCurrentSchemaURI = -1;
   private int fEmptyURI = - 1;
   private int fXsiPrefix = - 1;
   private int fXsiURI = -2;
   private int fXsiTypeAttValue = -1;
   private DatatypeValidator fXsiTypeValidator = null;

   private Grammar fGrammar = null;
   private int fGrammarNameSpaceIndex = -1;
   private GrammarResolver fGrammarResolver = null;

   // state and stuff

   private boolean fScanningDTD = false;
   private XMLDocumentScanner fDocumentScanner = null;
   private boolean fCalledStartDocument = false;
   private XMLDocumentHandler fDocumentHandler = null;
   private XMLDocumentHandler.DTDHandler fDTDHandler = null;
   private boolean fSeenRootElement = false;
   private XMLAttrList fAttrList = null;
   private int fXMLLang = -1;
   private LocatorImpl fAttrNameLocator = null;
   private boolean fCheckedForSchema = false;
   private boolean fDeclsAreExternal = false;
   private StringPool.CharArrayRange fCurrentElementCharArrayRange = null;
   private char[] fCharRefData = null;
   private boolean fSendCharDataAsCharArray = false;
   private boolean fBufferDatatype = false;
   private StringBuffer fDatatypeBuffer = new StringBuffer();

   private QName fTempQName = new QName();
   private XMLAttributeDecl fTempAttDecl = new XMLAttributeDecl();
   private XMLAttributeDecl fTempAttributeDecl = new XMLAttributeDecl();
   private XMLElementDecl fTempElementDecl = new XMLElementDecl();

   private boolean fGrammarIsDTDGrammar = false;
   private boolean fGrammarIsSchemaGrammar = false;

   private boolean fNeedValidationOff = false;

   // symbols

   private int fEMPTYSymbol = -1;
   private int fANYSymbol = -1;
   private int fMIXEDSymbol = -1;
   private int fCHILDRENSymbol = -1;
   private int fCDATASymbol = -1;
   private int fIDSymbol = -1;
   private int fIDREFSymbol = -1;
   private int fIDREFSSymbol = -1;
   private int fENTITYSymbol = -1;
   private int fENTITIESSymbol = -1;
   private int fNMTOKENSymbol = -1;
   private int fNMTOKENSSymbol = -1;
   private int fNOTATIONSymbol = -1;
   private int fENUMERATIONSymbol = -1;
   private int fREQUIREDSymbol = -1;
   private int fFIXEDSymbol = -1;
   private int fDATATYPESymbol = -1;
   private int fEpsilonIndex = -1;


   //Datatype Registry

   private DatatypeValidatorFactoryImpl fDataTypeReg = null;
   private DatatypeValidator            fValID   = null;
   private DatatypeValidator            fValIDRef    = null;
   private DatatypeValidator            fValIDRefs   = null;
   private DatatypeValidator            fValENTITY   = null;
   private DatatypeValidator            fValENTITIES = null;
   private DatatypeValidator            fValNMTOKEN  = null;
   private DatatypeValidator            fValNMTOKENS = null;
   private DatatypeValidator            fValNOTATION = null;


   //
   // Constructors
   //

   /** Constructs an XML validator. */
   public XMLValidator(StringPool stringPool,
                       XMLErrorReporter errorReporter,
                       DefaultEntityHandler entityHandler,
                       XMLDocumentScanner documentScanner) {

      // keep references
      fStringPool = stringPool;
      fErrorReporter = errorReporter;
      fEntityHandler = entityHandler;
      fDocumentScanner = documentScanner;

      fEmptyURI = fStringPool.addSymbol("");
      fXsiURI = fStringPool.addSymbol(SchemaSymbols.URI_XSI);
      // initialize
      fAttrList = new XMLAttrList(fStringPool);
      entityHandler.setEventHandler(this);
      entityHandler.setCharDataHandler(this);
      fDocumentScanner.setEventHandler(this);

      for (int i = 0; i < sizeQNameParts; i++) {
         fElementQNamePartsStack[i] = new QName();
      }
      init();

   } // <init>(StringPool,XMLErrorReporter,DefaultEntityHandler,XMLDocumentScanner)

   public void setGrammarResolver(GrammarResolver grammarResolver){
      fGrammarResolver = grammarResolver;
   }

   //
   // Public methods
   //

   // initialization

   /** Set char data processing preference and handlers. */
   public void initHandlers(boolean sendCharDataAsCharArray,
                            XMLDocumentHandler docHandler,
                            XMLDocumentHandler.DTDHandler dtdHandler) {

      fSendCharDataAsCharArray = sendCharDataAsCharArray;
      fEntityHandler.setSendCharDataAsCharArray(fSendCharDataAsCharArray);
      fDocumentHandler = docHandler;
      fDTDHandler = dtdHandler;

   } // initHandlers(boolean,XMLDocumentHandler,XMLDocumentHandler.DTDHandler)

   /** Reset or copy. */
   public void resetOrCopy(StringPool stringPool) throws Exception {
      fAttrList = new XMLAttrList(stringPool);
      resetCommon(stringPool);
   }

   /** Reset. */
   public void reset(StringPool stringPool) throws Exception {
      fAttrList.reset(stringPool);
      resetCommon(stringPool);
   }


   // settings

   /**
    * Turning on validation/dynamic turns on validation if it is off, and
    * this is remembered.  Turning off validation DISABLES validation/dynamic
    * if it is on.  Turning off validation/dynamic DOES NOT turn off
    * validation if it was explicitly turned on, only if it was turned on
    * BECAUSE OF the call to turn validation/dynamic on.  Turning on
    * validation will REENABLE and turn validation/dynamic back on if it
    * was disabled by a call that turned off validation while
    * validation/dynamic was enabled.
    */
   public void setValidationEnabled(boolean flag) throws Exception {
      fValidationEnabled = flag;
      fValidationEnabledByDynamic = false;
      if (fValidationEnabled) {
         if (fDynamicDisabledByValidation) {
            fDynamicValidation = true;
            fDynamicDisabledByValidation = false;
         }
      } else if (fDynamicValidation) {
         fDynamicValidation = false;
         fDynamicDisabledByValidation = true;
      }
      fValidating = fValidationEnabled;
   }

   /** Returns true if validation is enabled. */
   public boolean getValidationEnabled() {
      return fValidationEnabled;
   }

   /** Sets whether Schema support is on/off. */
   public void setSchemaValidationEnabled(boolean flag) {
      fSchemaValidation = flag;
   }

   /** Returns true if Schema support is on. */
   public boolean getSchemaValidationEnabled() {
      return fSchemaValidation;
   }

   /** Sets whether validation is dynamic. */
   public void setDynamicValidationEnabled(boolean flag) throws Exception {
      fDynamicValidation = flag;
      fDynamicDisabledByValidation = false;
      if (!fDynamicValidation) {
         if (fValidationEnabledByDynamic) {
            fValidationEnabled = false;
            fValidationEnabledByDynamic = false;
         }
      } else if (!fValidationEnabled) {
         fValidationEnabled = true;
         fValidationEnabledByDynamic = true;
      }
      fValidating = fValidationEnabled;
   }

   /** Returns true if validation is dynamic. */
   public boolean getDynamicValidationEnabled() {
      return fDynamicValidation;
   }

   /** Sets fLoadDTDGrammar when validation is off **/
   public void setLoadDTDGrammar(boolean loadDG){
      if (fValidating) {
         fLoadDTDGrammar = true;
      } else {
         fLoadDTDGrammar = loadDG;
      }
   }

   /** Returns fLoadDTDGrammar **/
   public boolean getLoadDTDGrammar() {
      return fLoadDTDGrammar;
   }

   /** Sets whether namespaces are enabled. */
   public void setNamespacesEnabled(boolean flag) {
      fNamespacesEnabled = flag;
   }

   /** Returns true if namespaces are enabled. */
   public boolean getNamespacesEnabled() {
      return fNamespacesEnabled;
   }

   /** Sets whether duplicate attribute definitions signal a warning. */
   public void setWarningOnDuplicateAttDef(boolean flag) {
      fWarningOnDuplicateAttDef = flag;
   }

   /** Returns true if duplicate attribute definitions signal a warning. */
   public boolean getWarningOnDuplicateAttDef() {
      return fWarningOnDuplicateAttDef;
   }

   /** Sets whether undeclared elements signal a warning. */
   public void setWarningOnUndeclaredElements(boolean flag) {
      fWarningOnUndeclaredElements = flag;
   }

   /** Returns true if undeclared elements signal a warning. */
   public boolean getWarningOnUndeclaredElements() {
      return fWarningOnUndeclaredElements;
   }

   //
   // DefaultEntityHandler.EventHandler methods
   //

   /** Start entity reference. */
   public void startEntityReference(int entityName, int entityType, int entityContext) throws Exception {
      fDocumentHandler.startEntityReference(entityName, entityType, entityContext);
   }

   /** End entity reference. */
   public void endEntityReference(int entityName, int entityType, int entityContext) throws Exception {
      fDocumentHandler.endEntityReference(entityName, entityType, entityContext);
   }

   /** Send end of input notification. */
   public void sendEndOfInputNotifications(int entityName, boolean moreToFollow) throws Exception {
      fDocumentScanner.endOfInput(entityName, moreToFollow);
      /***
      if (fScanningDTD) {
          fDTDImporter.sendEndOfInputNotifications(entityName, moreToFollow);
      }
      /***/
   }

   /** Send reader change notifications. */
   public void sendReaderChangeNotifications(XMLEntityHandler.EntityReader reader, int readerId) throws Exception {
      fDocumentScanner.readerChange(reader, readerId);
      /***
      if (fScanningDTD) {
          fDTDImporter.sendReaderChangeNotifications(reader, readerId);
      }
      /***/
   }

   /** External entity standalone check. */
   public boolean externalEntityStandaloneCheck() {
      return(fStandaloneReader != -1 && fValidating);
   }

   /** Return true if validating. */
   public boolean getValidating() {
      return fValidating;
   }

   //
   // XMLEntityHandler.CharDataHandler methods
   //

   /** Process characters. */
   public void processCharacters(char[] chars, int offset, int length) throws Exception {
      if (fValidating) {
         if (fInElementContent || fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
            charDataInContent();
         }
         if (fBufferDatatype) {
            fDatatypeBuffer.append(chars, offset, length);
         }
      }
      fDocumentHandler.characters(chars, offset, length);
   }

   /** Process characters. */
   public void processCharacters(int data) throws Exception {
      if (fValidating) {
         if (fInElementContent || fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
            charDataInContent();
         }
         if (fBufferDatatype) {
            fDatatypeBuffer.append(fStringPool.toString(data));
         }
      }
      fDocumentHandler.characters(data);
   }

   /** Process whitespace. */
   public void processWhitespace(char[] chars, int offset, int length)
   throws Exception {

      if (fInElementContent) {
         if (fStandaloneReader != -1 && fValidating && getElementDeclIsExternal(fCurrentElementIndex)) {
            reportRecoverableXMLError(XMLMessages.MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE,
                                      XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION);
         }
         fDocumentHandler.ignorableWhitespace(chars, offset, length);
      } else {
         if (fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
            charDataInContent();
         }
         fDocumentHandler.characters(chars, offset, length);
      }

   } // processWhitespace(char[],int,int)

   /** Process whitespace. */
   public void processWhitespace(int data) throws Exception {

      if (fInElementContent) {
         if (fStandaloneReader != -1 && fValidating && getElementDeclIsExternal(fCurrentElementIndex)) {
            reportRecoverableXMLError(XMLMessages.MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE,
                                      XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION);
         }
         fDocumentHandler.ignorableWhitespace(data);
      } else {
         if (fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
            charDataInContent();
         }
         fDocumentHandler.characters(data);
      }

   } // processWhitespace(int)

   //
   // XMLDocumentScanner.EventHandler methods
   //

   /** Scans element type. */
   public void scanElementType(XMLEntityHandler.EntityReader entityReader,
                               char fastchar, QName element) throws Exception {

      if (!fNamespacesEnabled) {
         element.clear();
         element.localpart = entityReader.scanName(fastchar);
         element.rawname = element.localpart;
      } else {
         entityReader.scanQName(fastchar, element);
         if (entityReader.lookingAtChar(':', false)) {
            fErrorReporter.reportError(fErrorReporter.getLocator(),
                                       XMLMessages.XML_DOMAIN,
                                       XMLMessages.MSG_TWO_COLONS_IN_QNAME,
                                       XMLMessages.P5_INVALID_CHARACTER,
                                       null,
                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
            entityReader.skipPastNmtoken(' ');
         }
      }

   } // scanElementType(XMLEntityHandler.EntityReader,char,QName)

   /** Scans expected element type. */
   public boolean scanExpectedElementType(XMLEntityHandler.EntityReader entityReader,
                                          char fastchar, QName element)
   throws Exception {

      if (fCurrentElementCharArrayRange == null) {
         fCurrentElementCharArrayRange = fStringPool.createCharArrayRange();
      }
      fStringPool.getCharArrayRange(fCurrentElement.rawname, fCurrentElementCharArrayRange);
      return entityReader.scanExpectedName(fastchar, fCurrentElementCharArrayRange);

   } // scanExpectedElementType(XMLEntityHandler.EntityReader,char,QName)

   /** Scans attribute name. */
   public void scanAttributeName(XMLEntityHandler.EntityReader entityReader,
                                 QName element, QName attribute)
   throws Exception {

      if (!fSeenRootElement) {
         fSeenRootElement = true;
         rootElementSpecified(element);
         fStringPool.resetShuffleCount();
      }

      if (!fNamespacesEnabled) {
         attribute.clear();
         attribute.localpart = entityReader.scanName('=');
         attribute.rawname = attribute.localpart;
      } else {
         entityReader.scanQName('=', attribute);
         if (entityReader.lookingAtChar(':', false)) {
            fErrorReporter.reportError(fErrorReporter.getLocator(),
                                       XMLMessages.XML_DOMAIN,
                                       XMLMessages.MSG_TWO_COLONS_IN_QNAME,
                                       XMLMessages.P5_INVALID_CHARACTER,
                                       null,
                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
            entityReader.skipPastNmtoken(' ');
         }
      }

   } // scanAttributeName(XMLEntityHandler.EntityReader,QName,QName)

   /** Call start document. */
   public void callStartDocument() throws Exception {

      if (!fCalledStartDocument) {
         fDocumentHandler.startDocument();
         fCalledStartDocument = true;
      }
   }

   /** Call end document. */
   public void callEndDocument() throws Exception {

      if (fCalledStartDocument) {
         fDocumentHandler.endDocument();
      }
   }

   /** Call XML declaration. */
   public void callXMLDecl(int version, int encoding, int standalone) throws Exception {
      fDocumentHandler.xmlDecl(version, encoding, standalone);
   }
   public void callStandaloneIsYes() throws Exception {
      // standalone = "yes". said XMLDocumentScanner.
      fStandaloneReader = fEntityHandler.getReaderId() ;

   }



   /** Call text declaration. */
   public void callTextDecl(int version, int encoding) throws Exception {
      fDocumentHandler.textDecl(version, encoding);
   }

   /**
    * Signal the scanning of an element name in a start element tag.
    *
    * @param element Element name scanned.
    */
   public void element(QName element) throws Exception {
      fAttrListHandle = -1;
   }
   /**
    * Signal the scanning of an attribute associated to the previous
    * start element tag.
    *
    * @param element Element name scanned.
    * @param attrName Attribute name scanned.
    * @param attrValue The string pool index of the attribute value.
    */
   public boolean attribute(QName element, QName attrName, int attrValue) throws Exception {
      if (fAttrListHandle == -1) {
         fAttrListHandle = fAttrList.startAttrList();
      }

      // if fAttrList.addAttr returns -1, indicates duplicate att in start tag of an element.
      // specified: true, search : true
      return fAttrList.addAttr(attrName, attrValue, fCDATASymbol, true, true) == -1;
   }

   /** Call start element. */
   public void callStartElement(QName element) throws Exception {

      if ( DEBUG_SCHEMA_VALIDATION )
         System.out.println("\n=======StartElement : " + fStringPool.toString(element.localpart));


      //
      // 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)
      //

      if (!fSeenRootElement) {
         fSeenRootElement = true;
         rootElementSpecified(element);
         fStringPool.resetShuffleCount();
      }

      if (fGrammar != null && fGrammarIsDTDGrammar) {
         fAttrListHandle = addDTDDefaultAttributes(element, fAttrList, fAttrListHandle, fValidating, fStandaloneReader != -1);
      }

      fCheckedForSchema = true;
      if (fNamespacesEnabled) {
         bindNamespacesToElementAndAttributes(element, fAttrList);
      }

      validateElementAndAttributes(element, fAttrList);
      if (fAttrListHandle != -1) {
         fAttrList.endAttrList();
      }

      fDocumentHandler.startElement(element, fAttrList, fAttrListHandle);
      fAttrListHandle = -1;

      //before we increment the element depth, add this element's QName to its enclosing element 's children list
      fElementDepth++;
      //if (fElementDepth >= 0) {
      if (fValidating) {
         // 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++;

         if (DEBUG_ELEMENT_CHILDREN) {
            printChildren();
            printStack();
         }
      }

      // One more level of depth
      //fElementDepth++;

      ensureStackCapacity(fElementDepth);
      fCurrentElement.setValues(element);
      fCurrentElementEntity = fEntityHandler.getReaderId();

      fElementQNamePartsStack[fElementDepth].setValues(fCurrentElement);

      fElementEntityStack[fElementDepth] = fCurrentElementEntity;
      fElementIndexStack[fElementDepth] = fCurrentElementIndex;
      fContentSpecTypeStack[fElementDepth] = fCurrentContentSpecType;

      if (fNeedValidationOff) {
         fValidating = false;
         fNeedValidationOff = false;
      }

      if (fValidating && fGrammarIsSchemaGrammar) {
         pushContentLeafStack();
      }

      fValidationFlagStack[fElementDepth] = fValidating ? 0 : -1;

      fScopeStack[fElementDepth] = fCurrentScope;
      fGrammarNameSpaceIndexStack[fElementDepth] = fGrammarNameSpaceIndex;

   } // callStartElement(QName)

   private void pushContentLeafStack() throws Exception {
      int contentType = getContentSpecType(fCurrentElementIndex);
      if ( contentType == XMLElementDecl.TYPE_CHILDREN) {
         XMLContentModel cm = getElementContentModel(fCurrentElementIndex);
         ContentLeafNameTypeVector cv = cm.getContentLeafNameTypeVector();
         if (cm != null) {
            fContentLeafStack[fElementDepth] = cv;
         }
      }
   }

   private void ensureStackCapacity ( int newElementDepth) {

      if (newElementDepth == fElementQNamePartsStack.length ) {
         int[] newStack = new int[newElementDepth * 2];
         System.arraycopy(fScopeStack, 0, newStack, 0, newElementDepth);
         fScopeStack = newStack;

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

         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();
            }
         }

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

         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;

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

         ContentLeafNameTypeVector[] newStackV = new ContentLeafNameTypeVector[newElementDepth * 2];
         System.arraycopy(fContentLeafStack, 0, newStackV, 0, newElementDepth);
         fContentLeafStack = newStackV;
      }
   }

   /** Call end element. */
   public void callEndElement(int readerId) throws Exception {
      if ( DEBUG_SCHEMA_VALIDATION )
         System.out.println("=======EndElement : " + fStringPool.toString(fCurrentElement.localpart)+"\n");

      int prefixIndex = fCurrentElement.prefix;
      int elementType = fCurrentElement.rawname;

      if (fCurrentElementEntity != readerId) {
         fErrorReporter.reportError(fErrorReporter.getLocator(),
                                    XMLMessages.XML_DOMAIN,
                                    XMLMessages.MSG_ELEMENT_ENTITY_MISMATCH,
                                    XMLMessages.P78_NOT_WELLFORMED,
                                    new Object[] { fStringPool.toString(elementType)},
                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
      }

      fElementDepth--;
      if (fValidating) {
         int elementIndex = fCurrentElementIndex;
         if (elementIndex != -1 && fCurrentContentSpecType != -1) {
            QName children[] = fElementChildren;
            int childrenOffset = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
            int childrenLength = fElementChildrenLength - childrenOffset;
            if (DEBUG_ELEMENT_CHILDREN) {
               System.out.println("endElement("+fStringPool.toString(fCurrentElement.rawname)+')');
               System.out.println("fCurrentContentSpecType : " + fCurrentContentSpecType );
               System.out.print("offset: ");
               System.out.print(childrenOffset);
               System.out.print(", length: ");
               System.out.print(childrenLength);
               System.out.println();
               printChildren();
               printStack();
            }
            int result = checkContent(elementIndex,
                                      children, childrenOffset, childrenLength);

            if ( DEBUG_SCHEMA_VALIDATION )
               System.out.println("!!!!!!!!In XMLValidator, the return value from checkContent : " + result);

            if (result != -1) {
               int majorCode = result != childrenLength ? XMLMessages.MSG_CONTENT_INVALID : XMLMessages.MSG_CONTENT_INCOMPLETE;
               fGrammar.getElementDecl(elementIndex, fTempElementDecl);
               if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
                  reportRecoverableXMLError(majorCode,
                                            0,
                                            fStringPool.toString(elementType),
                                            "EMPTY");
               } else
                  reportRecoverableXMLError(majorCode,
                                            0,
                                            fStringPool.toString(elementType),
                                            XMLContentSpec.toString(fGrammar, fStringPool, fTempElementDecl.contentSpecIndex));
            }
         }
         fElementChildrenLength = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
      }
      fDocumentHandler.endElement(fCurrentElement);
      if (fNamespacesEnabled) {
         fNamespacesScope.decreaseDepth();
      }

      // now pop this element off the top of the element stack
      //if (fElementDepth-- < 0) {
      if (fElementDepth < -1) {
         throw new RuntimeException("FWK008 Element stack underflow");
      }
      if (fElementDepth < 0) {
         fCurrentElement.clear();
         fCurrentElementEntity = -1;
         fCurrentElementIndex = -1;
         fCurrentContentSpecType = -1;
         fInElementContent = false;
         //
         // 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 (fValidating ) {
            try {
               this.fValIDRef.validate( null, this.fValidateIDRef );  
               this.fValIDRefs.validate( null, this.fValidateIDRef );
            } catch ( InvalidDatatypeValueException ex ) {
               reportRecoverableXMLError( ex.getMajorCode(), ex.getMinorCode(),
                                          ex.getMessage() );


            }
         }

         try {//Reset datatypes state
            this.fValID.validate( null, this.fResetID );
            this.fValIDRef.validate(null, this.fResetIDRef );
            this.fValIDRefs.validate(null, this.fResetID );
         } catch ( InvalidDatatypeValueException ex ) {
            System.err.println("Error re-Initializing: ID,IDRef,IDRefs pools" );
         }
         return;
      }


      //restore enclosing element to all the "current" variables
      // REVISIT: Validation. This information needs to be stored.
      fCurrentElement.prefix = -1;


      if (fNamespacesEnabled) { //If Namespace enable then localName != rawName
         fCurrentElement.localpart = fElementQNamePartsStack[fElementDepth].localpart;
      } else {//REVISIT - jeffreyr - This is so we still do old behavior when namespace is off
         fCurrentElement.localpart = fElementQNamePartsStack[fElementDepth].rawname;
      }
      fCurrentElement.rawname      = fElementQNamePartsStack[fElementDepth].rawname;
      fCurrentElement.uri          = fElementQNamePartsStack[fElementDepth].uri;
      fCurrentElement.prefix       = fElementQNamePartsStack[fElementDepth].prefix;


      fCurrentElementEntity = fElementEntityStack[fElementDepth];
      fCurrentElementIndex = fElementIndexStack[fElementDepth];
      fCurrentContentSpecType = fContentSpecTypeStack[fElementDepth];

      fValidating = fValidationFlagStack[fElementDepth] == 0 ? true : false;

      fCurrentScope = fScopeStack[fElementDepth]

      //if ( DEBUG_SCHEMA_VALIDATION ) {

/****
System.out.println("+++++ currentElement : " + fStringPool.toString(elementType)+
                   "\n fCurrentElementIndex : " + fCurrentElementIndex +
                   "\n fCurrentScope : " + fCurrentScope +
                   "\n fCurrentContentSpecType : " + fCurrentContentSpecType +
                   "\n++++++++++++++++++++++++++++++++++++++++++++++++" );
/****/
      //}

      // if enclosing element's Schema is different, need to switch "context"
      if ( fGrammarNameSpaceIndex != fGrammarNameSpaceIndexStack[fElementDepth] ) {
         fGrammarNameSpaceIndex = fGrammarNameSpaceIndexStack[fElementDepth];
         if ( fValidating && fGrammarIsSchemaGrammar )
            if ( !switchGrammar(fGrammarNameSpaceIndex) ) {
               reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR, XMLMessages.SCHEMA_GENERIC_ERROR,
                                         "Grammar with uri 1: " + fStringPool.toString(fGrammarNameSpaceIndex)
                                         + " , can not found");
            }
      }

      if (fValidating) {
         fBufferDatatype = false;
      }
      fInElementContent = (fCurrentContentSpecType == XMLElementDecl.TYPE_CHILDREN);

   } // callEndElement(int)

   /** Call start CDATA section. */
   public void callStartCDATA() throws Exception {
      fDocumentHandler.startCDATA();
   }

   /** Call end CDATA section. */
   public void callEndCDATA() throws Exception {
      fDocumentHandler.endCDATA();
   }

   /** Call characters. */
   public void callCharacters(int ch) throws Exception {

      if (fCharRefData == null) {
         fCharRefData = new char[2];
      }
      int count = (ch < 0x10000) ? 1 : 2;
      if (count == 1) {
         fCharRefData[0] = (char)ch;
      } else {
         fCharRefData[0] = (char)(((ch-0x00010000)>>10)+0xd800);
         fCharRefData[1] = (char)(((ch-0x00010000)&0x3ff)+0xdc00);
      }
      if (fValidating && (fInElementContent || fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY)) {
         charDataInContent();
      }
      if (fValidating) {
         if (fBufferDatatype) {
            fDatatypeBuffer.append(fCharRefData,0,1);
         }
      }
      if (fSendCharDataAsCharArray) {
         fDocumentHandler.characters(fCharRefData, 0, count);
      } else {
         int index = fStringPool.addString(new String(fCharRefData, 0, count));
         fDocumentHandler.characters(index);
      }

   } // callCharacters(int)

   /** Call processing instruction. */
   public void callProcessingInstruction(int target, int data) throws Exception {
      fDocumentHandler.processingInstruction(target, data);
   }

   /** Call comment. */
   public void callComment(int comment) throws Exception {
      fDocumentHandler.comment(comment);
   }

   //
   // NamespacesScope.NamespacesHandler methods
   //

   /** Start a new namespace declaration scope. */
   public void startNamespaceDeclScope(int prefix, int uri) throws Exception {
      fDocumentHandler.startNamespaceDeclScope(prefix, uri);
   }

   /** End a namespace declaration scope. */
   public void endNamespaceDeclScope(int prefix) throws Exception {
      fDocumentHandler.endNamespaceDeclScope(prefix);
   }

   // attributes


   // other

   /** Sets the root element. */
   public void setRootElementType(QName rootElement) {
      fRootElement.setValues(rootElement);
   }

   /**
    * Returns true if the element declaration is external.
    * <p>
    * <strong>Note:</strong> This method is primarilly useful for
    * DTDs with internal and external subsets.
    */
   private boolean getElementDeclIsExternal(int elementIndex) {
      /*if (elementIndex < 0 || elementIndex >= fElementCount) {
          return false;
      }
      int chunk = elementIndex >> CHUNK_SHIFT;
      int index = elementIndex & CHUNK_MASK;
      return (fElementDeclIsExternal[chunk][index] != 0);
      */

      if (fGrammarIsDTDGrammar ) {
         return((DTDGrammar) fGrammar).getElementDeclIsExternal(elementIndex);
      }
      return false;
   }

   /** Returns the content spec type for an element index. */
   public int getContentSpecType(int elementIndex) {

      int contentSpecType = -1;
      if ( elementIndex > -1) {
         if ( fGrammar.getElementDecl(elementIndex,fTempElementDecl) ) {
            contentSpecType = fTempElementDecl.type;
         }
      }
      return contentSpecType;
   }

   /** Returns the content spec handle for an element index. */
   public int getContentSpecHandle(int elementIndex) {
      int contentSpecHandle = -1;
      if ( elementIndex > -1) {
         if ( fGrammar.getElementDecl(elementIndex,fTempElementDecl) ) {
            contentSpecHandle = fTempElementDecl.contentSpecIndex;
         }
      }
      return contentSpecHandle;
   }

   //
   // Protected methods
   //

   // error reporting

   /** Report a recoverable xml error. */
   protected void reportRecoverableXMLError(int majorCode, int minorCode)
   throws Exception {

      fErrorReporter.reportError(fErrorReporter.getLocator(),
                                 XMLMessages.XML_DOMAIN,
                                 majorCode,
                                 minorCode,
                                 null,
                                 XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);

   } // reportRecoverableXMLError(int,int)

   /** Report a recoverable xml error. */
   protected void reportRecoverableXMLError(int majorCode, int minorCode,
                                            int stringIndex1)
   throws Exception {

      Object[] args = { fStringPool.toString(stringIndex1)};
      fErrorReporter.reportError(fErrorReporter.getLocator(),
                                 XMLMessages.XML_DOMAIN,
                                 majorCode,
                                 minorCode,
                                 args,
                                 XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);

   } // reportRecoverableXMLError(int,int,int)

   /** Report a recoverable xml error. */
   protected void reportRecoverableXMLError(int majorCode, int minorCode,
                                            String string1) throws Exception {

      Object[] args = { string1};
      fErrorReporter.reportError(fErrorReporter.getLocator(),
                                 XMLMessages.XML_DOMAIN,
                                 majorCode,
                                 minorCode,
                                 args,
                                 XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);

   } // reportRecoverableXMLError(int,int,String)

   /** Report a recoverable xml error. */
   protected void reportRecoverableXMLError(int majorCode, int minorCode,
                                            int stringIndex1, int stringIndex2)
   throws Exception {

      Object[] args = { fStringPool.toString(stringIndex1), fStringPool.toString(stringIndex2)};
      fErrorReporter.reportError(fErrorReporter.getLocator(),
                                 XMLMessages.XML_DOMAIN,
                                 majorCode,
                                 minorCode,
                                 args,
                                 XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);

   } // reportRecoverableXMLError(int,int,int,int)

   /** Report a recoverable xml error. */
   protected void reportRecoverableXMLError(int majorCode, int minorCode,
                                            String string1, String string2)
   throws Exception {

      Object[] args = { string1, string2};
      fErrorReporter.reportError(fErrorReporter.getLocator(),
                                 XMLMessages.XML_DOMAIN,
                                 majorCode,
                                 minorCode,
                                 args,
                                 XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);

   } // reportRecoverableXMLError(int,int,String,String)

   /** Report a recoverable xml error. */
   protected void reportRecoverableXMLError(int majorCode, int minorCode,
                                            String string1, String string2,
                                            String string3) throws Exception {

      Object[] args = { string1, string2, string3};
      fErrorReporter.reportError(fErrorReporter.getLocator(),
                                 XMLMessages.XML_DOMAIN,
                                 majorCode,
                                 minorCode,
                                 args,
                                 XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);

   } // reportRecoverableXMLError(int,int,String,String,String)

   // content spec

   /**
    * Returns information about which elements can be placed at a particular point
    * in the passed element's content model.
    * <p>
    * Note that the incoming content model to test must be valid at least up to
    * the insertion point. If not, then -1 will be returned and the info object
    * will not have been filled in.
    * <p>
    * If, on return, the info.isValidEOC flag is set, then the 'insert after'
    * elemement is a valid end of content, i.e. nothing needs to be inserted
    * after it to make the parent element's content model valid.
    *
    * @param elementIndex The index within the <code>ElementDeclPool</code> of the
    *                     element which is being querying.
    * @param fullyValid Only return elements that can be inserted and still
    *                   maintain the validity of subsequent elements past the
    *                   insertion point (if any).  If the insertion point is at
    *                   the end, and this is true, then only elements that can
    *                   be legal final states will be returned.
    * @param info An object that contains the required input data for the method,
    *             and which will contain the output information if successful.
    *
    * @return The value -1 if fully valid, else the 0 based index of the child
    *         that first failed before the insertion point. If the value
    *         returned is equal to the number of children, then the specified
    *         children are valid but additional content is required to reach a
    *         valid ending state.
    *
    * @exception Exception Thrown on error.
    *
    * @see InsertableElementsInfo
    */
   protected int whatCanGoHere(int elementIndex, boolean fullyValid,
                               InsertableElementsInfo info) throws Exception {

      //
      //  Do some basic sanity checking on the info packet. First, make sure
      //  that insertAt is not greater than the child count. It can be equal,
      //  which means to get appendable elements, but not greater. Or, if
      //  the current children array is null, that's bad too.
      //
      //  Since the current children array must have a blank spot for where
      //  the insert is going to be, the child count must always be at least
      //  one.
      //
      //  Make sure that the child count is not larger than the current children
      //  array. It can be equal, which means get appendable elements, but not
      //  greater.
      //
      if (info.insertAt > info.childCount || info.curChildren == null || 
          info.childCount < 1 || info.childCount > info.curChildren.length) {
         fErrorReporter.reportError(fErrorReporter.getLocator(),
                                    ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
                                    ImplementationMessages.VAL_WCGHI,
                                    0,
                                    null,
                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
      }

      int retVal = 0;
      try {
         // Get the content model for this element
         final XMLContentModel cmElem = getElementContentModel(elementIndex);

         // And delegate this call to it
         retVal = cmElem.whatCanGoHere(fullyValid, info);
      } catch (CMException excToCatch) {
         // REVISIT - Translate caught error to the protected error handler interface
         int majorCode = excToCatch.getErrorCode();
         fErrorReporter.reportError(fErrorReporter.getLocator(),
                                    ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
                                    majorCode,
                                    0,
                                    null,
                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
         throw excToCatch;
      }
      return retVal;

   } // whatCanGoHere(int,boolean,InsertableElementsInfo):int

   // attribute information

   /** Protected for use by AttributeValidator classes. */
   protected boolean getAttDefIsExternal(QName element, QName attribute) {
      int attDefIndex = getAttDef(element, attribute);
      if (fGrammarIsDTDGrammar ) {
         return((DTDGrammar) fGrammar).getAttributeDeclIsExternal(attDefIndex);
      }
      return false;
   }



   //
   // Private methods
   //

   // other

   /** Returns true if using a standalone reader. */
   private boolean usingStandaloneReader() {
      return fStandaloneReader == -1 || fEntityHandler.getReaderId() == fStandaloneReader;
   }

   /** Returns a locator implementation. */
   private LocatorImpl getLocatorImpl(LocatorImpl fillin) {

      Locator here = fErrorReporter.getLocator();
      if (fillin == null)
         return new LocatorImpl(here);
      fillin.setPublicId(here.getPublicId());
      fillin.setSystemId(here.getSystemId());
      fillin.setLineNumber(here.getLineNumber());
      fillin.setColumnNumber(here.getColumnNumber());
      return fillin;

   } // getLocatorImpl(LocatorImpl):LocatorImpl

                                                          
   // initialization

   /** Reset pool. */
   private void poolReset() {
      try {
         //System.out.println("We reset" );
         this.fValID.validate( null, this.fResetID );
         this.fValIDRef.validate(null, this.fResetIDRef );
         this.fValIDRefs.validate(null, this.fResetIDRef );
      } catch ( InvalidDatatypeValueException ex ) {
         System.err.println("Error re-Initializing: ID,IDRef,IDRefs pools" );
      }
   } // poolReset()

   /** Reset common. */
   private void resetCommon(StringPool stringPool) throws Exception {

      fStringPool = stringPool;
      fValidating = fValidationEnabled;
      fValidationEnabledByDynamic = false;
      fDynamicDisabledByValidation = false;
      poolReset();
      fCalledStartDocument = false;
      fStandaloneReader = -1;
      fElementChildrenLength = 0;
      fElementDepth = -1;
      fSeenRootElement = false;
      fSeenDoctypeDecl = false;
      fNamespacesScope = null;
      fNamespacesPrefix = -1;
      fRootElement.clear();
      fAttrListHandle = -1;
      fCheckedForSchema = false;

      fCurrentScope = TOP_LEVEL_SCOPE;
      fCurrentSchemaURI = -1;
      fEmptyURI = - 1;
      fXsiPrefix = - 1;
      fXsiTypeValidator = null;

      fGrammar = null;
      fGrammarNameSpaceIndex = -1;
      //fGrammarResolver = null;
      if (fGrammarResolver != null) {
         fGrammarResolver.clearGrammarResolver();
      }
      fGrammarIsDTDGrammar = false;
      fGrammarIsSchemaGrammar = false;


      init();

   } // resetCommon(StringPool)

   /** Initialize. */
   private void init() {

      fEmptyURI = fStringPool.addSymbol("");
      fXsiURI = fStringPool.addSymbol(SchemaSymbols.URI_XSI);


      fEMPTYSymbol = fStringPool.addSymbol("EMPTY");
      fANYSymbol = fStringPool.addSymbol("ANY");
      fMIXEDSymbol = fStringPool.addSymbol("MIXED");
      fCHILDRENSymbol = fStringPool.addSymbol("CHILDREN");

      fCDATASymbol = fStringPool.addSymbol("CDATA");
      fIDSymbol = fStringPool.addSymbol("ID");
      fIDREFSymbol = fStringPool.addSymbol("IDREF");
      fIDREFSSymbol = fStringPool.addSymbol("IDREFS");
      fENTITYSymbol = fStringPool.addSymbol("ENTITY");
      fENTITIESSymbol = fStringPool.addSymbol("ENTITIES");
      fNMTOKENSymbol = fStringPool.addSymbol("NMTOKEN");
      fNMTOKENSSymbol = fStringPool.addSymbol("NMTOKENS");
      fNOTATIONSymbol = fStringPool.addSymbol("NOTATION");
      fENUMERATIONSymbol = fStringPool.addSymbol("ENUMERATION");
      fREQUIREDSymbol = fStringPool.addSymbol("#REQUIRED");
      fFIXEDSymbol = fStringPool.addSymbol("#FIXED");
      fDATATYPESymbol = fStringPool.addSymbol("<<datatype>>");
      fEpsilonIndex = fStringPool.addSymbol("<<CMNODE_EPSILON>>");
      fXMLLang = fStringPool.addSymbol("xml:lang");

      try {
         //Initialize Validators
         //Datatype Registry

         fDataTypeReg =
         DatatypeValidatorFactoryImpl.getDatatypeRegistry();
         fDataTypeReg.resetRegistry();
         //fDatatypeReg.resetRegistry();

         fValID       = this.fDataTypeReg.getDatatypeValidator("ID" );
         fValIDRef    = this.fDataTypeReg.getDatatypeValidator("IDREF" );
         fValIDRefs   = this.fDataTypeReg.getDatatypeValidator("IDREFS" );
         fValENTITY   = this.fDataTypeReg.getDatatypeValidator("ENTITY" );
         fValENTITIES = this.fDataTypeReg.getDatatypeValidator("ENTITIES" );
         fValNMTOKEN  = this.fDataTypeReg.getDatatypeValidator("NMTOKEN");
         fValNMTOKENS = this.fDataTypeReg.getDatatypeValidator("NMTOKENS");
         fValNOTATION = this.fDataTypeReg.getDatatypeValidator("NOTATION" );


         //Initialize ENTITY & ENTITIES Validatorh
         Object[] packageArgsEntityVal = { (Object) this.fEntityHandler,
            (Object) this.fStringPool};
         fValidateENTITYMsg.setDatatypeObject( (Object ) packageArgsEntityVal);
         fValENTITY.validate( null, fValidateENTITYMsg );
         fValENTITIES.validate( null, fValidateENTITYMsg );
      } catch ( InvalidDatatypeValueException ex ) {
         System.err.println("Error: " + ex.getLocalizedMessage() );//Should not happen
      }


   } // init()

   // other

   // default attribute

   /** addDefaultAttributes. */
   private int addDefaultAttributes(int elementIndex, XMLAttrList attrList, int attrIndex, boolean validationEnabled, boolean standalone) throws Exception {

      //System.out.println("XMLValidator#addDefaultAttributes");
      //System.out.print("  ");
      //fGrammar.printAttributes(elementIndex);

      //
      // Check after all specified attrs are scanned
      // (1) report error for REQUIRED attrs that are missing (V_TAGc)
      // (2) check that FIXED attrs have matching value (V_TAGd)
      // (3) add default attrs (FIXED and NOT_FIXED)
      //
      fGrammar.getElementDecl(elementIndex,fTempElementDecl);

      int elementNameIndex = fTempElementDecl.name.localpart;
      int attlistIndex = fGrammar.getFirstAttributeDeclIndex(elementIndex);
      int firstCheck = attrIndex;
      int lastCheck = -1;
      while (attlistIndex != -1) {
         fGrammar.getAttributeDecl(attlistIndex, fTempAttDecl);


         int attPrefix = fTempAttDecl.name.prefix;
         int attName = fTempAttDecl.name.localpart;
         int attType = attributeTypeName(fTempAttDecl);
         int attDefType =fTempAttDecl.defaultType;
         int attValue = -1 ;
         if (fTempAttDecl.defaultValue != null ) {
            attValue = fStringPool.addSymbol(fTempAttDecl.defaultValue);
         }

         boolean specified = false;
         boolean required = attDefType == XMLAttributeDecl.DEFAULT_TYPE_REQUIRED;

         if (firstCheck != -1) {
            boolean cdata = attType == fCDATASymbol;
            if (!cdata || required || attValue != -1) {
               int i = attrList.getFirstAttr(firstCheck);
               while (i != -1 && (lastCheck == -1 || i <= lastCheck)) {

                  if ( (fGrammarIsDTDGrammar && (attrList.getAttrName(i) == fTempAttDecl.name.rawname)) ||
                       fStringPool.equalNames(attrList.getAttrLocalpart(i), attName)
                          && fStringPool.equalNames(attrList.getAttrURI(i), fTempAttDecl.name.uri) ) ) {

                     if (validationEnabled && attDefType == XMLAttributeDecl.DEFAULT_TYPE_FIXED) {
                        int alistValue = attrList.getAttValue(i);
                        if (alistValue != attValue &&
                            !fStringPool.toString(alistValue).equals(fStringPool.toString(attValue))) {
                           Object[] args = { fStringPool.toString(elementNameIndex),
                              fStringPool.toString(attName),
                              fStringPool.toString(alistValue),
                              fStringPool.toString(attValue)};
                           fErrorReporter.reportError(fErrorReporter.getLocator(),
                                                      XMLMessages.XML_DOMAIN,
                                                      XMLMessages.MSG_FIXED_ATTVALUE_INVALID,
                                                      XMLMessages.VC_FIXED_ATTRIBUTE_DEFAULT,
                                                      args,
                                                      XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
                        }
                     }
                     specified = true;
                     break;
                  }
                  i = attrList.getNextAttr(i);
               }
            }
         }

         if (!specified) {
            if (required) {
               if (validationEnabled) {
                  Object[] args = { fStringPool.toString(elementNameIndex),
                     fStringPool.toString(attName)};
                  fErrorReporter.reportError(fErrorReporter.getLocator(),
                                             XMLMessages.XML_DOMAIN,
                                             XMLMessages.MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED,
                                             XMLMessages.VC_REQUIRED_ATTRIBUTE,
                                             args,
                                             XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
               }
            } else if (attValue != -1) {
               if (validationEnabled && standalone )
                  if ( fGrammarIsDTDGrammar
                       && ((DTDGrammar) fGrammar).getAttributeDeclIsExternal(attlistIndex) ) {

                     Object[] args = { fStringPool.toString(elementNameIndex),
                        fStringPool.toString(attName)};
                     fErrorReporter.reportError(fErrorReporter.getLocator(),
                                                XMLMessages.XML_DOMAIN,
                                                XMLMessages.MSG_DEFAULTED_ATTRIBUTE_NOT_SPECIFIED,
                                                XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
                                                args,
                                                XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
                  }
               if (attType == fIDREFSymbol) {
                  this.fValIDRef.validate( fStringPool.toString(attValue), this.fStoreIDRef );
               } else if (attType == fIDREFSSymbol) {
                  this.fValIDRefs.validate( fStringPool.toString(attValue), this.fStoreIDRef );
               }
               if (attrIndex == -1) {
                  attrIndex = attrList.startAttrList();
               }
               // REVISIT: Validation. What should the prefix be?
               fTempQName.setValues(attPrefix, attName, attName, fTempAttDecl.name.uri);
               int newAttr = attrList.addAttr(fTempQName,
                                              attValue, attType,
                                              false, false);
               if (lastCheck == -1) {
                  lastCheck = newAttr;
               }
            }
         }
         attlistIndex = fGrammar.getNextAttributeDeclIndex(attlistIndex);
      }
      return attrIndex;

   } // addDefaultAttributes(int,XMLAttrList,int,boolean,boolean):int

   /** addDTDDefaultAttributes. */
   private int addDTDDefaultAttributes(QName element, XMLAttrList attrList, int attrIndex, boolean validationEnabled, boolean standalone) throws Exception {


      //
      // Check after all specified attrs are scanned
      // (1) report error for REQUIRED attrs that are missing (V_TAGc)
      // (2) check that FIXED attrs have matching value (V_TAGd)
      // (3) add default attrs (FIXED and NOT_FIXED)
      //

      int elementIndex = fGrammar.getElementDeclIndex(element, -1);

      if (elementIndex == -1) {
         return attrIndex;
      }

      fGrammar.getElementDecl(elementIndex,fTempElementDecl);


      int elementNameIndex = fTempElementDecl.name.rawname;
      int attlistIndex = fGrammar.getFirstAttributeDeclIndex(elementIndex);
      int firstCheck = attrIndex;
      int lastCheck = -1;
      while (attlistIndex != -1) {

         fGrammar.getAttributeDecl(attlistIndex, fTempAttDecl);

         // TO DO: For ericye Debug only
         /***
         if (fTempAttDecl != null) {
             XMLElementDecl element = new XMLElementDecl();
             fGrammar.getElementDecl(elementIndex, element);
             System.out.println("element: "+fStringPool.toString(element.name.localpart));
             System.out.println("attlistIndex " + attlistIndex + "\n"+
                 "attName : '"+fStringPool.toString(fTempAttDecl.name.localpart) + "'\n"
                                + "attType : "+fTempAttDecl.type + "\n"
                                + "attDefaultType : "+fTempAttDecl.defaultType + "\n"
                                + "attDefaultValue : '"+fTempAttDecl.defaultValue + "'\n"
                                + attrList.getLength() +"\n"
                                );
         }
         /***/

         int attPrefix = fTempAttDecl.name.prefix;
         int attName = fTempAttDecl.name.rawname;
         int attLocalpart = fTempAttDecl.name.localpart;
         int attType = attributeTypeName(fTempAttDecl);
         int attDefType =fTempAttDecl.defaultType;
         int attValue = -1 ;
         if (fTempAttDecl.defaultValue != null ) {
            attValue = fStringPool.addSymbol(fTempAttDecl.defaultValue);
         }
         boolean specified = false;
         boolean required = attDefType == XMLAttributeDecl.DEFAULT_TYPE_REQUIRED;


         /****
         if (fValidating && fGrammar != null && fGrammarIsDTDGrammar && attValue != -1) {
             normalizeAttValue(null, fTempAttDecl.name,
                               attValue,attType,fTempAttDecl.list,
                               fTempAttDecl.enumeration);
         }
         /****/

         if (firstCheck != -1) {
            boolean cdata = attType == fCDATASymbol;
            if (!cdata || required || attValue != -1) {
               int i = attrList.getFirstAttr(firstCheck);
               while (i != -1 && (lastCheck == -1 || i <= lastCheck)) {

                  if ( attrList.getAttrName(i) == fTempAttDecl.name.rawname ) {

                     if (validationEnabled && attDefType == XMLAttributeDecl.DEFAULT_TYPE_FIXED) {
                        int alistValue = attrList.getAttValue(i);
                        if (alistValue != attValue &&
                            !fStringPool.toString(alistValue).equals(fStringPool.toString(attValue))) {
                           Object[] args = { fStringPool.toString(elementNameIndex),
                              fStringPool.toString(attName),
                              fStringPool.toString(alistValue),
                              fStringPool.toString(attValue)};
                           fErrorReporter.reportError(fErrorReporter.getLocator(),
                                                      XMLMessages.XML_DOMAIN,
                                                      XMLMessages.MSG_FIXED_ATTVALUE_INVALID,
                                                      XMLMessages.VC_FIXED_ATTRIBUTE_DEFAULT,
                                                      args,
                                                      XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
                        }
                     }
                     specified = true;
                     break;
                  }
                  i = attrList.getNextAttr(i);
               }
            }
         }

         if (!specified) {
            if (required) {
               if (validationEnabled) {
                  Object[] args = { fStringPool.toString(elementNameIndex),
                     fStringPool.toString(attName)};
                  fErrorReporter.reportError(fErrorReporter.getLocator(),
                                             XMLMessages.XML_DOMAIN,
                                             XMLMessages.MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED,
                                             XMLMessages.VC_REQUIRED_ATTRIBUTE,
                                             args,
                                             XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
               }
            } else if (attValue != -1) {
               if (validationEnabled && standalone )
                  if ( fGrammarIsDTDGrammar
                       && ((DTDGrammar) fGrammar).getAttributeDeclIsExternal(attlistIndex) ) {

                     Object[] args = { fStringPool.toString(elementNameIndex),
                        fStringPool.toString(attName)};
                     fErrorReporter.reportError(fErrorReporter.getLocator(),
                                                XMLMessages.XML_DOMAIN,
                                                XMLMessages.MSG_DEFAULTED_ATTRIBUTE_NOT_SPECIFIED,
                                                XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
                                                args,
                                                XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
                  }
               if (attType == fIDREFSymbol) {
                  this.fValIDRef.validate( fStringPool.toString(attValue), this.fStoreIDRef );
               } else if (attType == fIDREFSSymbol) {
                  this.fValIDRefs.validate( fStringPool.toString(attValue), this.fStoreIDRef );
               }
               if (attrIndex == -1) {
                  attrIndex = attrList.startAttrList();
               }

               fTempQName.setValues(attPrefix, attLocalpart, attName, fTempAttDecl.name.uri);
               int newAttr = attrList.addAttr(fTempQName,
                                              attValue, attType,
                                              false, false);
               if (lastCheck == -1) {
                  lastCheck = newAttr;
               }
            }
         }
         attlistIndex = fGrammar.getNextAttributeDeclIndex(attlistIndex);
      }
      return attrIndex;

   } // addDTDDefaultAttributes(int,XMLAttrList,int,boolean,boolean):int

   // content models

   /** Queries the content model for the specified element index. */
   private XMLContentModel getElementContentModel(int elementIndex) throws CMException {
      XMLContentModel contentModel = null;
      if ( elementIndex > -1) {
         if ( fGrammar.getElementDecl(elementIndex,fTempElementDecl) ) {
            contentModel = fGrammar.getElementContentModel(elementIndex);
         }
      }
      //return fGrammar.getElementContentModel(elementIndex);
      return contentModel;
   }



   // query attribute information

   /** Returns an attribute definition for an element type. */
   // this is only used by DTD validation.
   private int getAttDef(QName element, QName attribute) {
      if (fGrammar != null) {
         int scope = fCurrentScope;
         if (element.uri > -1) {
            scope = TOP_LEVEL_SCOPE;
         }
         int elementIndex = fGrammar.getElementDeclIndex(element,scope);
         if (elementIndex == -1) {
            return -1;
         }
         int attDefIndex = fGrammar.getFirstAttributeDeclIndex(elementIndex);
         while (attDefIndex != -1) {
            fGrammar.getAttributeDecl(attDefIndex, fTempAttributeDecl);
            if (fTempAttributeDecl.name.localpart == attribute.localpart &&
                fTempAttributeDecl.name.uri == attribute.uri ) {
               return attDefIndex;
            }
            attDefIndex = fGrammar.getNextAttributeDeclIndex(attDefIndex);
         }
      }
      return -1;

   } // getAttDef(QName,QName)

   /** Returns an attribute definition for an element type. */
   private int getAttDefByElementIndex(int elementIndex, QName attribute) {
      if (fGrammar != null && elementIndex > -1) {
         if (elementIndex == -1) {
            return -1;
         }
         int attDefIndex = fGrammar.getFirstAttributeDeclIndex(elementIndex);
         while (attDefIndex != -1) {
            fGrammar.getAttributeDecl(attDefIndex, fTempAttDecl);

            if (fGrammarIsDTDGrammar) {
               if (fTempAttDecl.name.rawname == attribute.rawname )
                  return attDefIndex;
            } else
               if (fTempAttDecl.name.localpart == attribute.localpart &&
                   fTempAttDecl.name.uri == attribute.uri ) {
               return attDefIndex;
            }

            if (fGrammarIsSchemaGrammar) {
               if (fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_ANY) {
                  return attDefIndex;
               } else if (fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_LOCAL) {
                  if (attribute.uri == -1) {
                     return attDefIndex;
                  }
               } else if (fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_OTHER) {
                  if (attribute.uri != fTempAttDecl.name.uri) {
                     return attDefIndex;
                  }
               } else if (fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_LIST) {
                  if (fStringPool.stringInList(fTempAttDecl.enumeration, attribute.uri)) {
                     return attDefIndex;
                  }
               }
            }

            attDefIndex = fGrammar.getNextAttributeDeclIndex(attDefIndex);
         }
      }
      return -1;

   } // getAttDef(QName,QName)

   // validation

   /** Root element specified. */
   private void rootElementSpecified(QName rootElement) throws Exception {

      // this is what it used to be
      //if  (fDynamicValidation && !fSeenDoctypeDecl) {
      //fValidating = false;
      //}


      if ( fLoadDTDGrammar )
         // initialize the grammar to be the default one,
         // it definitely should be a DTD Grammar at this case;
         if (fGrammar == null) {

            fGrammar = fGrammarResolver.getGrammar("");

            //TO DO, for ericye debug only
            if (fGrammar == null && DEBUG_SCHEMA_VALIDATION) {
               System.out.println("Oops! no grammar is found for validation");
            }

            if (fDynamicValidation && fGrammar==null) {
               fValidating = false;
            }

            if (fGrammar != null) {
               if (fGrammar instanceof DTDGrammar) {
                  fGrammarIsDTDGrammar = true;
                  fGrammarIsSchemaGrammar = false;
               } else if ( fGrammar instanceof SchemaGrammar ) {
                  fGrammarIsSchemaGrammar = true;
                  fGrammarIsDTDGrammar = false;
               }

               fGrammarNameSpaceIndex = fEmptyURI;
            }
         }

      if (fValidating) {
         if ( fGrammarIsDTDGrammar &&
              ((DTDGrammar) fGrammar).getRootElementQName(fRootElement) ) {

            String root1 = fStringPool.toString(fRootElement.rawname);
            String root2 = fStringPool.toString(rootElement.rawname);
            if (!root1.equals(root2)) {
               reportRecoverableXMLError(XMLMessages.MSG_ROOT_ELEMENT_TYPE,
                                         XMLMessages.VC_ROOT_ELEMENT_TYPE,
                                         fRootElement.rawname,
                                         rootElement.rawname);
            }
         }
      }

      if (fNamespacesEnabled) {
         if (fNamespacesScope == null) {
            fNamespacesScope = new NamespacesScope(this);
            fNamespacesPrefix = fStringPool.addSymbol("xmlns");
            fNamespacesScope.setNamespaceForPrefix(fNamespacesPrefix, -1);
            int xmlSymbol = fStringPool.addSymbol("xml");
            int xmlNamespace = fStringPool.addSymbol("http://www.w3.org/XML/1998/namespace");
            fNamespacesScope.setNamespaceForPrefix(xmlSymbol, xmlNamespace);
         }
      }

   } // rootElementSpecified(QName)

   /** Switchs to correct validating symbol tables when Schema changes.*/

   private boolean switchGrammar(int newGrammarNameSpaceIndex) throws Exception {
      Grammar tempGrammar = fGrammarResolver.getGrammar(fStringPool.toString(newGrammarNameSpaceIndex));
      if (tempGrammar == null) {
         // This is a case where namespaces is on with a DTD grammar.
         tempGrammar = fGrammarResolver.getGrammar("");
      }
      if (tempGrammar == null) {
         return false;
      } else {
         fGrammar = tempGrammar;
         if (fGrammar instanceof DTDGrammar) {
            fGrammarIsDTDGrammar = true;
            fGrammarIsSchemaGrammar = false;
         } else if ( fGrammar instanceof SchemaGrammar ) {
            fGrammarIsSchemaGrammar = true;
            fGrammarIsDTDGrammar = false;
         }

         return true;
      }
   }

   /** Binds namespaces to the element and attributes. */
   private void bindNamespacesToElementAndAttributes(QName element,
                                                     XMLAttrList attrList)
   throws Exception {

      fNamespacesScope.increaseDepth();

      //Vector schemaCandidateURIs = null;
      Hashtable locationUriPairs = null;

      if (fAttrListHandle != -1) {
         int index = attrList.getFirstAttr(fAttrListHandle);
         while (index != -1) {
            int attName = attrList.getAttrName(index);
            int attPrefix = attrList.getAttrPrefix(index);
            if (fStringPool.equalNames(attName, fXMLLang)) {
               /***
               // NOTE: This check is done in the validateElementsAndAttributes
               //       method.
               fDocumentScanner.checkXMLLangAttributeValue(attrList.getAttValue(index));
               /***/
            } else if (fStringPool.equalNames(attName, fNamespacesPrefix)) {
               int uri = fStringPool.addSymbol(attrList.getAttValue(index));
               fNamespacesScope.setNamespaceForPrefix(StringPool.EMPTY_STRING, uri);
            } else {
               if (attPrefix == fNamespacesPrefix) {
                  int nsPrefix = attrList.getAttrLocalpart(index);
                  int uri = fStringPool.addSymbol(attrList.getAttValue(index));
                  fNamespacesScope.setNamespaceForPrefix(nsPrefix, uri);

                  if (fValidating && fSchemaValidation) {
                     boolean seeXsi = false;
                     String attrValue = fStringPool.toString(attrList.getAttValue(index));

                     if (attrValue.equals(SchemaSymbols.URI_XSI)) {
                        fXsiPrefix = nsPrefix;
                        seeXsi = true;
                     }

                     if (!seeXsi) {
                        /***
                        if (schemaCandidateURIs == null) {
                            schemaCandidateURIs = new Vector();
                        }
                        schemaCandidateURIs.addElement( fStringPool.toString(uri) );
                        /***/
                     }
                  }
               }
            }
            index = attrList.getNextAttr(index);
         }
         // if validating, walk through the list again to deal with "xsi:...."
         if (fValidating && fSchemaValidation) {
            fXsiTypeAttValue = -1;
            index = attrList.getFirstAttr(fAttrListHandle);
            while (index != -1) {

               int attName = attrList.getAttrName(index);
               int attPrefix = attrList.getAttrPrefix(index);

               if (fStringPool.equalNames(attName, fNamespacesPrefix)) {
                  // REVISIT
               } else {
                  if ( DEBUG_SCHEMA_VALIDATION ) {
                     System.out.println("deal with XSI");
                     System.out.println("before find XSI: "+fStringPool.toString(attPrefix)
                                        +","+fStringPool.toString(fXsiPrefix) );
                  }
                  if ( fXsiPrefix != -1 && attPrefix == fXsiPrefix ) {

                     if (DEBUG_SCHEMA_VALIDATION) {
                        System.out.println("find XSI: "+fStringPool.toString(attPrefix)
                                           +","+fStringPool.toString(attName) );
                     }


                     int localpart = attrList.getAttrLocalpart(index);
                     if (localpart == fStringPool.addSymbol(SchemaSymbols.XSI_SCHEMALOCACTION)) {
                        if (locationUriPairs == null) {
                           locationUriPairs = new Hashtable();
                        }
                        parseSchemaLocation(fStringPool.toString(attrList.getAttValue(index)), locationUriPairs);
                     } else if (localpart == fStringPool.addSymbol(SchemaSymbols.XSI_NONAMESPACESCHEMALOCACTION)) {
                        if (locationUriPairs == null) {
                           locationUriPairs = new Hashtable();
                        }
                        locationUriPairs.put(fStringPool.toString(attrList.getAttValue(index)), "");
                        if (fNamespacesScope != null) {
                           //bind prefix "" to URI "" in this case
                           fNamespacesScope.setNamespaceForPrefix( fStringPool.addSymbol(""),
                                                                   fStringPool.addSymbol(""));
                        }
                     } else if (localpart == fStringPool.addSymbol(SchemaSymbols.XSI_TYPE)) {
                        fXsiTypeAttValue = attrList.getAttValue(index);
                     }
                     // REVISIT: should we break here?
                     //break;
                  }
               }
               index = attrList.getNextAttr(index);
            }

            // try to resolve all the grammars here
            if (locationUriPairs != null) {
               Enumeration locations = locationUriPairs.keys();

               while (locations.hasMoreElements()) {
                  String loc = (String) locations.nextElement();
                  String uri = (String) locationUriPairs.get(loc);
                  resolveSchemaGrammar( loc, uri);
                  //schemaCandidateURIs.removeElement(uri);
               }
            }

            //TO DO: This should be a feature that can be turned on or off
            /*****
            for (int i=0; i< schemaCandidateURIs.size(); i++) {
           
                String uri = (String) schemaCandidateURIs.elementAt(i);
                resolveSchemaGrammar(uri);
            }
            /*****/

         }

      }

      // bind element to URI
      int prefix = element.prefix != -1 ? element.prefix : 0;
      int uri    = fNamespacesScope.getNamespaceForPrefix(prefix);
      if (element.prefix != -1 || uri != -1) {
         element.uri = uri;
         if (element.uri == -1) {
            Object[] args = { fStringPool.toString(element.prefix)};
            fErrorReporter.reportError(fErrorReporter.getLocator(),
                                       XMLMessages.XMLNS_DOMAIN,
                                       XMLMessages.MSG_PREFIX_DECLARED,
                                       XMLMessages.NC_PREFIX_DECLARED,
                                       args,
                                       XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
         }
      }


      if (fAttrListHandle != -1) {
         int index = attrList.getFirstAttr(fAttrListHandle);
         while (index != -1) {
            int attName = attrList.getAttrName(index);
            if (!fStringPool.equalNames(attName, fNamespacesPrefix)) {
               int attPrefix = attrList.getAttrPrefix(index);
               if (attPrefix != fNamespacesPrefix) {
                  if (attPrefix != -1 ) {
                     int attrUri = fNamespacesScope.getNamespaceForPrefix(attPrefix);
                     if (attrUri == -1) {
                        Object[] args = { fStringPool.toString(attPrefix)};
                        fErrorReporter.reportError(fErrorReporter.getLocator(),
                                                   XMLMessages.XMLNS_DOMAIN,
                                                   XMLMessages.MSG_PREFIX_DECLARED,
                                                   XMLMessages.NC_PREFIX_DECLARED,
                                                   args,
                                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
                     }
                     attrList.setAttrURI(index, attrUri);
                  }
               }
            }
            index = attrList.getNextAttr(index);
         }
      }

   } // bindNamespacesToElementAndAttributes(QName,XMLAttrList)

   void parseSchemaLocation(String schemaLocationStr, Hashtable locationUriPairs){
      if (locationUriPairs != null) {
         StringTokenizer tokenizer = new StringTokenizer(schemaLocationStr, " \n\t\r", false);
         int tokenTotal = tokenizer.countTokens();
         if (tokenTotal % 2 != 0 ) {
            // TO DO: report warning - malformed schemaLocation string
         } else {
            while (tokenizer.hasMoreTokens()) {
               String uri = tokenizer.nextToken();
               String location = tokenizer.nextToken();

               locationUriPairs.put(location, uri);
            }
         }
      } else {
         // TO DO: should report internal error here
      }

   }// parseSchemaLocaltion(String, Hashtable)
   private void resolveSchemaGrammar( String loc, String uri) throws Exception {

      SchemaGrammar grammar = (SchemaGrammar) fGrammarResolver.getGrammar(uri);

      if (grammar == null) {
         DOMParser parser = new DOMParser();
         parser.setEntityResolver( new Resolver(fEntityHandler) );
         parser.setErrorHandlernew ErrorHandler() );

         try {
            parser.setFeature("http://xml.org/sax/features/validation", false);
            parser.setFeature("http://xml.org/sax/features/namespaces", true);
            parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
         } catch org.xml.sax.SAXNotRecognizedException e ) {
            e.printStackTrace();
         } catch ( org.xml.sax.SAXNotSupportedException e ) {
            e.printStackTrace();
         }

         // expand it before passing it to the parser
         InputSource source = null;
         EntityResolver currentER = parser.getEntityResolver();
         if (currentER != null) {
            source = currentER.resolveEntity("", loc);
         }
         if (source == null) {
            loc = fEntityHandler.expandSystemId(loc);
            source = new InputSource(loc);
         }
         try {
            parser.parse( source );
         } catch ( IOException e ) {
            e.printStackTrace();
         } catch ( SAXException e ) {
            //System.out.println("loc = "+loc);
            //e.printStackTrace();
            reportRecoverableXMLError( XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
                                       XMLMessages.SCHEMA_GENERIC_ERROR, e.getMessage() );
         }

         Document     document   = parser.getDocument(); //Our Grammar

         TraverseSchema tst = null;
         try {
            if (DEBUG_SCHEMA_VALIDATION) {
               System.out.println("I am geting the Schema Document");
            }

            Element root   = document.getDocumentElement();// This is what we pass to TraverserSchema
            if (root == null) {
               reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR, XMLMessages.SCHEMA_GENERIC_ERROR, "Can't get back Schema document's root element :" + loc);
            } else {
               if (uri == null || !uri.equals(root.getAttribute(SchemaSymbols.ATT_TARGETNAMESPACE)) ) {
                  reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR, XMLMessages.SCHEMA_GENERIC_ERROR, "Schema in " + loc + " has a different target namespace " +
                                            "from the one specified in the instance document :" + uri);
               }
               grammar = new SchemaGrammar();
               grammar.setGrammarDocument(document);
               tst = new TraverseSchema( root, fStringPool, (SchemaGrammar)grammar, fGrammarResolver, fErrorReporter, source.getSystemId());
               fGrammarResolver.putGrammar(document.getDocumentElement().getAttribute("targetNamespace"), grammar);
            }
         } catch (Exception e) {
            e.printStackTrace(System.err);
         }
      }

   }

   private void resolveSchemaGrammar(String uri) throws Exception{

      resolveSchemaGrammar(uri, uri);

   }

   static class Resolver implements EntityResolver {

      //
      // Constants
      //

      private static final String SYSTEM[] = {
         "http://www.w3.org/TR/2000/WD-xmlschema-1-20000407/structures.dtd",
         "http://www.w3.org/TR/2000/WD-xmlschema-1-20000407/datatypes.dtd",
         "http://www.w3.org/TR/2000/WD-xmlschema-1-20000407/versionInfo.ent",
      };
      private static final String PATH[] = {
         "structures.dtd",
         "datatypes.dtd",
         "versionInfo.ent",
      };

      //
      // Data
      //

      private DefaultEntityHandler fEntityHandler;

      //
      // Constructors
      //

      public Resolver(DefaultEntityHandler handler) {
         fEntityHandler = handler;
      }

      //
      // EntityResolver methods
      //

      public InputSource resolveEntity(String publicId, String systemId)
      throws IOException, SAXException {

         // looking for the schema DTDs?
         for (int i = 0; i < SYSTEM.length; i++) {
            if (systemId.equals(SYSTEM[i])) {
               InputSource source = new InputSource(getClass().getResourceAsStream(PATH[i]));
               source.setPublicId(publicId);
               source.setSystemId(systemId);
               return source;
            }
         }

         // first try to resolve using user's entity resolver
         EntityResolver resolver = fEntityHandler.getEntityResolver();
         if (resolver != null) {
            InputSource source = resolver.resolveEntity(publicId, systemId);
            if (source != null) {
               return source;
            }
         }

         // use default resolution
         return new InputSource(fEntityHandler.expandSystemId(systemId));

      } // resolveEntity(String,String):InputSource

   } // class Resolver

   static class ErrorHandler implements org.xml.sax.ErrorHandler {

      /** Warning. */
      public void warning(SAXParseException ex) {
         System.err.println("[Warning] "+
                            getLocationString(ex)+": "+
                            ex.getMessage());
      }

      /** Error. */
      public void error(SAXParseException ex) {
         System.err.println("[Error] "+
                            getLocationString(ex)+": "+
                            ex.getMessage());
      }

      /** Fatal error. */
      public void fatalError(SAXParseException ex)  {
         System.err.println("[Fatal Error] "+
                            getLocationString(ex)+": "+
                            ex.getMessage());
         //throw ex;
      }

      //
      // Private methods
      //

      /** Returns a string of the location. */
      private String getLocationString(SAXParseException ex) {
         StringBuffer str = new StringBuffer();

         String systemId_ = ex.getSystemId();
         if (systemId_ != null) {
            int index = systemId_.lastIndexOf('/');
            if (index != -1)
               systemId_ = systemId_.substring(index + 1);
            str.append(systemId_);
         }
         str.append(':');
         str.append(ex.getLineNumber());
         str.append(':');
         str.append(ex.getColumnNumber());

         return str.toString();

      } // getLocationString(SAXParseException):String
   }

   private int attributeTypeName(XMLAttributeDecl attrDecl) {
      switch (attrDecl.type) {
      case XMLAttributeDecl.TYPE_ENTITY: {
            return attrDecl.list ? fENTITIESSymbol : fENTITYSymbol;
         }
      case XMLAttributeDecl.TYPE_ENUMERATION: {
            String enumeration = fStringPool.stringListAsString(attrDecl.enumeration);
            return fStringPool.addString(enumeration);
         }
      case XMLAttributeDecl.TYPE_ID: {
            return fIDSymbol;
         }
      case XMLAttributeDecl.TYPE_IDREF: {
            return attrDecl.list ? fIDREFSSymbol : fIDREFSymbol;
         }
      case XMLAttributeDecl.TYPE_NMTOKEN: {
            return attrDecl.list ? fNMTOKENSSymbol : fNMTOKENSSymbol;
         }
      case XMLAttributeDecl.TYPE_NOTATION: {
            return fNOTATIONSymbol;
         }
      }
      return fCDATASymbol;
   }

   /** Validates element and attributes. */
   private void validateElementAndAttributes(QName element,
                                             XMLAttrList attrList)
   throws Exception {

      if ((fElementDepth >= 0 && fValidationFlagStack[fElementDepth] != 0 )||
          (fGrammar == null && !fValidating && !fNamespacesEnabled) ) {
         fCurrentElementIndex = -1;
         fCurrentContentSpecType = -1;
         fInElementContent = false;
         if (fAttrListHandle != -1) {
            fAttrList.endAttrList();
            int index = fAttrList.getFirstAttr(fAttrListHandle);
            while (index != -1) {
               if (fStringPool.equalNames(fAttrList.getAttrName(index), fXMLLang)) {
                  fDocumentScanner.checkXMLLangAttributeValue(fAttrList.getAttValue(index));
                  break;
               }
               index = fAttrList.getNextAttr(index);
            }
         }
         return;
      }

      int elementIndex = -1;
      int contentSpecType = -1;

      boolean skipThisOne = false;
      boolean laxThisOne = false;

      if ( fGrammarIsSchemaGrammar && fContentLeafStack[fElementDepth] != null ) {
         ContentLeafNameTypeVector cv = fContentLeafStack[fElementDepth];

         QName[] fElemMap = cv.leafNames;
         for (int i=0; i<cv.leafCount; i++) {
            int type = cv.leafTypes[i;
            //System.out.println("******* see a ANY_OTHER_SKIP, "+type+","+element+","+fElemMap[i]+"\n*******");

            if (type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
               if (fElemMap[i].uri==element.uri
                   && fElemMap[i].localpart == element.localpart)
                  break;
            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY) {
               int uri = fElemMap[i].uri;
               if (uri == -1 || uri == element.uri) {
                  break;
               }
            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) {
               if (element.uri == -1) {
                  break;
               }
            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
               if (fElemMap[i].uri != element.uri) {
                  break;
               }
            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_SKIP) {
               int uri = fElemMap[i].uri;
               if (uri == -1 || uri == element.uri) {
                  skipThisOne = true;
                  break;
               }
            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL_SKIP) {
               if (element.uri == -1) {
                  skipThisOne = true;
                  break;
               }
            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER_SKIP) {
               if (fElemMap[i].uri != element.uri) {
                  skipThisOne = true;
                  break;
               }
            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_LAX) {
               int uri = fElemMap[i].uri;
               if (uri == -1 || uri == element.uri) {
                  laxThisOne = true;
                  break;
               }
            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL_LAX) {
               if (element.uri == -1) {
                  laxThisOne = true;
                  break;
               }
            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER_LAX) {
               if (fElemMap[i].uri != element.uri) {
                  laxThisOne = true;
                  break;
               }
            }

         }

      }

      if (skipThisOne) {
         fNeedValidationOff = true;
      } else {

         //REVISIT: is this the right place to check on if the Schema has changed?

         if ( fNamespacesEnabled && fValidating && element.uri != fGrammarNameSpaceIndex && element.uri != -) {
            fGrammarNameSpaceIndex = element.uri;

            boolean success = switchGrammar(fGrammarNameSpaceIndex);

            if (!success && !laxThisOne) {
               reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR, XMLMessages.SCHEMA_GENERIC_ERROR,
                                         "Grammar with uri 2: " + fStringPool.toString(fGrammarNameSpaceIndex)
                                         + " , can not found");
            }
         }


         if ( fGrammar != null ) {
            if (DEBUG_SCHEMA_VALIDATION) {
               System.out.println("*******Lookup element: uri: " + fStringPool.toString(element.uri)+
                                  "localpart: '" + fStringPool.toString(element.localpart)
                                  +"' and scope : " + fCurrentScope+"\n");
            }

            elementIndex = fGrammar.getElementDeclIndex(element,fCurrentScope);

            if (elementIndex == -1 ) {
               elementIndex = fGrammar.getElementDeclIndex(element, TOP_LEVEL_SCOPE);
            }

            if (elementIndex == -1) {
               // if validating based on a Schema, try to resolve the element again by searching in its type's ancestor types
               if (fGrammarIsSchemaGrammar && fCurrentElementIndex != -1) {
                  TraverseSchema.ComplexTypeInfo baseTypeInfo = null;
                  baseTypeInfo = ((SchemaGrammar)fGrammar).getElementComplexTypeInfo(fCurrentElementIndex);
                  int aGrammarNSIndex = fGrammarNameSpaceIndex;
                  while (baseTypeInfo != null) {
                     elementIndex = fGrammar.getElementDeclIndex(element, baseTypeInfo.scopeDefined);
                     if (elementIndex > -1 ) {
                        // update the current Grammar NS index if resolving element succeed.
                        fGrammarNameSpaceIndex = aGrammarNSIndex;
                        break;
                     }
                     baseTypeInfo = baseTypeInfo.baseComplexTypeInfo;
                     if (baseTypeInfo != null) {
                        String baseTName = baseTypeInfo.typeName;
                        if (!baseTName.startsWith("#")) {
                           int comma = baseTName.indexOf(',');
                           aGrammarNSIndex = fStringPool.addSymbol(baseTName.substring(0,comma).trim());
                           if (aGrammarNSIndex != fGrammarNameSpaceIndex) {
                              if ( !switchGrammar(aGrammarNSIndex) ) {
                                 break; //exit the loop in this case
                              }
                           }
                        }
                     }
                  }
                  if (elementIndex == -1) {
                     switchGrammar(fGrammarNameSpaceIndex);
                  }
               }
               //if still can't resolve it, try TOP_LEVEL_SCOPE AGAIN
               /****
               if ( element.uri == -1 && elementIndex == -1
               && fNamespacesScope != null
               && fNamespacesScope.getNamespaceForPrefix(StringPool.EMPTY_STRING) != -1 ) {
               elementIndex = fGrammar.getElementDeclIndex(element.localpart, TOP_LEVEL_SCOPE);
               // REVISIT:
               // this is a hack to handle the situation where namespace prefix "" is bound to nothing, and there
               // is a "noNamespaceSchemaLocation" specified, and element
               element.uri = StringPool.EMPTY_STRING;
               }
               /****/

               /****/
               if (elementIndex == -1) {
                  if (laxThisOne) {
                     fNeedValidationOff = true;
                  } else
                     if (DEBUG_SCHEMA_VALIDATION)
                     System.out.println("!!! can not find elementDecl in the grammar, " +
                                        " the element localpart: " + element.localpart +
                                        "["+fStringPool.toString(element.localpart) +"]" +
                                        " the element uri: " + element.uri +
                                        "["+fStringPool.toString(element.uri) +"]" +
                                        " and the current enclosing scope: " + fCurrentScope );
               }
               /****/
            }

            if (DEBUG_SCHEMA_VALIDATION) {
               fGrammar.getElementDecl(elementIndex, fTempElementDecl);
               System.out.println("elementIndex: " + elementIndex+" \n and itsName : '"
                                  + fStringPool.toString(fTempElementDecl.name.localpart)
                                  +"' \n its ContentType:" + fTempElementDecl.type
                                  +"\n its ContentSpecIndex : " + fTempElementDecl.contentSpecIndex +"\n"+
                                  " and the current enclosing scope: " + fCurrentScope);
            }
         }

         contentSpecType =  getContentSpecType(elementIndex);

         if (fGrammarIsSchemaGrammar && elementIndex != -1) {

            // handle "xsi:type" right here
            if (fXsiTypeAttValue > -1) {
               String xsiType = fStringPool.toString(fXsiTypeAttValue);
               int colonP = xsiType.indexOf(":");
               String prefix = "";
               String localpart = xsiType;
               if (colonP > -1) {
                  prefix = xsiType.substring(0,colonP);
                  localpart = xsiType.substring(colonP+1);
               }

               String uri = "";
               int uriIndex = -1;
               if (fNamespacesScope != null) {
                  uriIndex = fNamespacesScope.getNamespaceForPrefix(fStringPool.addSymbol(prefix));
                  if (uriIndex > -1) {
                     uri = fStringPool.toString(uriIndex);
                     if (uriIndex != fGrammarNameSpaceIndex) {
                        fGrammarNameSpaceIndex = fCurrentSchemaURI = uriIndex;
                        boolean success = switchGrammar(fCurrentSchemaURI);
                        if (!success && !fNeedValidationOff) {
                           reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
                                                     XMLMessages.SCHEMA_GENERIC_ERROR,
                                                     "Grammar with uri 3: "
                                                     + fStringPool.toString(fCurrentSchemaURI)
                                                     + " , can not found");
                        }
                     }
                  }
               }


               Hashtable complexRegistry = ((SchemaGrammar)fGrammar).getComplexTypeRegistry();
               DatatypeValidatorFactoryImpl dataTypeReg = ((SchemaGrammar)fGrammar).getDatatypeRegistry();
               if (complexRegistry==null || dataTypeReg == null) {
                  reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
                                            XMLMessages.SCHEMA_GENERIC_ERROR,
                                            fErrorReporter.getLocator().getSystemId()
                                            +" line"+fErrorReporter.getLocator().getLineNumber()
                                            +", canot resolve xsi:type = " + xsiType+"  ---2");
               } else {
                  TraverseSchema.ComplexTypeInfo typeInfo =
                  (TraverseSchema.ComplexTypeInfo) complexRegistry.get(uri+","+localpart);
                  //TO DO:
                  //      here need to check if this substitution is legal based on the current active grammar,
                  //      this should be easy, cause we already saved final, block and base type information in
                  //      the SchemaGrammar.

                  if (typeInfo==null) {
                     if (uri.length() == 0 || uri.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA) ) {
                        fXsiTypeValidator = dataTypeReg.getDatatypeValidator(localpart);
                     } else
                        fXsiTypeValidator = dataTypeReg.getDatatypeValidator(uri+","+localpart);
                     if ( fXsiTypeValidator == null )
                        reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
                                                  XMLMessages.SCHEMA_GENERIC_ERROR,
                                                  "unresolved type : "+uri+","+localpart
                                                  +" found  in xsi:type handling");
                  } else
                     elementIndex = typeInfo.templateElementIndex;
               }

               fXsiTypeAttValue = -1;
            }

            //Change the current scope to be the one defined by this element.
            fCurrentScope = ((SchemaGrammar) fGrammar).getElementDefinedScope(elementIndex);

            //       here need to check if we need to switch Grammar by asking SchemaGrammar whether
            //       this element actually is of a type in another Schema.
            String anotherSchemaURI = ((SchemaGrammar)fGrammar).getElementFromAnotherSchemaURI(elementIndex);
            if (anotherSchemaURI != null) {
               //before switch Grammar, set the elementIndex to be the template elementIndex of its type
               if (contentSpecType != -1
                   && contentSpecType != XMLElementDecl.TYPE_EMPTY ) {
                  TraverseSchema.ComplexTypeInfo typeInfo = ((SchemaGrammar) fGrammar).getElementComplexTypeInfo(elementIndex);
                  if (typeInfo != null) {
                     elementIndex = typeInfo.templateElementIndex;
                  }

               }

               // now switch the grammar
               fGrammarNameSpaceIndex = fCurrentSchemaURI = fStringPool.addSymbol(anotherSchemaURI);
               boolean success = switchGrammar(fCurrentSchemaURI);
               if (!success && !fNeedValidationOff) {
                  reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
                                            XMLMessages.SCHEMA_GENERIC_ERROR,
                                            "Grammar with uri 4: "
                                            + fStringPool.toString(fCurrentSchemaURI)
                                            + " , can not found");
               }
            }

         }

         if (contentSpecType == -1 && fValidating && !fNeedValidationOff ) {
            reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_NOT_DECLARED,
                                      XMLMessages.VC_ELEMENT_VALID,
                                      element.rawname);
         }
         if (fGrammar != null && fGrammarIsSchemaGrammar && elementIndex != -1) {
            fAttrListHandle = addDefaultAttributes(elementIndex, attrList, fAttrListHandle, fValidating, fStandaloneReader != -1);
         }
         if (fAttrListHandle != -1) {
            fAttrList.endAttrList();
         }

         if (DEBUG_PRINT_ATTRIBUTES) {
            String elementStr = fStringPool.toString(element.rawname);
            System.out.print("startElement: <" + elementStr);
            if (fAttrListHandle != -1) {
               int index = attrList.getFirstAttr(fAttrListHandle);
               while (index != -1) {
                  System.out.print(" " + fStringPool.toString(attrList.getAttrName(index)) + "=\"" +
                                   fStringPool.toString(attrList.getAttValue(index)) + "\"");
                  index = attrList.getNextAttr(index);
               }
            }
            System.out.println(">");
         }
         // REVISIT: Validation. Do we need to recheck for the xml:lang
         //          attribute? It was already checked above -- perhaps
         //          this is to check values that are defaulted in? If
         //          so, this check could move to the attribute decl
         //          callback so we can check the default value before
         //          it is used.
         if (fAttrListHandle != -1 && !fNeedValidationOff ) {
            int index = fAttrList.getFirstAttr(fAttrListHandle);
            while (index != -1) {
               int attrNameIndex = attrList.getAttrName(index);

               if (fStringPool.equalNames(attrNameIndex, fXMLLang)) {
                  fDocumentScanner.checkXMLLangAttributeValue(attrList.getAttValue(index));
                  // break;
               }
               // here, we validate every "user-defined" attributes
               int _xmlns = fStringPool.addSymbol("xmlns");

               if (attrNameIndex != _xmlns && attrList.getAttrPrefix(index) != _xmlns)
                  if (fGrammar != null) {
                     fAttrNameLocator = getLocatorImpl(fAttrNameLocator);
                     fTempQName.setValues(attrList.getAttrPrefix(index),
                                          attrList.getAttrLocalpart(index),
                                          attrList.getAttrName(index),
                                          attrList.getAttrURI(index) );
                     int attDefIndex = getAttDefByElementIndex(elementIndex, fTempQName);

                     if (fTempQName.uri != fXsiURI)
                        if (attDefIndex == -1 ) {
                           if (fValidating) {
                              // REVISIT - cache the elem/attr tuple so that we only give
                              //  this error once for each unique occurrence
                              Object[] args = { fStringPool.toString(element.rawname),
                                 fStringPool.toString(attrList.getAttrName(index))};

                              /*****/
                              fErrorReporter.reportError(fAttrNameLocator,
                                                         XMLMessages.XML_DOMAIN,
                                                         XMLMessages.MSG_ATTRIBUTE_NOT_DECLARED,
                                                         XMLMessages.VC_ATTRIBUTE_VALUE_TYPE,
                                                         args,
                                                         XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);  
                              /******/
                           }
                        } else {

                           fGrammar.getAttributeDecl(attDefIndex, fTempAttDecl);

                           int attributeType = attributeTypeName(fTempAttDecl);
                           attrList.setAttType(index, attributeType);

                           if (fValidating) {

                              if (fGrammarIsDTDGrammar &&
                                  (fTempAttDecl.type == XMLAttributeDecl.TYPE_ENTITY ||
                                   fTempAttDecl.type == XMLAttributeDecl.TYPE_ENUMERATION ||
                                   fTempAttDecl.type == XMLAttributeDecl.TYPE_ID ||
                                   fTempAttDecl.type == XMLAttributeDecl.TYPE_IDREF ||
                                   fTempAttDecl.type == XMLAttributeDecl.TYPE_NMTOKEN ||
                                   fTempAttDecl.type == XMLAttributeDecl.TYPE_NOTATION)
                                 ) {
                                 validateDTDattribute(element, attrList.getAttValue(index), fTempAttDecl);
                              }

                              // check to see if this attribute matched an attribute wildcard
                              else if ( fGrammarIsSchemaGrammar &&
                                        (fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_ANY
                                         ||fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_LIST
                                         ||fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_LOCAL
                                         ||fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_OTHER) ) {

                                 if (fTempAttDecl.defaultType == XMLAttributeDecl.PROCESSCONTENTS_SKIP) {
                                    // attribute should just be bypassed,
                                 } else if ( fTempAttDecl.defaultType == XMLAttributeDecl.PROCESSCONTENTS_STRICT
                                             || fTempAttDecl.defaultType == XMLAttributeDecl.PROCESSCONTENTS_LAX) {

                                    boolean reportError = false;
                                    boolean processContentStrict =
                                    fTempAttDecl.defaultType == XMLAttributeDecl.PROCESSCONTENTS_STRICT;

                                    if (fTempQName.uri == -1) {
                                       if (processContentStrict) {
                                          reportError = true;
                                       }
                                    } else {
                                       Grammar aGrammar =
                                       fGrammarResolver.getGrammar(fStringPool.toString(fTempQName.uri));

                                       if (aGrammar == null || !(aGrammar instanceof SchemaGrammar) ) {
                                          if (processContentStrict) {
                                             reportError = true;
                                          }
                                       } else {
                                          SchemaGrammar sGrammar = (SchemaGrammar) aGrammar;
                                          Hashtable attRegistry = sGrammar.getAttirubteDeclRegistry();
                                          if (attRegistry == null) {
                                             if (processContentStrict) {
                                                reportError = true;
                                             }
                                          } else {
                                             XMLAttributeDecl attDecl = (XMLAttributeDecl) attRegistry.get(fStringPool.toString(fTempQName.localpart));
                                             if (attDecl == null) {
                                                if (processContentStrict) {
                                                   reportError = true;
                                                }
                                             } else {
                                                DatatypeValidator attDV = attDecl.datatypeValidator;
                                                if (attDV == null) {
                                                   if (processContentStrict) {
                                                      reportError = true;
                                                   }
                                                } else {
                                                   try {
                                                      String  unTrimValue = fStringPool.toString(attrList.getAttValue(index));
                                                      String  value       = unTrimValue.trim();
                                                      if (attDecl.type == XMLAttributeDecl.TYPE_ID ) {
                                                         this.fStoreIDRef.setDatatypeObject( fValID.validate( value, null ) );
                                                      }
                                                      if (attDecl.type == XMLAttributeDecl.TYPE_IDREF ) {
                                                         attDV.validate(value, this.fStoreIDRef );
                                                      } else
                                                         attDV.validate(unTrimValue, null );
                                                   } catch (InvalidDatatypeValueException idve) {
                                                      fErrorReporter.reportError(fErrorReporter.getLocator(),
                                                                                 SchemaMessageProvider.SCHEMA_DOMAIN,
                                                                                 SchemaMessageProvider.DatatypeError,
                                                                                 SchemaMessageProvider.MSG_NONE,
                                                                                 new Object [] { idve.getMessage()},
                                                                                 XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
                                                   }
                                                }
                                             }
                                          }
                                       }
                                    }
                                    if (reportError) {
                                       Object[] args = { fStringPool.toString(element.rawname),
                                          "ANY---"+fStringPool.toString(attrList.getAttrName(index))};

                                       fErrorReporter.reportError(fAttrNameLocator,   
                                                                  XMLMessages.XML_DOMAIN,
                                                                  XMLMessages.MSG_ATTRIBUTE_NOT_DECLARED,
                                                                  XMLMessages.VC_ATTRIBUTE_VALUE_TYPE,
                                                                  args,
                                                                  XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);

                                    }
                                 }
                              } else if (fTempAttDecl.datatypeValidator == null) {
                                 Object[] args = { fStringPool.toString(element.rawname),
                                    fStringPool.toString(attrList.getAttrName(index))};

                                 System.out.println("[Error] Datatypevalidator for attribute " + fStringPool.toString(attrList.getAttrName(index))
                                                    + " not found in element type " + fStringPool.toString(element.rawname));
                                 //REVISIT : is this the right message?
                                 /****/
                                 fErrorReporter.reportError(fAttrNameLocator,   
                                                            XMLMessages.XML_DOMAIN,
                                                            XMLMessages.MSG_ATTRIBUTE_NOT_DECLARED,
                                                            XMLMessages.VC_ATTRIBUTE_VALUE_TYPE,
                                                            args,
                                                            XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);  
                                 /****/
                              } else {
                                 try {
                                    String  unTrimValue = fStringPool.toString(attrList.getAttValue(index));
                                    String  value       = unTrimValue.trim();
                                    if (fTempAttDecl.type == XMLAttributeDecl.TYPE_ID ) {
                                       this.fStoreIDRef.setDatatypeObject( fValID.validate( value, null ) );
                                    } else if (fTempAttDecl.type == XMLAttributeDecl.TYPE_IDREF ) {
                                       fTempAttDecl.datatypeValidator.validate(value, this.fStoreIDRef );
                                    } else {
                                       fTempAttDecl.datatypeValidator.validate(unTrimValue, null );
                                    }

                                 } catch (InvalidDatatypeValueException idve) {
                                    fErrorReporter.reportError(fErrorReporter.getLocator(),
                                                               SchemaMessageProvider.SCHEMA_DOMAIN,
                                                               SchemaMessageProvider.DatatypeError,
                                                               SchemaMessageProvider.MSG_NONE,
                                                               new Object [] { idve.getMessage()},
                                                               XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
                                 }
                              }
                           } // end of if (fValidating)


                        } // end of if (attDefIndex == -1) else

                  }// end of if (fGrammar != null)
               index = fAttrList.getNextAttr(index);
            }
         }
      }
      if (fAttrListHandle != -1) {
         int index = attrList.getFirstAttr(fAttrListHandle);
         while (index != -1) {
            int attName = attrList.getAttrName(index);
            if (!fStringPool.equalNames(attName, fNamespacesPrefix)) {
               int attPrefix = attrList.getAttrPrefix(index);
               if (attPrefix != fNamespacesPrefix) {
                  if (attPrefix != -1) {
                     int uri = fNamespacesScope.getNamespaceForPrefix(attPrefix);
                     if (uri == -1) {
                        Object[] args = { fStringPool.toString(attPrefix)};
                        fErrorReporter.reportError(fErrorReporter.getLocator(),
                                                   XMLMessages.XMLNS_DOMAIN,
                                                   XMLMessages.MSG_PREFIX_DECLARED,
                                                   XMLMessages.NC_PREFIX_DECLARED,
                                                   args,
                                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
                     }
                     attrList.setAttrURI(index, uri);
                  }
               }
            }
            index = attrList.getNextAttr(index);
         }
      }

      fCurrentElementIndex = elementIndex;
      fCurrentContentSpecType = contentSpecType;

      if (fValidating && contentSpecType == XMLElementDecl.TYPE_SIMPLE) {
         fBufferDatatype = true;
         fDatatypeBuffer.setLength(0);
      }

      fInElementContent = (contentSpecType == XMLElementDecl.TYPE_CHILDREN);

   } // validateElementAndAttributes(QName,XMLAttrList)


   //validate attributes in DTD fashion
   private void validateDTDattribute(QName element, int attValue,
                                     XMLAttributeDecl attributeDecl) throws Exception{
      AttributeValidator av = null;
      switch (attributeDecl.type) {
      case XMLAttributeDecl.TYPE_ENTITY:
         {
            boolean isAlistAttribute = attributeDecl.list;//Caveat - Save this information because invalidStandaloneAttDef
            String  unTrimValue      = fStringPool.toString(attValue);
            String  value            = unTrimValue.trim();
            //System.out.println("value = " + value );
            //changes fTempAttDef
            if (fValidationEnabled) {
               if (value != unTrimValue) {
                  if (invalidStandaloneAttDef(element, attributeDecl.name)) {
                     reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
                                               XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
                                               fStringPool.toString(attributeDecl.name.rawname), unTrimValue, value);
                  }
               }
            }

            try {
               if ( isAlistAttribute ) {
                  fValENTITIES.validate( value, null );
               } else {
                  fValENTITY.validate( value, null );
               }
            } catch ( InvalidDatatypeValueException ex ) {
               if ( ex.getMajorCode() != 1 && ex.getMinorCode() != -1 ) {
                  reportRecoverableXMLError(ex.getMajorCode(),
                                            ex.getMinorCode(),
                                            fStringPool.toString( attributeDecl.name.rawname), value );
               } else {
                  System.err.println("Error: " + ex.getLocalizedMessage() );//Should not happen
               }
            }

            /*if (attributeDecl.list) {
                av = fAttValidatorENTITIES;
            }
            else {
                av = fAttValidatorENTITY;
            }*/

         }
         break;
      case XMLAttributeDecl.TYPE_ENUMERATION:
         av = fAttValidatorENUMERATION;
         break;
      case XMLAttributeDecl.TYPE_ID:
         {
            String  unTrimValue = fStringPool.toString(attValue);
            String  value       = unTrimValue.trim();
            if (fValidationEnabled) {
               if (value != unTrimValue) {
                  if (invalidStandaloneAttDef(element, attributeDecl.name)) {
                     reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
                                               XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
                                               fStringPool.toString(attributeDecl.name.rawname), unTrimValue, value);
                  }
               }
            }
            try {
               //this.fIdDefs = (Hashtable) fValID.validate( value, null );
               //System.out.println("this.fIdDefs = " + this.fIdDefs );

               this.fStoreIDRef.setDatatypeObject( fValID.validate( value, null ) );
               fValIDRef.validate( value, this.fStoreIDRef ); //just in case we called id after IDREF
            } catch ( InvalidDatatypeValueException ex ) {
               reportRecoverableXMLError(ex.getMajorCode(),
                                         ex.getMinorCode(),
                                         fStringPool.toString( attributeDecl.name.rawname), value );
            }
         }
         break;
      case XMLAttributeDecl.TYPE_IDREF:
         {
            String  unTrimValue = fStringPool.toString(attValue);
            String  value       = unTrimValue.trim();
            boolean isAlistAttribute = attributeDecl.list;//Caveat - Save this information because invalidStandaloneAttDef
                                                          //changes fTempAttDef
            if (fValidationEnabled) {
               if (value != unTrimValue) {
                  if (invalidStandaloneAttDef(element, attributeDecl.name)) {
                     reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
                                               XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
                                               fStringPool.toString(attributeDecl.name.rawname), unTrimValue, value);
                  }
               }
            }
            try {
               if ( isAlistAttribute ) {
                  fValIDRefs.validate( value, this.fStoreIDRef );
               } else {
                  fValIDRef.validate( value, this.fStoreIDRef );
               }
            } catch ( InvalidDatatypeValueException ex ) {
               if ( ex.getMajorCode() != 1 && ex.getMinorCode() != -1 ) {
                  reportRecoverableXMLError(ex.getMajorCode(),
                                            ex.getMinorCode(),
                                            fStringPool.toString( attributeDecl.name.rawname), value );
               } else {
                  System.err.println("Error: " + ex.getLocalizedMessage() );//Should not happen
               }
            }

         }
         break;
      case XMLAttributeDecl.TYPE_NOTATION:
         {
            /* WIP
            String  unTrimValue = fStringPool.toString(attValue);
         String  value       = unTrimValue.trim();
         if (fValidationEnabled) {
             if (value != unTrimValue) {
                 if (invalidStandaloneAttDef(element, attributeDecl.name)) {
                     reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
                                               XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
                                               fStringPool.toString(attributeDecl.name.rawname), unTrimValue, value);
                 }
             }
         }
         try {
             //this.fIdDefs = (Hashtable) fValID.validate( value, null );
             //System.out.println("this.fIdDefs = " + this.fIdDefs );

             this.fStoreIDRef.setDatatypeObject( fValID.validate( value, null ) );
         } catch ( InvalidDatatypeValueException ex ) {
             reportRecoverableXMLError(ex.getMajorCode(),
                                       ex.getMinorCode(),
                                       fStringPool.toString( attributeDecl.name.rawname), value );
         }
      }
        */
            av = fAttValidatorNOTATION;


         }
         break;
      case XMLAttributeDecl.TYPE_NMTOKEN:
         {
            String  unTrimValue = fStringPool.toString(attValue);
            String  value       = unTrimValue.trim();
            boolean isAlistAttribute = attributeDecl.list;//Caveat - Save this information because invalidStandaloneAttDef
            //changes fTempAttDef
            if (fValidationEnabled) {
               if (value != unTrimValue) {
                  if (invalidStandaloneAttDef(element, attributeDecl.name)) {
                     reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
                                               XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
                                               fStringPool.toString(attributeDecl.name.rawname), unTrimValue, value);
                  }
               }
            }
            try {
               if ( isAlistAttribute ) {
                  fValNMTOKENS.validate( value, null );
               } else {
                  fValNMTOKEN.validate( value, null );
               }
            } catch ( InvalidDatatypeValueException ex ) {
               reportRecoverableXMLError(XMLMessages.MSG_NMTOKEN_INVALID,
                                         XMLMessages.VC_NAME_TOKEN,
                                         fStringPool.toString(attributeDecl.name.rawname), value);//TODO NMTOKENS messge
            }

         }
         break;
      }
      if ( av != null )
         av.normalize(element, attributeDecl.name, attValue,
                      attributeDecl.type, attributeDecl.enumeration);
   }

   /** Character data in content. */
   private void charDataInContent() {

      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++;

   } // charDataInCount()

   /**
    * Check that the content of an element is valid.
    * <p>
    * 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.
    * <p>
    * This can also be called to do 'what if' testing of content models just to see
    * if they would be valid.
    * <p>
    * 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.
    * <p>
    * 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 <code>ElementDeclPool</code> of this
    *                     element.
    * @param childCount The number of entries in the <code>children</code> array.
    * @param children The children of this element.  Each integer is an index within
    *                 the <code>StringPool</code> of the child element name.  An index
    *                 of -1 is used to indicate an occurrence of non-whitespace character
    *                 data.
    *
    * @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.
    */
   private int checkContent(int elementIndex,
                            QName[] children,
                            int childOffset,
                            int childCount) throws Exception {

      // Get the element name index from the element
      // REVISIT: Validation
      final int elementType = fCurrentElement.rawname;

      if (DEBUG_PRINT_CONTENT) {
         String strTmp = fStringPool.toString(elementType);
         System.out.println("Name: "+strTmp+", "+
                            "Count: "+childCount+", "+
                            "ContentSpecType: " +fCurrentContentSpecType); //+getContentSpecAsString(elementIndex));
         for (int index = childOffset; index < (childOffset+childCount&& index < 10; index++) {
            if (index == 0) {
               System.out.print("  (");
            }
            String childName = (children[index].localpart == -1) ? "#PCDATA" : fStringPool.toString(children[index].localpart);
            if (index + 1 == childCount) {
               System.out.println(childName + ")");
            } else if (index + 1 == 10) {
               System.out.println(childName + ",...)");
            } else {
               System.out.print(childName + ",");
            }
         }
      }

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

// debugging
//System.out.println("~~~~~~in checkContent, fCurrentContentSpecType : " + 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
         XMLContentModel cmElem = null;
         try {
            cmElem = getElementContentModel(elementIndex);
            int result = cmElem.validateContent(children, childOffset, childCount);
            if (result != -1 && fGrammarIsSchemaGrammar) {
               // REVISIT: not optimized for performance,
               EquivClassComparator comparator = new EquivClassComparator(fGrammarResolver, fStringPool);
               cmElem.setEquivClassComparator(comparator);
               result = cmElem.validateContentSpecial(children, childOffset, childCount);
            }
            return result;
         } catch (CMException excToCatch) {
            // REVISIT - Translate the caught exception to the protected error API
            int majorCode = excToCatch.getErrorCode();
            fErrorReporter.reportError(fErrorReporter.getLocator(),
                                       ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
                                       majorCode,
                                       0,
                                       null,
                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
         }
      } else if (contentType == -1) {
         reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_NOT_DECLARED,
                                   XMLMessages.VC_ELEMENT_VALID,
                                   elementType);
      } else if (contentType == XMLElementDecl.TYPE_SIMPLE ) {

         XMLContentModel cmElem = null;
         if (childCount > 0) {
            fErrorReporter.reportError(fErrorReporter.getLocator(),
                                       SchemaMessageProvider.SCHEMA_DOMAIN,
                                       SchemaMessageProvider.DatatypeError,
                                       SchemaMessageProvider.MSG_NONE,
                                       new Object [] { "In element '"+fStringPool.toString(elementType)+"' : "+
                                          "Can not have element children within a simple type content"},
                                       XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
         } else {
            try {

               fGrammar.getElementDecl(elementIndex, fTempElementDecl);

               DatatypeValidator dv = fTempElementDecl.datatypeValidator;

               // If there is xsi:type validator, substitute it.
               if ( fXsiTypeValidator != null ) {
                  dv = fXsiTypeValidator;
                  fXsiTypeValidator = null;
               }

               if (dv == null) {
                  System.out.println("Internal Error: this element have a simpletype "+
                                     "but no datatypevalidator was found, element "+fTempElementDecl.name
                                     +",locapart: "+fStringPool.toString(fTempElementDecl.name.localpart));
               } else {
                  dv.validate(fDatatypeBuffer.toString(), null);
               }

            } catch (InvalidDatatypeValueException idve) {
               fErrorReporter.reportError(fErrorReporter.getLocator(),
                                          SchemaMessageProvider.SCHEMA_DOMAIN,
                                          SchemaMessageProvider.DatatypeError,
                                          SchemaMessageProvider.MSG_NONE,
                                          new Object [] { "In element '"+fStringPool.toString(elementType)+"' : "+idve.getMessage()},
                                          XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
            }
         }
      } else {
         fErrorReporter.reportError(fErrorReporter.getLocator(),
                                    ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
                                    ImplementationMessages.VAL_CST,
                                    0,
                                    null,
                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
      }

      // We succeeded
      return -1;

   } // checkContent(int,int,int[]):int


   /**
    * Checks that all declared elements refer to declared elements
    * in their content models. This method calls out to the error
    * handler to indicate warnings.
    */
   /*private void checkDeclaredElements() throws Exception {

               //****DEBUG****
               if (DEBUG) print("(???) XMLValidator.checkDeclaredElements\n");
               //****DEBUG****

       for (int i = 0; i < fElementCount; i++) {
           int type = fGrammar.getContentSpecType(i);
           if (type == XMLElementDecl.TYPE_MIXED || type == XMLElementDecl.TYPE_CHILDREN) {
               int chunk = i >> CHUNK_SHIFT;
               int index = i &  CHUNK_MASK;
               int contentSpecIndex = fContentSpec[chunk][index];
               checkDeclaredElements(i, contentSpecIndex);
           }
       }
   }
   */

   private void printChildren() {
      if (DEBUG_ELEMENT_CHILDREN) {
         System.out.print('[');
         for (int i = 0; i < fElementChildrenLength; i++) {
            System.out.print(' ');
            QName qname = fElementChildren[i];
            if (qname != null) {
               System.out.print(fStringPool.toString(qname.rawname));
            } else {
               System.out.print("null");
            }
            if (i < fElementChildrenLength - 1) {
               System.out.print(", ");
            }
            System.out.flush();
         }
         System.out.print(" ]");
         System.out.println();
      }
   }

   private void printStack() {
      if (DEBUG_ELEMENT_CHILDREN) {
         System.out.print('{');
         for (int i = 0; i <= fElementDepth; i++) {
            System.out.print(' ');
            System.out.print(fElementChildrenOffsetStack[i]);
            if (i < fElementDepth) {
               System.out.print(", ");
            }
            System.out.flush();
         }
         System.out.print(" }");
         System.out.println();
      }
   }


   //
   // Interfaces
   //

   /**
    * AttributeValidator.
    */
   public interface AttributeValidator {

      //
      // AttributeValidator methods
      //

      /** Normalize. */
      public int normalize(QName element, QName attribute,
                           int attValue, int attType, int enumHandle)
      throws Exception;

   } // interface AttributeValidator


   /** Returns true if invalid standalone attribute definition. */
   boolean invalidStandaloneAttDef(QName element, QName attribute) {
      if (fStandaloneReader == -1) {
         return false;
      }
      // we are normalizing a default att value...  this ok?
      if (element.rawname == -1) {
         return false;
      }
      return getAttDefIsExternal(element, attribute);
   }


   //
   // Classes
   //


   /**
    * AttValidatorNOTATION.
    */
   final class AttValidatorNOTATION
   implements AttributeValidator {

      //
      // AttributeValidator methods
      //

      /** Normalize. */
      public int normalize(QName element, QName attribute,
                           int attValueHandle, int attType,
                           int enumHandle) throws Exception {
         //
         // Normalize attribute based upon attribute type...
         //
         String attValue = fStringPool.toString(attValueHandle);
         String newAttValue = attValue.trim();
         if (fValidating) {
            // REVISIT - can we release the old string?
            if (newAttValue != attValue) {
               if (invalidStandaloneAttDef(element, attribute)) {
                  reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
                                            XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
                                            fStringPool.toString(attribute.rawname), attValue, newAttValue);
               }
               attValueHandle = fStringPool.addSymbol(newAttValue);
            } else {
               attValueHandle = fStringPool.addSymbol(attValueHandle);
            }
            //
            // NOTATION - check that the value is in the AttDef enumeration (V_TAGo)
            //
            if (!fStringPool.stringInList(enumHandle, attValueHandle)) {
               reportRecoverableXMLError(XMLMessages.MSG_ATTRIBUTE_VALUE_NOT_IN_LIST,
                                         XMLMessages.VC_NOTATION_ATTRIBUTES,
                                         fStringPool.toString(attribute.rawname),
                                         newAttValue, fStringPool.stringListAsString(enumHandle));
            }
         } else if (newAttValue != attValue) {
            // REVISIT - can we release the old string?
            attValueHandle = fStringPool.addSymbol(newAttValue);
         }
         return attValueHandle;

      } // normalize(QName,QName,int,int,int):int

      //
      // Package methods
      //

      /** Returns true if invalid standalone attribute definition. */
      boolean invalidStandaloneAttDef(QName element, QName attribute) {
         if (fStandaloneReader == -1) {
            return false;
         }
         // we are normalizing a default att value...  this ok?
         if (element.rawname == -1) {
            return false;
         }
         return getAttDefIsExternal(element, attribute);
      }

   } // class AttValidatorNOTATION

   /**
    * AttValidatorENUMERATION.
    */
   final class AttValidatorENUMERATION
   implements AttributeValidator {

      //
      // AttributeValidator methods
      //

      /** Normalize. */
      public int normalize(QName element, QName attribute,
                           int attValueHandle, int attType,
                           int enumHandle) throws Exception {
         //
         // Normalize attribute based upon attribute type...
         //
         String attValue = fStringPool.toString(attValueHandle);
         String newAttValue = attValue.trim();
         if (fValidating) {
            // REVISIT - can we release the old string?
            if (newAttValue != attValue) {
               if (invalidStandaloneAttDef(element, attribute)) {
                  reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
                                            XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
                                            fStringPool.toString(attribute.rawname), attValue, newAttValue);
               }
               attValueHandle = fStringPool.addSymbol(newAttValue);
            } else {
               attValueHandle = fStringPool.addSymbol(attValueHandle);
            }
            //
            // ENUMERATION - check that value is in the AttDef enumeration (V_TAG9)
            //
            if (!fStringPool.stringInList(enumHandle, attValueHandle)) {
               reportRecoverableXMLError(XMLMessages.MSG_ATTRIBUTE_VALUE_NOT_IN_LIST,
                                         XMLMessages.VC_ENUMERATION,
                                         fStringPool.toString(attribute.rawname),
                                         newAttValue, fStringPool.stringListAsString(enumHandle));
            }
         } else if (newAttValue != attValue) {
            // REVISIT - can we release the old string?
            attValueHandle = fStringPool.addSymbol(newAttValue);
         }
         return attValueHandle;

      } // normalize(QName,QName,int,int,int):int

      //
      // Package methods
      //

      /** Returns true if invalid standalone attribute definition. */
      boolean invalidStandaloneAttDef(QName element, QName attribute) {
         if (fStandaloneReader == -1) {
            return false;
         }
         // we are normalizing a default att value...  this ok?
         if (element.rawname == -1) {
            return false;
         }
         return getAttDefIsExternal(element, attribute);
      }

   } // class AttValidatorENUMERATION

} // class XMLValidator
TOP

Related Classes of org.apache.xerces.validators.common.XMLValidator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.