Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/xerces/validators/common/XMLValidator.java


1   /*
2    * The Apache Software License, Version 1.1
3    *
4    *
5    * Copyright (c) 1999,2000 The Apache Software Foundation.  All rights 
6    * reserved.
7    *
8    * Redistribution and use in source and binary forms, with or without
9    * modification, are permitted provided that the following conditions
10   * are met:
11   *
12   * 1. Redistributions of source code must retain the above copyright
13   *    notice, this list of conditions and the following disclaimer. 
14   *
15   * 2. Redistributions in binary form must reproduce the above copyright
16   *    notice, this list of conditions and the following disclaimer in
17   *    the documentation and/or other materials provided with the
18   *    distribution.
19   *
20   * 3. The end-user documentation included with the redistribution,
21   *    if any, must include the following acknowledgment:  
22   *       "This product includes software developed by the
23   *        Apache Software Foundation (http://www.apache.org/)."
24   *    Alternately, this acknowledgment may appear in the software itself,
25   *    if and wherever such third-party acknowledgments normally appear.
26   *
27   * 4. The names "Xerces" and "Apache Software Foundation" must
28   *    not be used to endorse or promote products derived from this
29   *    software without prior written permission. For written 
30   *    permission, please contact apache@apache.org.
31   *
32   * 5. Products derived from this software may not be called "Apache",
33   *    nor may "Apache" appear in their name, without prior written
34   *    permission of the Apache Software Foundation.
35   *
36   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47   * SUCH DAMAGE.
48   * ====================================================================
49   *
50   * This software consists of voluntary contributions made by many
51   * individuals on behalf of the Apache Software Foundation and was
52   * originally based on software copyright (c) 1999, International
53   * Business Machines, Inc., http://www.apache.org.  For more
54   * information on the Apache Software Foundation, please see
55   * <http://www.apache.org/>.
56   */
57  
58  package org.apache.xerces.validators.common;
59  
60  import org.apache.xerces.framework.XMLAttrList;
61  import org.apache.xerces.framework.XMLContentSpec;
62  import org.apache.xerces.framework.XMLDocumentHandler;
63  import org.apache.xerces.framework.XMLDocumentScanner;
64  import org.apache.xerces.framework.XMLErrorReporter;
65  import org.apache.xerces.readers.DefaultEntityHandler;
66  import org.apache.xerces.readers.XMLEntityHandler;
67  import org.apache.xerces.utils.ChunkyCharArray;
68  import org.apache.xerces.utils.Hash2intTable;
69  import org.apache.xerces.utils.NamespacesScope;
70  import org.apache.xerces.utils.QName;
71  import org.apache.xerces.utils.StringPool;
72  import org.apache.xerces.utils.XMLCharacterProperties;
73  import org.apache.xerces.utils.XMLMessages;
74  import org.apache.xerces.utils.ImplementationMessages;
75  
76  import org.apache.xerces.parsers.DOMParser;
77  
78  import org.w3c.dom.Document;
79  import org.w3c.dom.Element;
80  
81  import org.xml.sax.InputSource;
82  import org.xml.sax.EntityResolver;
83  import org.xml.sax.Locator;
84  import org.xml.sax.helpers.LocatorImpl;
85  import org.xml.sax.SAXException;
86  import org.xml.sax.SAXParseException;
87  
88  import java.io.IOException;
89  import java.io.InputStream;
90  
91  import java.util.Enumeration;
92  import java.util.Hashtable;
93  import java.util.StringTokenizer;
94  import java.util.Vector;
95  
96  import org.apache.xerces.validators.dtd.DTDGrammar;
97  
98  import org.apache.xerces.validators.schema.EquivClassComparator;
99  import org.apache.xerces.validators.schema.SchemaGrammar;
100 import org.apache.xerces.validators.schema.SchemaMessageProvider;
101 import org.apache.xerces.validators.schema.SchemaSymbols;
102 import org.apache.xerces.validators.schema.TraverseSchema;
103 
104 import org.apache.xerces.validators.datatype.DatatypeValidatorFactoryImpl;
105 import org.apache.xerces.validators.datatype.DatatypeValidator;
106 import org.apache.xerces.validators.datatype.InvalidDatatypeValueException;
107 import org.apache.xerces.validators.datatype.StateMessageDatatype;
108 import org.apache.xerces.validators.datatype.IDREFDatatypeValidator;
109 import org.apache.xerces.validators.datatype.IDDatatypeValidator;
110 import org.apache.xerces.validators.datatype.ENTITYDatatypeValidator;
111 
112 /**
113  * This class is the super all-in-one validator used by the parser.
114  *
115  * @version $Id: XMLValidator.java,v 1.2 2000/10/07 18:06:55 markd Exp $
116  */
117 public final class XMLValidator
118 implements DefaultEntityHandler.EventHandler,
119 XMLEntityHandler.CharDataHandler,
120 XMLDocumentScanner.EventHandler,
121 NamespacesScope.NamespacesHandler {
122 
123     //
124     // Constants
125     //
126 
127     // debugging
128 
129     private static final boolean PRINT_EXCEPTION_STACK_TRACE = false;
130     private static final boolean DEBUG_PRINT_ATTRIBUTES = false;
131     private static final boolean DEBUG_PRINT_CONTENT = false;
132     private static final boolean DEBUG_SCHEMA_VALIDATION = false;
133     private static final boolean DEBUG_ELEMENT_CHILDREN = false;
134 
135     // Chunk size constants
136 
137     private static final int CHUNK_SHIFT = 8;           // 2^8 = 256
138     private static final int CHUNK_SIZE = (1 << CHUNK_SHIFT);
139     private static final int CHUNK_MASK = CHUNK_SIZE - 1;
140     private static final int INITIAL_CHUNK_COUNT = (1 << (10 - CHUNK_SHIFT));   // 2^10 = 1k
141 
142     private Hashtable fIdDefs = null;
143 
144 
145     private  StateMessageDatatype fStoreIDRef = new StateMessageDatatype() {
146         private Hashtable fIdDefs;
147         public Object getDatatypeObject(){
148             return(Object) fIdDefs;
149         }
150         public int    getDatatypeState(){
151             return IDREFDatatypeValidator.IDREF_STORE;
152         }
153         public void setDatatypeObject( Object data ){
154             fIdDefs = (Hashtable) data;
155         }
156     };
157 
158     private StateMessageDatatype fResetID = new StateMessageDatatype() {
159         public Object getDatatypeObject(){
160             return(Object) null;
161         }
162         public int    getDatatypeState(){
163             return IDDatatypeValidator.ID_CLEAR;
164         }
165         public void setDatatypeObject( Object data ){
166         }
167     };
168 
169 
170     private StateMessageDatatype fResetIDRef = new StateMessageDatatype() {
171         public Object getDatatypeObject(){
172             return(Object) null;
173         }
174         public int    getDatatypeState(){
175             return IDREFDatatypeValidator.IDREF_CLEAR;
176         }
177         public void setDatatypeObject( Object data ){
178         }
179     };
180 
181     private  StateMessageDatatype fValidateIDRef = new StateMessageDatatype() {
182         public Object getDatatypeObject(){
183             return(Object) null;
184         }
185         public int    getDatatypeState(){
186             return IDREFDatatypeValidator.IDREF_VALIDATE;
187         }
188         public void setDatatypeObject( Object data ){
189         }
190     };
191 
192 
193     private  StateMessageDatatype fValidateENTITYMsg = new StateMessageDatatype() {
194         private  Object  packagedMessage = null;
195         public Object getDatatypeObject(){
196             return packagedMessage;
197         }
198         public int    getDatatypeState(){
199             return ENTITYDatatypeValidator.ENTITY_INITIALIZE;//No state
200         }
201         public void setDatatypeObject( Object data ){
202             packagedMessage = data;// Set Entity Handler
203         }
204     };
205 
206     /*
207     private  StateMessageDatatype fValidateNOTATIONMsg = new StateMessageDatatype() {
208         private  Object  packagedMessage = null;
209         public Object getDatatypeObject(){
210             return packagedMessage;
211         }
212         public int    getDatatypeState(){
213             return NOTATIONDatatypeValidator.ENTITY_INITIALIZE;//No state
214         }
215         public void setDatatypeObject( Object data ){
216             packagedMessage = data;// Set Entity Handler
217         }
218     };
219     */
220 
221 
222 
223 
224 
225     //
226     // Data
227     //
228 
229     // REVISIT: The data should be regrouped and re-organized so that
230     //          it's easier to find a meaningful field.
231 
232     // debugging
233 
234 //    private static boolean DEBUG = false;
235 
236     // other
237 
238     // attribute validators
239 
240     private AttributeValidator fAttValidatorNOTATION = new AttValidatorNOTATION();
241     private AttributeValidator fAttValidatorENUMERATION = new AttValidatorENUMERATION();
242     private AttributeValidator fAttValidatorDATATYPE = null;
243 
244     // Package access for use by AttributeValidator classes.
245 
246     StringPool fStringPool = null;
247     boolean fValidating = false;
248     boolean fInElementContent = false;
249     int fStandaloneReader = -1;
250 
251 
252     // settings
253 
254     private boolean fValidationEnabled = false;
255     private boolean fDynamicValidation = false;
256     private boolean fSchemaValidation = true;
257     private boolean fValidationEnabledByDynamic = false;
258     private boolean fDynamicDisabledByValidation = false;
259     private boolean fWarningOnDuplicateAttDef = false;
260     private boolean fWarningOnUndeclaredElements = false;
261     private boolean fLoadDTDGrammar = true;
262 
263     // declarations
264 
265     private int fDeclaration[];
266     private XMLErrorReporter fErrorReporter = null;
267     private DefaultEntityHandler fEntityHandler = null;
268     private QName fCurrentElement = new QName();
269 
270     private ContentLeafNameTypeVector[] fContentLeafStack = new ContentLeafNameTypeVector[8];
271     private int[] fValidationFlagStack = new int[8];
272 
273     private int[] fScopeStack = new int[8];
274     private int[] fGrammarNameSpaceIndexStack = new int[8];
275 
276     private int[] fElementEntityStack = new int[8];
277     private int[] fElementIndexStack = new int[8];
278     private int[] fContentSpecTypeStack = new int[8];
279 
280     private static final int sizeQNameParts      = 8;
281     private QName[] fElementQNamePartsStack      = new QName[sizeQNameParts];
282 
283     private QName[] fElementChildren = new QName[32];
284     private int fElementChildrenLength = 0;
285     private int[] fElementChildrenOffsetStack = new int[32];
286     private int fElementDepth = -1;
287 
288     private boolean fNamespacesEnabled = false;
289     private NamespacesScope fNamespacesScope = null;
290     private int fNamespacesPrefix = -1;
291     private QName fRootElement = new QName();
292     private int fAttrListHandle = -1;
293     private int fCurrentElementEntity = -1;
294     private int fCurrentElementIndex = -1;
295     private int fCurrentContentSpecType = -1;
296     private boolean fSeenDoctypeDecl = false;
297 
298     private final int TOP_LEVEL_SCOPE = -1;
299     private int fCurrentScope = TOP_LEVEL_SCOPE;
300     private int fCurrentSchemaURI = -1;
301     private int fEmptyURI = - 1; 
302     private int fXsiPrefix = - 1;
303     private int fXsiURI = -2; 
304     private int fXsiTypeAttValue = -1;
305     private DatatypeValidator fXsiTypeValidator = null;
306 
307     private Grammar fGrammar = null;
308     private int fGrammarNameSpaceIndex = -1;
309     private GrammarResolver fGrammarResolver = null;
310 
311     // state and stuff
312 
313     private boolean fScanningDTD = false;
314     private XMLDocumentScanner fDocumentScanner = null;
315     private boolean fCalledStartDocument = false;
316     private XMLDocumentHandler fDocumentHandler = null;
317     private XMLDocumentHandler.DTDHandler fDTDHandler = null;
318     private boolean fSeenRootElement = false;
319     private XMLAttrList fAttrList = null;
320     private int fXMLLang = -1;
321     private LocatorImpl fAttrNameLocator = null;
322     private boolean fCheckedForSchema = false;
323     private boolean fDeclsAreExternal = false;
324     private StringPool.CharArrayRange fCurrentElementCharArrayRange = null;
325     private char[] fCharRefData = null;
326     private boolean fSendCharDataAsCharArray = false;
327     private boolean fBufferDatatype = false;
328     private StringBuffer fDatatypeBuffer = new StringBuffer();
329 
330     private QName fTempQName = new QName();
331     private XMLAttributeDecl fTempAttDecl = new XMLAttributeDecl();
332     private XMLAttributeDecl fTempAttributeDecl = new XMLAttributeDecl();
333     private XMLElementDecl fTempElementDecl = new XMLElementDecl();
334 
335     private boolean fGrammarIsDTDGrammar = false;
336     private boolean fGrammarIsSchemaGrammar = false;
337 
338     private boolean fNeedValidationOff = false;
339 
340     // symbols
341 
342     private int fEMPTYSymbol = -1;
343     private int fANYSymbol = -1;
344     private int fMIXEDSymbol = -1;
345     private int fCHILDRENSymbol = -1;
346     private int fCDATASymbol = -1;
347     private int fIDSymbol = -1;
348     private int fIDREFSymbol = -1;
349     private int fIDREFSSymbol = -1;
350     private int fENTITYSymbol = -1;
351     private int fENTITIESSymbol = -1;
352     private int fNMTOKENSymbol = -1;
353     private int fNMTOKENSSymbol = -1;
354     private int fNOTATIONSymbol = -1;
355     private int fENUMERATIONSymbol = -1;
356     private int fREQUIREDSymbol = -1;
357     private int fFIXEDSymbol = -1;
358     private int fDATATYPESymbol = -1;
359     private int fEpsilonIndex = -1;
360 
361 
362     //Datatype Registry
363 
364     private DatatypeValidatorFactoryImpl fDataTypeReg = 
365     DatatypeValidatorFactoryImpl.getDatatypeRegistry();
366 
367     private DatatypeValidator     fValID   = this.fDataTypeReg.getDatatypeValidator("ID" );
368     private DatatypeValidator fValIDRef    = this.fDataTypeReg.getDatatypeValidator("IDREF" );
369     private DatatypeValidator fValIDRefs   = this.fDataTypeReg.getDatatypeValidator("IDREFS" );
370     private DatatypeValidator fValENTITY   = this.fDataTypeReg.getDatatypeValidator("ENTITY" );
371     private DatatypeValidator fValENTITIES = this.fDataTypeReg.getDatatypeValidator("ENTITIES" );
372     private DatatypeValidator fValNMTOKEN  = this.fDataTypeReg.getDatatypeValidator("NMTOKEN");
373     private DatatypeValidator fValNMTOKENS = this.fDataTypeReg.getDatatypeValidator("NMTOKENS");
374     private DatatypeValidator fValNOTATION = this.fDataTypeReg.getDatatypeValidator("NOTATION" );
375 
376 
377     //
378     // Constructors
379     //
380 
381     /** Constructs an XML validator. */
382     public XMLValidator(StringPool stringPool,
383                         XMLErrorReporter errorReporter,
384                         DefaultEntityHandler entityHandler,
385                         XMLDocumentScanner documentScanner) {
386 
387         // keep references
388         fStringPool = stringPool;
389         fErrorReporter = errorReporter;
390         fEntityHandler = entityHandler;
391         fDocumentScanner = documentScanner;
392 
393         fEmptyURI = fStringPool.addSymbol("");
394         fXsiURI = fStringPool.addSymbol(SchemaSymbols.URI_XSI);
395         // initialize
396         fAttrList = new XMLAttrList(fStringPool);
397         entityHandler.setEventHandler(this);
398         entityHandler.setCharDataHandler(this);
399         fDocumentScanner.setEventHandler(this);
400 
401         for (int i = 0; i < sizeQNameParts; i++) {
402             fElementQNamePartsStack[i] = new QName();
403         }
404         init();
405 
406     } // <init>(StringPool,XMLErrorReporter,DefaultEntityHandler,XMLDocumentScanner)
407 
408     public void setGrammarResolver(GrammarResolver grammarResolver){
409         fGrammarResolver = grammarResolver;
410     }
411 
412     //
413     // Public methods
414     //
415 
416     // initialization
417 
418     /** Set char data processing preference and handlers. */
419     public void initHandlers(boolean sendCharDataAsCharArray,
420                              XMLDocumentHandler docHandler,
421                              XMLDocumentHandler.DTDHandler dtdHandler) {
422 
423         fSendCharDataAsCharArray = sendCharDataAsCharArray;
424         fEntityHandler.setSendCharDataAsCharArray(fSendCharDataAsCharArray);
425         fDocumentHandler = docHandler;
426         fDTDHandler = dtdHandler;
427 
428     } // initHandlers(boolean,XMLDocumentHandler,XMLDocumentHandler.DTDHandler)
429 
430     /** Reset or copy. */
431     public void resetOrCopy(StringPool stringPool) throws Exception {
432         fAttrList = new XMLAttrList(stringPool);
433         resetCommon(stringPool);
434     }
435 
436     /** Reset. */
437     public void reset(StringPool stringPool) throws Exception {
438         fAttrList.reset(stringPool);
439         resetCommon(stringPool);
440     }
441 
442 
443     // settings
444 
445     /**
446      * Turning on validation/dynamic turns on validation if it is off, and 
447      * this is remembered.  Turning off validation DISABLES validation/dynamic
448      * if it is on.  Turning off validation/dynamic DOES NOT turn off
449      * validation if it was explicitly turned on, only if it was turned on
450      * BECAUSE OF the call to turn validation/dynamic on.  Turning on
451      * validation will REENABLE and turn validation/dynamic back on if it
452      * was disabled by a call that turned off validation while 
453      * validation/dynamic was enabled.
454      */
455     public void setValidationEnabled(boolean flag) throws Exception {
456         fValidationEnabled = flag;
457         fValidationEnabledByDynamic = false;
458         if (fValidationEnabled) {
459             if (fDynamicDisabledByValidation) {
460                 fDynamicValidation = true;
461                 fDynamicDisabledByValidation = false;
462             }
463         } else if (fDynamicValidation) {
464             fDynamicValidation = false;
465             fDynamicDisabledByValidation = true;
466         }
467         fValidating = fValidationEnabled;
468     }
469 
470     /** Returns true if validation is enabled. */
471     public boolean getValidationEnabled() {
472         return fValidationEnabled;
473     }
474 
475     /** Sets whether Schema support is on/off. */
476     public void setSchemaValidationEnabled(boolean flag) {
477         fSchemaValidation = flag;
478     }
479 
480     /** Returns true if Schema support is on. */
481     public boolean getSchemaValidationEnabled() {
482         return fSchemaValidation;
483     }
484 
485     /** Sets whether validation is dynamic. */
486     public void setDynamicValidationEnabled(boolean flag) throws Exception {
487         fDynamicValidation = flag;
488         fDynamicDisabledByValidation = false;
489         if (!fDynamicValidation) {
490             if (fValidationEnabledByDynamic) {
491                 fValidationEnabled = false;
492                 fValidationEnabledByDynamic = false;
493             }
494         } else if (!fValidationEnabled) {
495             fValidationEnabled = true;
496             fValidationEnabledByDynamic = true;
497         }
498         fValidating = fValidationEnabled;
499     }
500 
501     /** Returns true if validation is dynamic. */
502     public boolean getDynamicValidationEnabled() {
503         return fDynamicValidation;
504     }
505 
506     /** Sets fLoadDTDGrammar when validation is off **/
507     public void setLoadDTDGrammar(boolean loadDG){
508         if (fValidating) {
509             fLoadDTDGrammar = true;
510         } else {
511             fLoadDTDGrammar = loadDG;
512         }
513     }
514 
515     /** Returns fLoadDTDGrammar **/
516     public boolean getLoadDTDGrammar() {
517         return fLoadDTDGrammar;
518     }
519 
520     /** Sets whether namespaces are enabled. */
521     public void setNamespacesEnabled(boolean flag) {
522         fNamespacesEnabled = flag;
523     }
524 
525     /** Returns true if namespaces are enabled. */
526     public boolean getNamespacesEnabled() {
527         return fNamespacesEnabled;
528     }
529 
530     /** Sets whether duplicate attribute definitions signal a warning. */
531     public void setWarningOnDuplicateAttDef(boolean flag) {
532         fWarningOnDuplicateAttDef = flag;
533     }
534 
535     /** Returns true if duplicate attribute definitions signal a warning. */
536     public boolean getWarningOnDuplicateAttDef() {
537         return fWarningOnDuplicateAttDef;
538     }
539 
540     /** Sets whether undeclared elements signal a warning. */
541     public void setWarningOnUndeclaredElements(boolean flag) {
542         fWarningOnUndeclaredElements = flag;
543     }
544 
545     /** Returns true if undeclared elements signal a warning. */
546     public boolean getWarningOnUndeclaredElements() {
547         return fWarningOnUndeclaredElements;
548     }
549 
550     //
551     // DefaultEntityHandler.EventHandler methods
552     //
553 
554     /** Start entity reference. */
555     public void startEntityReference(int entityName, int entityType, int entityContext) throws Exception {
556         fDocumentHandler.startEntityReference(entityName, entityType, entityContext);
557     }
558 
559     /** End entity reference. */
560     public void endEntityReference(int entityName, int entityType, int entityContext) throws Exception {
561         fDocumentHandler.endEntityReference(entityName, entityType, entityContext);
562     }
563 
564     /** Send end of input notification. */
565     public void sendEndOfInputNotifications(int entityName, boolean moreToFollow) throws Exception {
566         fDocumentScanner.endOfInput(entityName, moreToFollow);
567         /***
568         if (fScanningDTD) {
569             fDTDImporter.sendEndOfInputNotifications(entityName, moreToFollow);
570         }
571         /***/
572     }
573 
574     /** Send reader change notifications. */
575     public void sendReaderChangeNotifications(XMLEntityHandler.EntityReader reader, int readerId) throws Exception {
576         fDocumentScanner.readerChange(reader, readerId);
577         /***
578         if (fScanningDTD) {
579             fDTDImporter.sendReaderChangeNotifications(reader, readerId);
580         }
581         /***/
582     }
583 
584     /** External entity standalone check. */
585     public boolean externalEntityStandaloneCheck() {
586         return(fStandaloneReader != -1 && fValidating);
587     }
588 
589     /** Return true if validating. */
590     public boolean getValidating() {
591         return fValidating;
592     }
593 
594     //
595     // XMLEntityHandler.CharDataHandler methods
596     //
597 
598     /** Process characters. */
599     public void processCharacters(char[] chars, int offset, int length) throws Exception {
600         if (fValidating) {
601             if (fInElementContent || fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
602                 charDataInContent();
603             }
604             if (fBufferDatatype) {
605                 fDatatypeBuffer.append(chars, offset, length);
606             }
607         }
608         fDocumentHandler.characters(chars, offset, length);
609     }
610 
611     /** Process characters. */
612     public void processCharacters(int data) throws Exception {
613         if (fValidating) {
614             if (fInElementContent || fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
615                 charDataInContent();
616             }
617             if (fBufferDatatype) {
618                 fDatatypeBuffer.append(fStringPool.toString(data));
619             }
620         }
621         fDocumentHandler.characters(data);
622     }
623 
624     /** Process whitespace. */
625     public void processWhitespace(char[] chars, int offset, int length) 
626     throws Exception {
627 
628         if (fInElementContent) {
629             if (fStandaloneReader != -1 && fValidating && getElementDeclIsExternal(fCurrentElementIndex)) {
630                 reportRecoverableXMLError(XMLMessages.MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE,
631                                           XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION);
632             }
633             fDocumentHandler.ignorableWhitespace(chars, offset, length);
634         } else {
635             if (fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
636                 charDataInContent();
637             }
638             fDocumentHandler.characters(chars, offset, length);
639         }
640 
641     } // processWhitespace(char[],int,int)
642 
643     /** Process whitespace. */
644     public void processWhitespace(int data) throws Exception {
645 
646         if (fInElementContent) {
647             if (fStandaloneReader != -1 && fValidating && getElementDeclIsExternal(fCurrentElementIndex)) {
648                 reportRecoverableXMLError(XMLMessages.MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE,
649                                           XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION);
650             }
651             fDocumentHandler.ignorableWhitespace(data);
652         } else {
653             if (fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
654                 charDataInContent();
655             }
656             fDocumentHandler.characters(data);
657         }
658 
659     } // processWhitespace(int)
660 
661     //
662     // XMLDocumentScanner.EventHandler methods
663     //
664 
665     /** Scans element type. */
666     public void scanElementType(XMLEntityHandler.EntityReader entityReader, 
667                                 char fastchar, QName element) throws Exception {
668 
669         if (!fNamespacesEnabled) {
670             element.clear();
671             element.localpart = entityReader.scanName(fastchar);
672             element.rawname = element.localpart;
673         } else {
674             entityReader.scanQName(fastchar, element);
675             if (entityReader.lookingAtChar(':', false)) {
676                 fErrorReporter.reportError(fErrorReporter.getLocator(),
677                                            XMLMessages.XML_DOMAIN,
678                                            XMLMessages.MSG_TWO_COLONS_IN_QNAME,
679                                            XMLMessages.P5_INVALID_CHARACTER,
680                                            null,
681                                            XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
682                 entityReader.skipPastNmtoken(' ');
683             }
684         }
685 
686     } // scanElementType(XMLEntityHandler.EntityReader,char,QName)
687 
688     /** Scans expected element type. */
689     public boolean scanExpectedElementType(XMLEntityHandler.EntityReader entityReader, 
690                                            char fastchar, QName element) 
691     throws Exception {
692 
693         if (fCurrentElementCharArrayRange == null) {
694             fCurrentElementCharArrayRange = fStringPool.createCharArrayRange();
695         }
696         fStringPool.getCharArrayRange(fCurrentElement.rawname, fCurrentElementCharArrayRange);
697         return entityReader.scanExpectedName(fastchar, fCurrentElementCharArrayRange);
698 
699     } // scanExpectedElementType(XMLEntityHandler.EntityReader,char,QName)
700 
701     /** Scans attribute name. */
702     public void scanAttributeName(XMLEntityHandler.EntityReader entityReader, 
703                                   QName element, QName attribute) 
704     throws Exception {
705 
706         if (!fSeenRootElement) {
707             fSeenRootElement = true;
708             rootElementSpecified(element);
709             fStringPool.resetShuffleCount();
710         }
711 
712         if (!fNamespacesEnabled) {
713             attribute.clear();
714             attribute.localpart = entityReader.scanName('=');
715             attribute.rawname = attribute.localpart;
716         } else {
717             entityReader.scanQName('=', attribute);
718             if (entityReader.lookingAtChar(':', false)) {
719                 fErrorReporter.reportError(fErrorReporter.getLocator(),
720                                            XMLMessages.XML_DOMAIN,
721                                            XMLMessages.MSG_TWO_COLONS_IN_QNAME,
722                                            XMLMessages.P5_INVALID_CHARACTER,
723                                            null,
724                                            XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
725                 entityReader.skipPastNmtoken(' ');
726             }
727         }
728 
729     } // scanAttributeName(XMLEntityHandler.EntityReader,QName,QName)
730 
731     /** Call start document. */
732     public void callStartDocument() throws Exception {
733 
734         if (!fCalledStartDocument) {
735             fDocumentHandler.startDocument();
736             fCalledStartDocument = true;
737         }
738     }
739 
740     /** Call end document. */
741     public void callEndDocument() throws Exception {
742 
743         if (fCalledStartDocument) {
744             fDocumentHandler.endDocument();
745         }
746     }
747 
748     /** Call XML declaration. */
749     public void callXMLDecl(int version, int encoding, int standalone) throws Exception {
750         fDocumentHandler.xmlDecl(version, encoding, standalone);
751     }
752     public void callStandaloneIsYes() throws Exception {
753         // standalone = "yes". said XMLDocumentScanner.
754         fStandaloneReader = fEntityHandler.getReaderId() ;
755 
756     }
757 
758 
759 
760     /** Call text declaration. */
761     public void callTextDecl(int version, int encoding) throws Exception {
762         fDocumentHandler.textDecl(version, encoding);
763     }
764 
765     /**
766      * Signal the scanning of an element name in a start element tag.
767      *
768      * @param element Element name scanned.
769      */
770     public void element(QName element) throws Exception {
771         fAttrListHandle = -1;
772     }
773     /**
774      * Signal the scanning of an attribute associated to the previous
775      * start element tag.
776      *
777      * @param element Element name scanned.
778      * @param attrName Attribute name scanned.
779      * @param attrValue The string pool index of the attribute value.
780      */
781     public boolean attribute(QName element, QName attrName, int attrValue) throws Exception {
782         if (fAttrListHandle == -1) {
783             fAttrListHandle = fAttrList.startAttrList();
784         }
785 
786         // if fAttrList.addAttr returns -1, indicates duplicate att in start tag of an element.
787         // specified: true, search : true
788         return fAttrList.addAttr(attrName, attrValue, fCDATASymbol, true, true) == -1;
789     }
790 
791     /** Call start element. */
792     public void callStartElement(QName element) throws Exception {
793 
794         if ( DEBUG_SCHEMA_VALIDATION )
795             System.out.println("\n=======StartElement : " + fStringPool.toString(element.localpart));
796 
797 
798         //
799         // Check after all specified attrs are scanned
800         // (1) report error for REQUIRED attrs that are missing (V_TAGc)
801         // (2) add default attrs (FIXED and NOT_FIXED)
802         //
803 
804         if (!fSeenRootElement) {
805             fSeenRootElement = true;
806             rootElementSpecified(element);
807             fStringPool.resetShuffleCount();
808         }
809 
810         if (fGrammar != null && fGrammarIsDTDGrammar) {
811             fAttrListHandle = addDTDDefaultAttributes(element, fAttrList, fAttrListHandle, fValidating, fStandaloneReader != -1);
812         }
813 
814         fCheckedForSchema = true;
815         if (fNamespacesEnabled) {
816             bindNamespacesToElementAndAttributes(element, fAttrList);
817         }
818 
819         validateElementAndAttributes(element, fAttrList);
820         if (fAttrListHandle != -1) {
821             fAttrList.endAttrList();
822         }
823 
824         fDocumentHandler.startElement(element, fAttrList, fAttrListHandle);
825         fAttrListHandle = -1;
826 
827         //before we increment the element depth, add this element's QName to its enclosing element 's children list
828         fElementDepth++;
829         //if (fElementDepth >= 0) {
830         if (fValidating) {
831             // push current length onto stack
832             if (fElementChildrenOffsetStack.length < fElementDepth) {
833                 int newarray[] = new int[fElementChildrenOffsetStack.length * 2];
834                 System.arraycopy(fElementChildrenOffsetStack, 0, newarray, 0, fElementChildrenOffsetStack.length);
835                 fElementChildrenOffsetStack = newarray;
836             }
837             fElementChildrenOffsetStack[fElementDepth] = fElementChildrenLength;
838 
839             // add this element to children
840             if (fElementChildren.length <= fElementChildrenLength) {
841                 QName[] newarray = new QName[fElementChildrenLength * 2];
842                 System.arraycopy(fElementChildren, 0, newarray, 0, fElementChildren.length);
843                 fElementChildren = newarray;
844             }
845             QName qname = fElementChildren[fElementChildrenLength];
846             if (qname == null) {
847                 for (int i = fElementChildrenLength; i < fElementChildren.length; i++) {
848                     fElementChildren[i] = new QName();
849                 }
850                 qname = fElementChildren[fElementChildrenLength];
851             }
852             qname.setValues(element);
853             fElementChildrenLength++;
854 
855             if (DEBUG_ELEMENT_CHILDREN) {
856                 printChildren();
857                 printStack();
858             }
859         }
860 
861         // One more level of depth
862         //fElementDepth++;
863 
864         ensureStackCapacity(fElementDepth);
865         fCurrentElement.setValues(element);
866         fCurrentElementEntity = fEntityHandler.getReaderId();
867 
868         fElementQNamePartsStack[fElementDepth].setValues(fCurrentElement); 
869 
870         fElementEntityStack[fElementDepth] = fCurrentElementEntity;
871         fElementIndexStack[fElementDepth] = fCurrentElementIndex;
872         fContentSpecTypeStack[fElementDepth] = fCurrentContentSpecType;
873 
874         if (fNeedValidationOff) {
875             fValidating = false;
876             fNeedValidationOff = false;
877         }
878 
879         if (fValidating && fGrammarIsSchemaGrammar) {
880             pushContentLeafStack();
881         }
882 
883         fValidationFlagStack[fElementDepth] = fValidating ? 0 : -1;
884 
885         fScopeStack[fElementDepth] = fCurrentScope;
886         fGrammarNameSpaceIndexStack[fElementDepth] = fGrammarNameSpaceIndex;
887 
888     } // callStartElement(QName)
889 
890     private void pushContentLeafStack() throws Exception {
891         int contentType = getContentSpecType(fCurrentElementIndex);
892         if ( contentType == XMLElementDecl.TYPE_CHILDREN) {
893             XMLContentModel cm = getElementContentModel(fCurrentElementIndex);
894             ContentLeafNameTypeVector cv = cm.getContentLeafNameTypeVector();
895             if (cm != null) {
896                 fContentLeafStack[fElementDepth] = cv;
897             }
898         }
899     }
900 
901     private void ensureStackCapacity ( int newElementDepth) {
902 
903         if (newElementDepth == fElementQNamePartsStack.length ) {
904             int[] newStack = new int[newElementDepth * 2];
905             System.arraycopy(fScopeStack, 0, newStack, 0, newElementDepth);
906             fScopeStack = newStack;
907 
908             newStack = new int[newElementDepth * 2];
909             System.arraycopy(fGrammarNameSpaceIndexStack, 0, newStack, 0, newElementDepth);
910             fGrammarNameSpaceIndexStack = newStack;
911 
912             QName[] newStackOfQueue = new QName[newElementDepth * 2];
913             System.arraycopy(this.fElementQNamePartsStack, 0, newStackOfQueue, 0, newElementDepth );
914             fElementQNamePartsStack      = newStackOfQueue;
915 
916             QName qname = fElementQNamePartsStack[newElementDepth];
917             if (qname == null) {
918                 for (int i = newElementDepth; i < fElementQNamePartsStack.length; i++) {
919                     fElementQNamePartsStack[i] = new QName();
920                 }
921             }
922 
923             newStack = new int[newElementDepth * 2];
924             System.arraycopy(fElementEntityStack, 0, newStack, 0, newElementDepth);
925             fElementEntityStack = newStack;
926 
927             newStack = new int[newElementDepth * 2];
928             System.arraycopy(fElementIndexStack, 0, newStack, 0, newElementDepth);
929             fElementIndexStack = newStack;
930 
931             newStack = new int[newElementDepth * 2];
932             System.arraycopy(fContentSpecTypeStack, 0, newStack, 0, newElementDepth);
933             fContentSpecTypeStack = newStack;
934 
935             newStack = new int[newElementDepth * 2];
936             System.arraycopy(fValidationFlagStack, 0, newStack, 0, newElementDepth);
937             fValidationFlagStack = newStack;
938 
939             ContentLeafNameTypeVector[] newStackV = new ContentLeafNameTypeVector[newElementDepth * 2];
940             System.arraycopy(fContentLeafStack, 0, newStackV, 0, newElementDepth);
941             fContentLeafStack = newStackV;
942         }
943     }
944 
945     /** Call end element. */
946     public void callEndElement(int readerId) throws Exception {
947         if ( DEBUG_SCHEMA_VALIDATION )
948             System.out.println("=======EndElement : " + fStringPool.toString(fCurrentElement.localpart)+"\n");
949 
950         int prefixIndex = fCurrentElement.prefix;
951         int elementType = fCurrentElement.rawname;
952 
953         if (fCurrentElementEntity != readerId) {
954             fErrorReporter.reportError(fErrorReporter.getLocator(),
955                                        XMLMessages.XML_DOMAIN,
956                                        XMLMessages.MSG_ELEMENT_ENTITY_MISMATCH,
957                                        XMLMessages.P78_NOT_WELLFORMED,
958                                        new Object[] { fStringPool.toString(elementType)},
959                                        XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
960         }
961 
962         fElementDepth--;
963         if (fValidating) {
964             int elementIndex = fCurrentElementIndex;
965             if (elementIndex != -1 && fCurrentContentSpecType != -1) {
966                 QName children[] = fElementChildren;
967                 int childrenOffset = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
968                 int childrenLength = fElementChildrenLength - childrenOffset;
969                 if (DEBUG_ELEMENT_CHILDREN) {
970                     System.out.println("endElement("+fStringPool.toString(fCurrentElement.rawname)+')');
971                     System.out.println("fCurrentContentSpecType : " + fCurrentContentSpecType );
972                     System.out.print("offset: ");
973                     System.out.print(childrenOffset);
974                     System.out.print(", length: ");
975                     System.out.print(childrenLength);
976                     System.out.println();
977                     printChildren();
978                     printStack();
979                 }
980                 int result = checkContent(elementIndex, 
981                                           children, childrenOffset, childrenLength);
982 
983                 if ( DEBUG_SCHEMA_VALIDATION )
984                     System.out.println("!!!!!!!!In XMLValidator, the return value from checkContent : " + result);
985 
986                 if (result != -1) {
987                     int majorCode = result != childrenLength ? XMLMessages.MSG_CONTENT_INVALID : XMLMessages.MSG_CONTENT_INCOMPLETE;
988                     fGrammar.getElementDecl(elementIndex, fTempElementDecl);
989                     if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
990                         reportRecoverableXMLError(majorCode,
991                                                   0,
992                                                   fStringPool.toString(elementType),
993                                                   "EMPTY");
994                     } else
995                         reportRecoverableXMLError(majorCode,
996                                                   0,
997                                                   fStringPool.toString(elementType),
998                                                   XMLContentSpec.toString(fGrammar, fStringPool, fTempElementDecl.contentSpecIndex));
999                 }
1000            }
1001            fElementChildrenLength = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
1002        }
1003        fDocumentHandler.endElement(fCurrentElement);
1004        if (fNamespacesEnabled) {
1005            fNamespacesScope.decreaseDepth();
1006        }
1007
1008        // now pop this element off the top of the element stack
1009        //if (fElementDepth-- < 0) {
1010        if (fElementDepth < -1) {
1011            throw new RuntimeException("FWK008 Element stack underflow");
1012        }
1013        if (fElementDepth < 0) {
1014            fCurrentElement.clear();
1015            fCurrentElementEntity = -1;
1016            fCurrentElementIndex = -1;
1017            fCurrentContentSpecType = -1;
1018            fInElementContent = false;
1019            //
1020            // Check after document is fully parsed
1021            // (1) check that there was an element with a matching id for every
1022            //   IDREF and IDREFS attr (V_IDREF0)
1023            //
1024            if (fValidating ) {
1025                try {
1026                    this.fValIDRef.validate( null, this.fValidateIDRef );   
1027                    this.fValIDRefs.validate( null, this.fValidateIDRef );
1028                } catch ( InvalidDatatypeValueException ex ) {
1029                    reportRecoverableXMLError( ex.getMajorCode(), ex.getMinorCode(), 
1030                                               ex.getMessage() ); 
1031
1032
1033                }
1034            }
1035            
1036            try {//Reset datatypes state
1037               this.fValID.validate( null, this.fResetID );
1038               this.fValIDRef.validate(null, this.fResetIDRef );
1039               this.fValIDRefs.validate(null, this.fResetIDRef );
1040            } catch ( InvalidDatatypeValueException ex ) {
1041                System.err.println("Error re-Initializing: ID,IDRef,IDRefs pools" );
1042            }
1043            return;
1044        }
1045
1046
1047        //restore enclosing element to all the "current" variables
1048        // REVISIT: Validation. This information needs to be stored.
1049        fCurrentElement.prefix = -1;
1050
1051
1052        if (fNamespacesEnabled) { //If Namespace enable then localName != rawName
1053            fCurrentElement.localpart = fElementQNamePartsStack[fElementDepth].localpart;
1054        } else {//REVISIT - jeffreyr - This is so we still do old behavior when namespace is off 
1055            fCurrentElement.localpart = fElementQNamePartsStack[fElementDepth].rawname;
1056        }
1057        fCurrentElement.rawname      = fElementQNamePartsStack[fElementDepth].rawname;
1058        fCurrentElement.uri          = fElementQNamePartsStack[fElementDepth].uri;
1059        fCurrentElement.prefix       = fElementQNamePartsStack[fElementDepth].prefix;
1060
1061
1062        fCurrentElementEntity = fElementEntityStack[fElementDepth];
1063        fCurrentElementIndex = fElementIndexStack[fElementDepth];
1064        fCurrentContentSpecType = fContentSpecTypeStack[fElementDepth];
1065
1066        fValidating = fValidationFlagStack[fElementDepth] == 0 ? true : false;
1067
1068        fCurrentScope = fScopeStack[fElementDepth];  
1069
1070        //if ( DEBUG_SCHEMA_VALIDATION ) {
1071
1072/****
1073System.out.println("+++++ currentElement : " + fStringPool.toString(elementType)+
1074                   "\n fCurrentElementIndex : " + fCurrentElementIndex +
1075                   "\n fCurrentScope : " + fCurrentScope +
1076                   "\n fCurrentContentSpecType : " + fCurrentContentSpecType +
1077                   "\n++++++++++++++++++++++++++++++++++++++++++++++++" );
1078/****/
1079        //}
1080
1081        // if enclosing element's Schema is different, need to switch "context"
1082        if ( fGrammarNameSpaceIndex != fGrammarNameSpaceIndexStack[fElementDepth] ) {
1083            fGrammarNameSpaceIndex = fGrammarNameSpaceIndexStack[fElementDepth];
1084            if ( fValidating && fGrammarIsSchemaGrammar )
1085                if ( !switchGrammar(fGrammarNameSpaceIndex) ) {
1086                    reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR, XMLMessages.SCHEMA_GENERIC_ERROR, 
1087                                              "Grammar with uri : " + fStringPool.toString(fGrammarNameSpaceIndex) 
1088                                              + " , can not found");
1089                }
1090        }
1091
1092        if (fValidating) {
1093            fBufferDatatype = false;
1094        }
1095        fInElementContent = (fCurrentContentSpecType == XMLElementDecl.TYPE_CHILDREN);
1096
1097    } // callEndElement(int)
1098
1099    /** Call start CDATA section. */
1100    public void callStartCDATA() throws Exception {
1101        fDocumentHandler.startCDATA();
1102    }
1103
1104    /** Call end CDATA section. */
1105    public void callEndCDATA() throws Exception {
1106        fDocumentHandler.endCDATA();
1107    }
1108
1109    /** Call characters. */
1110    public void callCharacters(int ch) throws Exception {
1111
1112        if (fCharRefData == null) {
1113            fCharRefData = new char[2];
1114        }
1115        int count = (ch < 0x10000) ? 1 : 2;
1116        if (count == 1) {
1117            fCharRefData[0] = (char)ch;
1118        } else {
1119            fCharRefData[0] = (char)(((ch-0x00010000)>>10)+0xd800);
1120            fCharRefData[1] = (char)(((ch-0x00010000)&0x3ff)+0xdc00);
1121        }
1122        if (fValidating && (fInElementContent || fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY)) {
1123            charDataInContent();
1124        }
1125        if (fSendCharDataAsCharArray) {
1126            fDocumentHandler.characters(fCharRefData, 0, count);
1127        } else {
1128            int index = fStringPool.addString(new String(fCharRefData, 0, count));
1129            fDocumentHandler.characters(index);
1130        }
1131
1132    } // callCharacters(int)
1133
1134    /** Call processing instruction. */
1135    public void callProcessingInstruction(int target, int data) throws Exception {
1136        fDocumentHandler.processingInstruction(target, data);
1137    }
1138
1139    /** Call comment. */
1140    public void callComment(int comment) throws Exception {
1141        fDocumentHandler.comment(comment);
1142    }
1143
1144    //
1145    // NamespacesScope.NamespacesHandler methods
1146    //
1147
1148    /** Start a new namespace declaration scope. */
1149    public void startNamespaceDeclScope(int prefix, int uri) throws Exception {
1150        fDocumentHandler.startNamespaceDeclScope(prefix, uri);
1151    }
1152
1153    /** End a namespace declaration scope. */
1154    public void endNamespaceDeclScope(int prefix) throws Exception {
1155        fDocumentHandler.endNamespaceDeclScope(prefix);
1156    }
1157
1158    // attributes
1159
1160
1161    // other
1162
1163    /** Sets the root element. */
1164    public void setRootElementType(QName rootElement) {
1165        fRootElement.setValues(rootElement);
1166    }
1167
1168    /** 
1169     * Returns true if the element declaration is external. 
1170     * <p>
1171     * <strong>Note:</strong> This method is primarilly useful for
1172     * DTDs with internal and external subsets.
1173     */
1174    private boolean getElementDeclIsExternal(int elementIndex) {
1175        /*if (elementIndex < 0 || elementIndex >= fElementCount) {
1176            return false;
1177        }
1178        int chunk = elementIndex >> CHUNK_SHIFT;
1179        int index = elementIndex & CHUNK_MASK;
1180        return (fElementDeclIsExternal[chunk][index] != 0);
1181        */
1182
1183        if (fGrammarIsDTDGrammar ) {
1184            return((DTDGrammar) fGrammar).getElementDeclIsExternal(elementIndex);
1185        }
1186        return false;
1187    }
1188
1189    /** Returns the content spec type for an element index. */
1190    public int getContentSpecType(int elementIndex) {
1191
1192        int contentSpecType = -1;
1193        if ( elementIndex > -1) {
1194            if ( fGrammar.getElementDecl(elementIndex,fTempElementDecl) ) {
1195                contentSpecType = fTempElementDecl.type;
1196            }
1197        }
1198        return contentSpecType;
1199    }
1200
1201    /** Returns the content spec handle for an element index. */
1202    public int getContentSpecHandle(int elementIndex) {
1203        int contentSpecHandle = -1;
1204        if ( elementIndex > -1) {
1205            if ( fGrammar.getElementDecl(elementIndex,fTempElementDecl) ) {
1206                contentSpecHandle = fTempElementDecl.contentSpecIndex;
1207            }
1208        }
1209        return contentSpecHandle;
1210    }
1211
1212    //
1213    // Protected methods
1214    //
1215
1216    // error reporting
1217
1218    /** Report a recoverable xml error. */
1219    protected void reportRecoverableXMLError(int majorCode, int minorCode) 
1220    throws Exception {
1221
1222        fErrorReporter.reportError(fErrorReporter.getLocator(),
1223                                   XMLMessages.XML_DOMAIN,
1224                                   majorCode,
1225                                   minorCode,
1226                                   null,
1227                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1228
1229    } // reportRecoverableXMLError(int,int)
1230
1231    /** Report a recoverable xml error. */
1232    protected void reportRecoverableXMLError(int majorCode, int minorCode, 
1233                                             int stringIndex1) 
1234    throws Exception {
1235
1236        Object[] args = { fStringPool.toString(stringIndex1)};
1237        fErrorReporter.reportError(fErrorReporter.getLocator(),
1238                                   XMLMessages.XML_DOMAIN,
1239                                   majorCode,
1240                                   minorCode,
1241                                   args,
1242                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1243
1244    } // reportRecoverableXMLError(int,int,int)
1245
1246    /** Report a recoverable xml error. */
1247    protected void reportRecoverableXMLError(int majorCode, int minorCode, 
1248                                             String string1) throws Exception {
1249
1250        Object[] args = { string1};
1251        fErrorReporter.reportError(fErrorReporter.getLocator(),
1252                                   XMLMessages.XML_DOMAIN,
1253                                   majorCode,
1254                                   minorCode,
1255                                   args,
1256                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1257
1258    } // reportRecoverableXMLError(int,int,String)
1259
1260    /** Report a recoverable xml error. */
1261    protected void reportRecoverableXMLError(int majorCode, int minorCode, 
1262                                             int stringIndex1, int stringIndex2) 
1263    throws Exception {
1264
1265        Object[] args = { fStringPool.toString(stringIndex1), fStringPool.toString(stringIndex2)};
1266        fErrorReporter.reportError(fErrorReporter.getLocator(),
1267                                   XMLMessages.XML_DOMAIN,
1268                                   majorCode,
1269                                   minorCode,
1270                                   args,
1271                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1272
1273    } // reportRecoverableXMLError(int,int,int,int)
1274
1275    /** Report a recoverable xml error. */
1276    protected void reportRecoverableXMLError(int majorCode, int minorCode, 
1277                                             String string1, String string2) 
1278    throws Exception {
1279
1280        Object[] args = { string1, string2};
1281        fErrorReporter.reportError(fErrorReporter.getLocator(),
1282                                   XMLMessages.XML_DOMAIN,
1283                                   majorCode,
1284                                   minorCode,
1285                                   args,
1286                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1287
1288    } // reportRecoverableXMLError(int,int,String,String)
1289
1290    /** Report a recoverable xml error. */
1291    protected void reportRecoverableXMLError(int majorCode, int minorCode, 
1292                                             String string1, String string2, 
1293                                             String string3) throws Exception {
1294
1295        Object[] args = { string1, string2, string3};
1296        fErrorReporter.reportError(fErrorReporter.getLocator(),
1297                                   XMLMessages.XML_DOMAIN,
1298                                   majorCode,
1299                                   minorCode,
1300                                   args,
1301                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1302
1303    } // reportRecoverableXMLError(int,int,String,String,String)
1304
1305    // content spec
1306
1307    /**
1308     * Returns information about which elements can be placed at a particular point
1309     * in the passed element's content model.
1310     * <p>
1311     * Note that the incoming content model to test must be valid at least up to
1312     * the insertion point. If not, then -1 will be returned and the info object
1313     * will not have been filled in.
1314     * <p>
1315     * If, on return, the info.isValidEOC flag is set, then the 'insert after'
1316     * elemement is a valid end of content, i.e. nothing needs to be inserted
1317     * after it to make the parent element's content model valid.
1318     *
1319     * @param elementIndex The index within the <code>ElementDeclPool</code> of the
1320     *                     element which is being querying.
1321     * @param fullyValid Only return elements that can be inserted and still
1322     *                   maintain the validity of subsequent elements past the
1323     *                   insertion point (if any).  If the insertion point is at
1324     *                   the end, and this is true, then only elements that can
1325     *                   be legal final states will be returned.
1326     * @param info An object that contains the required input data for the method,
1327     *             and which will contain the output information if successful.
1328     *
1329     * @return The value -1 if fully valid, else the 0 based index of the child
1330     *         that first failed before the insertion point. If the value
1331     *         returned is equal to the number of children, then the specified
1332     *         children are valid but additional content is required to reach a
1333     *         valid ending state.
1334     *
1335     * @exception Exception Thrown on error.
1336     *
1337     * @see InsertableElementsInfo
1338     */
1339    protected int whatCanGoHere(int elementIndex, boolean fullyValid,
1340                                InsertableElementsInfo info) throws Exception {
1341
1342        //
1343        //  Do some basic sanity checking on the info packet. First, make sure
1344        //  that insertAt is not greater than the child count. It can be equal,
1345        //  which means to get appendable elements, but not greater. Or, if
1346        //  the current children array is null, that's bad too.
1347        //
1348        //  Since the current children array must have a blank spot for where
1349        //  the insert is going to be, the child count must always be at least
1350        //  one.
1351        //
1352        //  Make sure that the child count is not larger than the current children
1353        //  array. It can be equal, which means get appendable elements, but not
1354        //  greater.
1355        //
1356        if (info.insertAt > info.childCount || info.curChildren == null ||  
1357            info.childCount < 1 || info.childCount > info.curChildren.length) {
1358            fErrorReporter.reportError(fErrorReporter.getLocator(),
1359                                       ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
1360                                       ImplementationMessages.VAL_WCGHI,
1361                                       0,
1362                                       null,
1363                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
1364        }
1365
1366        int retVal = 0;
1367        try {
1368            // Get the content model for this element
1369            final XMLContentModel cmElem = getElementContentModel(elementIndex);
1370
1371            // And delegate this call to it
1372            retVal = cmElem.whatCanGoHere(fullyValid, info);
1373        } catch (CMException excToCatch) {
1374            // REVISIT - Translate caught error to the protected error handler interface
1375            int majorCode = excToCatch.getErrorCode();
1376            fErrorReporter.reportError(fErrorReporter.getLocator(),
1377                                       ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
1378                                       majorCode,
1379                                       0,
1380                                       null,
1381                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
1382            throw excToCatch;
1383        }
1384        return retVal;
1385
1386    } // whatCanGoHere(int,boolean,InsertableElementsInfo):int
1387
1388    // attribute information
1389
1390    /** Protected for use by AttributeValidator classes. */
1391    protected boolean getAttDefIsExternal(QName element, QName attribute) {
1392        int attDefIndex = getAttDef(element, attribute);
1393        if (fGrammarIsDTDGrammar ) {
1394            return((DTDGrammar) fGrammar).getAttributeDeclIsExternal(attDefIndex);
1395        }
1396        return false;
1397    }
1398
1399
1400
1401    //
1402    // Private methods
1403    //
1404
1405    // other
1406
1407    /** Returns true if using a standalone reader. */
1408    private boolean usingStandaloneReader() {
1409        return fStandaloneReader == -1 || fEntityHandler.getReaderId() == fStandaloneReader;
1410    }
1411
1412    /** Returns a locator implementation. */
1413    private LocatorImpl getLocatorImpl(LocatorImpl fillin) {
1414
1415        Locator here = fErrorReporter.getLocator();
1416        if (fillin == null)
1417            return new LocatorImpl(here);
1418        fillin.setPublicId(here.getPublicId());
1419        fillin.setSystemId(here.getSystemId());
1420        fillin.setLineNumber(here.getLineNumber());
1421        fillin.setColumnNumber(here.getColumnNumber());
1422        return fillin;
1423
1424    } // getLocatorImpl(LocatorImpl):LocatorImpl
1425
1426
1427    // initialization
1428
1429    /** Reset pool. */
1430    private void poolReset() {
1431        try {
1432            //System.out.println("We reset" );
1433            this.fValID.validate( null, this.fResetID );
1434            this.fValIDRef.validate(null, this.fResetIDRef );
1435            this.fValIDRefs.validate(null, this.fResetIDRef );
1436        } catch ( InvalidDatatypeValueException ex ) {
1437            System.err.println("Error re-Initializing: ID,IDRef,IDRefs pools" );
1438        }
1439    } // poolReset()
1440
1441    /** Reset common. */
1442    private void resetCommon(StringPool stringPool) throws Exception {
1443
1444        fStringPool = stringPool;
1445        fValidating = fValidationEnabled;
1446        fValidationEnabledByDynamic = false;
1447        fDynamicDisabledByValidation = false;
1448        poolReset();
1449        fCalledStartDocument = false;
1450        fStandaloneReader = -1;
1451        fElementChildrenLength = 0;
1452        fElementDepth = -1;
1453        fSeenRootElement = false;
1454        fSeenDoctypeDecl = false;
1455        fNamespacesScope = null;
1456        fNamespacesPrefix = -1;
1457        fRootElement.clear();
1458        fAttrListHandle = -1;
1459        fCheckedForSchema = false;
1460
1461        fCurrentScope = TOP_LEVEL_SCOPE;
1462        fCurrentSchemaURI = -1;
1463        fEmptyURI = - 1; 
1464        fXsiPrefix = - 1;
1465        fXsiTypeValidator = null;
1466
1467        fGrammar = null;
1468        fGrammarNameSpaceIndex = -1;
1469        //fGrammarResolver = null;
1470        if (fGrammarResolver != null) {
1471            fGrammarResolver.clearGrammarResolver();
1472        }
1473        fGrammarIsDTDGrammar = false;
1474        fGrammarIsSchemaGrammar = false;
1475
1476
1477        init();
1478
1479    } // resetCommon(StringPool)
1480
1481    /** Initialize. */
1482    private void init() {
1483
1484        fEmptyURI = fStringPool.addSymbol("");
1485        fXsiURI = fStringPool.addSymbol(SchemaSymbols.URI_XSI);
1486
1487
1488        fEMPTYSymbol = fStringPool.addSymbol("EMPTY");
1489        fANYSymbol = fStringPool.addSymbol("ANY");
1490        fMIXEDSymbol = fStringPool.addSymbol("MIXED");
1491        fCHILDRENSymbol = fStringPool.addSymbol("CHILDREN");
1492
1493        fCDATASymbol = fStringPool.addSymbol("CDATA");
1494        fIDSymbol = fStringPool.addSymbol("ID");
1495        fIDREFSymbol = fStringPool.addSymbol("IDREF");
1496        fIDREFSSymbol = fStringPool.addSymbol("IDREFS");
1497        fENTITYSymbol = fStringPool.addSymbol("ENTITY");
1498        fENTITIESSymbol = fStringPool.addSymbol("ENTITIES");
1499        fNMTOKENSymbol = fStringPool.addSymbol("NMTOKEN");
1500        fNMTOKENSSymbol = fStringPool.addSymbol("NMTOKENS");
1501        fNOTATIONSymbol = fStringPool.addSymbol("NOTATION");
1502        fENUMERATIONSymbol = fStringPool.addSymbol("ENUMERATION");
1503        fREQUIREDSymbol = fStringPool.addSymbol("#REQUIRED");
1504        fFIXEDSymbol = fStringPool.addSymbol("#FIXED");
1505        fDATATYPESymbol = fStringPool.addSymbol("<<datatype>>");
1506        fEpsilonIndex = fStringPool.addSymbol("<<CMNODE_EPSILON>>");
1507        fXMLLang = fStringPool.addSymbol("xml:lang");
1508
1509        try {//Initialize ENTITIES and ENTITY Validators
1510            Object[] packageArgsEntityVal = { (Object) this.fEntityHandler,
1511                (Object) this.fStringPool};
1512            fValidateENTITYMsg.setDatatypeObject( (Object ) packageArgsEntityVal);
1513            fValENTITIES.validate( null, fValidateENTITYMsg );
1514            fValENTITY.validate( null, fValidateENTITYMsg );
1515        } catch ( InvalidDatatypeValueException ex ) {
1516            System.err.println("Error: " + ex.getLocalizedMessage() );//Should not happen
1517        }
1518
1519
1520    } // init()
1521
1522    // other
1523
1524    // default attribute
1525
1526    /** addDefaultAttributes. */
1527    private int addDefaultAttributes(int elementIndex, XMLAttrList attrList, int attrIndex, boolean validationEnabled, boolean standalone) throws Exception {
1528
1529        //System.out.println("XMLValidator#addDefaultAttributes");
1530        //System.out.print("  ");
1531        //fGrammar.printAttributes(elementIndex);
1532
1533        //
1534        // Check after all specified attrs are scanned
1535        // (1) report error for REQUIRED attrs that are missing (V_TAGc)
1536        // (2) check that FIXED attrs have matching value (V_TAGd)
1537        // (3) add default attrs (FIXED and NOT_FIXED)
1538        //
1539        fGrammar.getElementDecl(elementIndex,fTempElementDecl);
1540
1541        int elementNameIndex = fTempElementDecl.name.localpart;
1542        int attlistIndex = fGrammar.getFirstAttributeDeclIndex(elementIndex);
1543        int firstCheck = attrIndex;
1544        int lastCheck = -1;
1545        while (attlistIndex != -1) {
1546            //int adChunk = attlistIndex >> CHUNK_SHIFT;
1547            //int adIndex = attlistIndex & CHUNK_MASK;
1548            fGrammar.getAttributeDecl(attlistIndex, fTempAttDecl);
1549
1550            // TO DO: For ericye Debug only
1551            /***
1552            if (fTempAttDecl != null) {
1553                XMLElementDecl element = new XMLElementDecl();
1554                fGrammar.getElementDecl(elementIndex, element);
1555                System.out.println("element: "+fStringPool.toString(element.name.localpart));
1556                System.out.println("attlistIndex " + attlistIndex + "\n"+
1557                    "attName : '"+fStringPool.toString(fTempAttDecl.name.localpart) + "'\n"
1558                                   + "attType : "+fTempAttDecl.type + "\n"
1559                                   + "attDefaultType : "+fTempAttDecl.defaultType + "\n"
1560                                   + "attDefaultValue : '"+fTempAttDecl.defaultValue + "'\n"
1561                                   + attrList.getLength() +"\n"
1562                                   );
1563            }
1564            /***/
1565
1566            int attPrefix = fTempAttDecl.name.prefix;
1567            int attName = fTempAttDecl.name.localpart;
1568            int attType = attributeTypeName(fTempAttDecl);
1569            int attDefType =fTempAttDecl.defaultType;
1570            int attValue = -1 ;
1571            if (fTempAttDecl.defaultValue != null ) {
1572                attValue = fStringPool.addSymbol(fTempAttDecl.defaultValue);
1573            }
1574
1575            boolean specified = false;
1576            boolean required = attDefType == XMLAttributeDecl.DEFAULT_TYPE_REQUIRED;
1577
1578            if (firstCheck != -1) {
1579                boolean cdata = attType == fCDATASymbol;
1580                if (!cdata || required || attValue != -1) {
1581                    int i = attrList.getFirstAttr(firstCheck);
1582                    while (i != -1 && (lastCheck == -1 || i <= lastCheck)) {
1583
1584                        if ( (fGrammarIsDTDGrammar && (attrList.getAttrName(i) == fTempAttDecl.name.rawname)) ||
1585                             (  fStringPool.equalNames(attrList.getAttrLocalpart(i), attName)
1586                                && fStringPool.equalNames(attrList.getAttrURI(i), fTempAttDecl.name.uri) ) ) {
1587
1588                            if (validationEnabled && attDefType == XMLAttributeDecl.DEFAULT_TYPE_FIXED) {
1589                                int alistValue = attrList.getAttValue(i);
1590                                if (alistValue != attValue &&
1591                                    !fStringPool.toString(alistValue).equals(fStringPool.toString(attValue))) {
1592                                    Object[] args = { fStringPool.toString(elementNameIndex),
1593                                        fStringPool.toString(attName),
1594                                        fStringPool.toString(alistValue),
1595                                        fStringPool.toString(attValue)};
1596                                    fErrorReporter.reportError(fErrorReporter.getLocator(),
1597                                                               XMLMessages.XML_DOMAIN,
1598                                                               XMLMessages.MSG_FIXED_ATTVALUE_INVALID,
1599                                                               XMLMessages.VC_FIXED_ATTRIBUTE_DEFAULT,
1600                                                               args,
1601                                                               XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1602                                }
1603                            }
1604                            specified = true;
1605                            break;
1606                        }
1607                        i = attrList.getNextAttr(i);
1608                    }
1609                }
1610            }
1611
1612            if (!specified) {
1613                if (required) {
1614                    if (validationEnabled) {
1615                        Object[] args = { fStringPool.toString(elementNameIndex),
1616                            fStringPool.toString(attName)};
1617                        fErrorReporter.reportError(fErrorReporter.getLocator(),
1618                                                   XMLMessages.XML_DOMAIN,
1619                                                   XMLMessages.MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED,
1620                                                   XMLMessages.VC_REQUIRED_ATTRIBUTE,
1621                                                   args,
1622                                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1623                    }
1624                } else if (attValue != -1) {
1625                    if (validationEnabled && standalone )
1626                        if ( fGrammarIsDTDGrammar 
1627                             && ((DTDGrammar) fGrammar).getAttributeDeclIsExternal(attlistIndex) ) {
1628
1629                            Object[] args = { fStringPool.toString(elementNameIndex),
1630                                fStringPool.toString(attName)};
1631                            fErrorReporter.reportError(fErrorReporter.getLocator(),
1632                                                       XMLMessages.XML_DOMAIN,
1633                                                       XMLMessages.MSG_DEFAULTED_ATTRIBUTE_NOT_SPECIFIED,
1634                                                       XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
1635                                                       args,
1636                                                       XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1637                        }
1638                    if (attType == fIDREFSymbol) {
1639                        this.fValIDRef.validate( fStringPool.toString(attValue), this.fStoreIDRef );
1640                    } else if (attType == fIDREFSSymbol) {
1641                        this.fValIDRefs.validate( fStringPool.toString(attValue), this.fStoreIDRef );
1642                    }
1643                    if (attrIndex == -1) {
1644                        attrIndex = attrList.startAttrList();
1645                    }
1646                    // REVISIT: Validation. What should the prefix be?
1647                    fTempQName.setValues(attPrefix, attName, attName, fTempAttDecl.name.uri);
1648                    int newAttr = attrList.addAttr(fTempQName, 
1649                                                   attValue, attType, 
1650                                                   false, false);
1651                    if (lastCheck == -1) {
1652                        lastCheck = newAttr;
1653                    }
1654                }
1655            }
1656            attlistIndex = fGrammar.getNextAttributeDeclIndex(attlistIndex);
1657        }
1658        return attrIndex;
1659
1660    } // addDefaultAttributes(int,XMLAttrList,int,boolean,boolean):int
1661
1662    /** addDTDDefaultAttributes. */
1663    private int addDTDDefaultAttributes(QName element, XMLAttrList attrList, int attrIndex, boolean validationEnabled, boolean standalone) throws Exception {
1664
1665
1666        //
1667        // Check after all specified attrs are scanned
1668        // (1) report error for REQUIRED attrs that are missing (V_TAGc)
1669        // (2) check that FIXED attrs have matching value (V_TAGd)
1670        // (3) add default attrs (FIXED and NOT_FIXED)
1671        //
1672
1673        int elementIndex = fGrammar.getElementDeclIndex(element, -1);
1674
1675        if (elementIndex == -1) {
1676            return attrIndex;
1677        }
1678
1679        fGrammar.getElementDecl(elementIndex,fTempElementDecl);
1680
1681
1682        int elementNameIndex = fTempElementDecl.name.rawname;
1683        int attlistIndex = fGrammar.getFirstAttributeDeclIndex(elementIndex);
1684        int firstCheck = attrIndex;
1685        int lastCheck = -1;
1686        while (attlistIndex != -1) {
1687
1688            fGrammar.getAttributeDecl(attlistIndex, fTempAttDecl);
1689
1690            // TO DO: For ericye Debug only
1691            /***
1692            if (fTempAttDecl != null) {
1693                XMLElementDecl element = new XMLElementDecl();
1694                fGrammar.getElementDecl(elementIndex, element);
1695                System.out.println("element: "+fStringPool.toString(element.name.localpart));
1696                System.out.println("attlistIndex " + attlistIndex + "\n"+
1697                    "attName : '"+fStringPool.toString(fTempAttDecl.name.localpart) + "'\n"
1698                                   + "attType : "+fTempAttDecl.type + "\n"
1699                                   + "attDefaultType : "+fTempAttDecl.defaultType + "\n"
1700                                   + "attDefaultValue : '"+fTempAttDecl.defaultValue + "'\n"
1701                                   + attrList.getLength() +"\n"
1702                                   );
1703            }
1704            /***/
1705
1706            int attPrefix = fTempAttDecl.name.prefix;
1707            int attName = fTempAttDecl.name.rawname;
1708            int attLocalpart = fTempAttDecl.name.localpart;
1709            int attType = attributeTypeName(fTempAttDecl);
1710            int attDefType =fTempAttDecl.defaultType;
1711            int attValue = -1 ;
1712            if (fTempAttDecl.defaultValue != null ) {
1713                attValue = fStringPool.addSymbol(fTempAttDecl.defaultValue);
1714            }
1715            boolean specified = false;
1716            boolean required = attDefType == XMLAttributeDecl.DEFAULT_TYPE_REQUIRED;
1717
1718
1719            /****
1720            if (fValidating && fGrammar != null && fGrammarIsDTDGrammar && attValue != -1) {
1721                normalizeAttValue(null, fTempAttDecl.name,
1722                                  attValue,attType,fTempAttDecl.list, 
1723                                  fTempAttDecl.enumeration);
1724            }
1725            /****/
1726
1727            if (firstCheck != -1) {
1728                boolean cdata = attType == fCDATASymbol;
1729                if (!cdata || required || attValue != -1) {
1730                    int i = attrList.getFirstAttr(firstCheck);
1731                    while (i != -1 && (lastCheck == -1 || i <= lastCheck)) {
1732
1733                        if ( attrList.getAttrName(i) == fTempAttDecl.name.rawname ) {
1734
1735                            if (validationEnabled && attDefType == XMLAttributeDecl.DEFAULT_TYPE_FIXED) {
1736                                int alistValue = attrList.getAttValue(i);
1737                                if (alistValue != attValue &&
1738                                    !fStringPool.toString(alistValue).equals(fStringPool.toString(attValue))) {
1739                                    Object[] args = { fStringPool.toString(elementNameIndex),
1740                                        fStringPool.toString(attName),
1741                                        fStringPool.toString(alistValue),
1742                                        fStringPool.toString(attValue)};
1743                                    fErrorReporter.reportError(fErrorReporter.getLocator(),
1744                                                               XMLMessages.XML_DOMAIN,
1745                                                               XMLMessages.MSG_FIXED_ATTVALUE_INVALID,
1746                                                               XMLMessages.VC_FIXED_ATTRIBUTE_DEFAULT,
1747                                                               args,
1748                                                               XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1749                                }
1750                            }
1751                            specified = true;
1752                            break;
1753                        }
1754                        i = attrList.getNextAttr(i);
1755                    }
1756                }
1757            }
1758
1759            if (!specified) {
1760                if (required) {
1761                    if (validationEnabled) {
1762                        Object[] args = { fStringPool.toString(elementNameIndex),
1763                            fStringPool.toString(attName)};
1764                        fErrorReporter.reportError(fErrorReporter.getLocator(),
1765                                                   XMLMessages.XML_DOMAIN,
1766                                                   XMLMessages.MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED,
1767                                                   XMLMessages.VC_REQUIRED_ATTRIBUTE,
1768                                                   args,
1769                                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1770                    }
1771                } else if (attValue != -1) {
1772                    if (validationEnabled && standalone )
1773                        if ( fGrammarIsDTDGrammar 
1774                             && ((DTDGrammar) fGrammar).getAttributeDeclIsExternal(attlistIndex) ) {
1775
1776                            Object[] args = { fStringPool.toString(elementNameIndex),
1777                                fStringPool.toString(attName)};
1778                            fErrorReporter.reportError(fErrorReporter.getLocator(),
1779                                                       XMLMessages.XML_DOMAIN,
1780                                                       XMLMessages.MSG_DEFAULTED_ATTRIBUTE_NOT_SPECIFIED,
1781                                                       XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
1782                                                       args,
1783                                                       XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1784                        }
1785                    if (attType == fIDREFSymbol) {
1786                        this.fValIDRef.validate( fStringPool.toString(attValue), this.fStoreIDRef );
1787                    } else if (attType == fIDREFSSymbol) {
1788                        this.fValIDRefs.validate( fStringPool.toString(attValue), this.fStoreIDRef );
1789                    }
1790                    if (attrIndex == -1) {
1791                        attrIndex = attrList.startAttrList();
1792                    }
1793
1794                    fTempQName.setValues(attPrefix, attLocalpart, attName, fTempAttDecl.name.uri);
1795                    int newAttr = attrList.addAttr(fTempQName, 
1796                                                   attValue, attType, 
1797                                                   false, false);
1798                    if (lastCheck == -1) {
1799                        lastCheck = newAttr;
1800                    }
1801                }
1802            }
1803            attlistIndex = fGrammar.getNextAttributeDeclIndex(attlistIndex);
1804        }
1805        return attrIndex;
1806
1807    } // addDTDDefaultAttributes(int,XMLAttrList,int,boolean,boolean):int
1808
1809    // content models
1810
1811    /** Queries the content model for the specified element index. */
1812    private XMLContentModel getElementContentModel(int elementIndex) throws CMException {
1813        XMLContentModel contentModel = null;
1814        if ( elementIndex > -1) {
1815            if ( fGrammar.getElementDecl(elementIndex,fTempElementDecl) ) {
1816                contentModel = fGrammar.getElementContentModel(elementIndex);
1817            }
1818        }
1819        //return fGrammar.getElementContentModel(elementIndex);
1820        return contentModel;
1821    }
1822
1823
1824
1825    // query attribute information
1826
1827    /** Returns an attribute definition for an element type. */
1828    // this is only used by DTD validation.
1829    private int getAttDef(QName element, QName attribute) {
1830        if (fGrammar != null) {
1831            int scope = fCurrentScope;
1832            if (element.uri > -1) {
1833                scope = TOP_LEVEL_SCOPE;
1834            }
1835            int elementIndex = fGrammar.getElementDeclIndex(element,scope);
1836            if (elementIndex == -1) {
1837                return -1;
1838            }
1839            int attDefIndex = fGrammar.getFirstAttributeDeclIndex(elementIndex);
1840            while (attDefIndex != -1) {
1841                fGrammar.getAttributeDecl(attDefIndex, fTempAttributeDecl);
1842                if (fTempAttributeDecl.name.localpart == attribute.localpart &&
1843                    fTempAttributeDecl.name.uri == attribute.uri ) {
1844                    return attDefIndex;
1845                }
1846                attDefIndex = fGrammar.getNextAttributeDeclIndex(attDefIndex);
1847            }
1848        }
1849        return -1;
1850
1851    } // getAttDef(QName,QName)
1852
1853    /** Returns an attribute definition for an element type. */
1854    private int getAttDefByElementIndex(int elementIndex, QName attribute) {
1855        if (fGrammar != null && elementIndex > -1) {
1856            if (elementIndex == -1) {
1857                return -1;
1858            }
1859            int attDefIndex = fGrammar.getFirstAttributeDeclIndex(elementIndex);
1860            while (attDefIndex != -1) {
1861                fGrammar.getAttributeDecl(attDefIndex, fTempAttDecl);
1862
1863                if (fGrammarIsDTDGrammar) {
1864                    if (fTempAttDecl.name.rawname == attribute.rawname )
1865                        return attDefIndex;
1866                } else
1867                    if (fTempAttDecl.name.localpart == attribute.localpart &&
1868                        fTempAttDecl.name.uri == attribute.uri ) {
1869                    return attDefIndex;
1870                }
1871
1872                if (fGrammarIsSchemaGrammar) {
1873                    if (fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_ANY) {
1874                        return attDefIndex;
1875                    } else if (fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_LOCAL) {
1876                        if (attribute.uri == -1) {
1877                            return attDefIndex;
1878                        }
1879                    } else if (fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_OTHER) {
1880                        if (attribute.uri != fTempAttDecl.name.uri) {
1881                            return attDefIndex;
1882                        }
1883                    } else if (fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_LIST) {
1884                        if (fStringPool.stringInList(fTempAttDecl.enumeration, attribute.uri)) {
1885                            return attDefIndex;
1886                        }
1887                    }
1888                }
1889
1890                attDefIndex = fGrammar.getNextAttributeDeclIndex(attDefIndex);
1891            }
1892        }
1893        return -1;
1894
1895    } // getAttDef(QName,QName)
1896
1897    // validation
1898
1899    /** Root element specified. */
1900    private void rootElementSpecified(QName rootElement) throws Exception {
1901
1902        // this is what it used to be
1903        //if  (fDynamicValidation && !fSeenDoctypeDecl) {
1904        //fValidating = false;
1905        //}
1906
1907
1908        if ( fLoadDTDGrammar )
1909            // initialize the grammar to be the default one, 
1910            // it definitely should be a DTD Grammar at this case;
1911            if (fGrammar == null) {
1912
1913                fGrammar = fGrammarResolver.getGrammar("");
1914
1915                //TO DO, for ericye debug only
1916                if (fGrammar == null && DEBUG_SCHEMA_VALIDATION) {
1917                    System.out.println("Oops! no grammar is found for validation");
1918                }
1919
1920                if (fDynamicValidation && fGrammar==null) {
1921                    fValidating = false;
1922                }
1923
1924                if (fGrammar != null) {
1925                    if (fGrammar instanceof DTDGrammar) {
1926                        fGrammarIsDTDGrammar = true;
1927                        fGrammarIsSchemaGrammar = false;
1928                    } else if ( fGrammar instanceof SchemaGrammar ) {
1929                        fGrammarIsSchemaGrammar = true;
1930                        fGrammarIsDTDGrammar = false;
1931                    }
1932
1933                    fGrammarNameSpaceIndex = fEmptyURI;
1934                }
1935            }
1936
1937        if (fValidating) {
1938            if ( fGrammarIsDTDGrammar && 
1939                 ((DTDGrammar) fGrammar).getRootElementQName(fRootElement) ) {
1940
1941                String root1 = fStringPool.toString(fRootElement.rawname);
1942                String root2 = fStringPool.toString(rootElement.rawname);
1943                if (!root1.equals(root2)) {
1944                    reportRecoverableXMLError(XMLMessages.MSG_ROOT_ELEMENT_TYPE,
1945                                              XMLMessages.VC_ROOT_ELEMENT_TYPE,
1946                                              fRootElement.rawname, 
1947                                              rootElement.rawname);
1948                }
1949            }
1950        }
1951
1952        if (fNamespacesEnabled) {
1953            if (fNamespacesScope == null) {
1954                fNamespacesScope = new NamespacesScope(this);
1955                fNamespacesPrefix = fStringPool.addSymbol("xmlns");
1956                fNamespacesScope.setNamespaceForPrefix(fNamespacesPrefix, -1);
1957                int xmlSymbol = fStringPool.addSymbol("xml");
1958                int xmlNamespace = fStringPool.addSymbol("http://www.w3.org/XML/1998/namespace");
1959                fNamespacesScope.setNamespaceForPrefix(xmlSymbol, xmlNamespace);
1960            }
1961        }
1962
1963    } // rootElementSpecified(QName)
1964
1965    /** Switchs to correct validating symbol tables when Schema changes.*/
1966
1967    private boolean switchGrammar(int newGrammarNameSpaceIndex) throws Exception {
1968        Grammar tempGrammar = fGrammarResolver.getGrammar(fStringPool.toString(newGrammarNameSpaceIndex));
1969        if (tempGrammar == null) {
1970            // This is a case where namespaces is on with a DTD grammar.
1971            tempGrammar = fGrammarResolver.getGrammar("");
1972        }
1973        if (tempGrammar == null) {
1974            return false;
1975        } else {
1976            fGrammar = tempGrammar;
1977            if (fGrammar instanceof DTDGrammar) {
1978                fGrammarIsDTDGrammar = true;
1979                fGrammarIsSchemaGrammar = false;
1980            } else if ( fGrammar instanceof SchemaGrammar ) {
1981                fGrammarIsSchemaGrammar = true;
1982                fGrammarIsDTDGrammar = false;
1983            }
1984
1985            return true;
1986        }
1987    }
1988
1989    /** Binds namespaces to the element and attributes. */
1990    private void bindNamespacesToElementAndAttributes(QName element, 
1991                                                      XMLAttrList attrList)
1992    throws Exception {
1993
1994        fNamespacesScope.increaseDepth();
1995
1996        //Vector schemaCandidateURIs = null;
1997        Hashtable locationUriPairs = null;
1998
1999        if (fAttrListHandle != -1) {
2000            int index = attrList.getFirstAttr(fAttrListHandle);
2001            while (index != -1) {
2002                int attName = attrList.getAttrName(index);
2003                int attPrefix = attrList.getAttrPrefix(index);
2004                if (fStringPool.equalNames(attName, fXMLLang)) {
2005                    /***
2006                    // NOTE: This check is done in the validateElementsAndAttributes
2007                    //       method.
2008                    fDocumentScanner.checkXMLLangAttributeValue(attrList.getAttValue(index));
2009                    /***/
2010                } else if (fStringPool.equalNames(attName, fNamespacesPrefix)) {
2011                    int uri = fStringPool.addSymbol(attrList.getAttValue(index));
2012                    fNamespacesScope.setNamespaceForPrefix(StringPool.EMPTY_STRING, uri);
2013                } else {
2014                    if (attPrefix == fNamespacesPrefix) {
2015                        int nsPrefix = attrList.getAttrLocalpart(index);
2016                        int uri = fStringPool.addSymbol(attrList.getAttValue(index));
2017                        fNamespacesScope.setNamespaceForPrefix(nsPrefix, uri);
2018
2019                        if (fValidating && fSchemaValidation) {
2020                            boolean seeXsi = false;
2021                            String attrValue = fStringPool.toString(attrList.getAttValue(index));
2022
2023                            if (attrValue.equals(SchemaSymbols.URI_XSI)) {
2024                                fXsiPrefix = nsPrefix;
2025                                seeXsi = true;
2026                            }
2027
2028                            if (!seeXsi) {
2029                                /***
2030                                if (schemaCandidateURIs == null) {
2031                                    schemaCandidateURIs = new Vector();
2032                                }
2033                                schemaCandidateURIs.addElement( fStringPool.toString(uri) );
2034                                /***/
2035                            }
2036                        }
2037                    }
2038                }
2039                index = attrList.getNextAttr(index);
2040            }
2041            // if validating, walk through the list again to deal with "xsi:...."
2042            if (fValidating && fSchemaValidation) {
2043                fXsiTypeAttValue = -1;
2044                index = attrList.getFirstAttr(fAttrListHandle);
2045                while (index != -1) {
2046
2047                    int attName = attrList.getAttrName(index);
2048                    int attPrefix = attrList.getAttrPrefix(index);
2049
2050                    if (fStringPool.equalNames(attName, fNamespacesPrefix)) {
2051                        // REVISIT
2052                    } else {
2053                        if ( DEBUG_SCHEMA_VALIDATION ) {
2054                            System.out.println("deal with XSI");
2055                            System.out.println("before find XSI: "+fStringPool.toString(attPrefix)
2056                                               +","+fStringPool.toString(fXsiPrefix) );
2057                        }
2058                        if ( fXsiPrefix != -1 && attPrefix == fXsiPrefix ) {
2059
2060                            if (DEBUG_SCHEMA_VALIDATION) {
2061                                System.out.println("find XSI: "+fStringPool.toString(attPrefix)
2062                                                   +","+fStringPool.toString(attName) );
2063                            }
2064
2065
2066                            int localpart = attrList.getAttrLocalpart(index);
2067                            if (localpart == fStringPool.addSymbol(SchemaSymbols.XSI_SCHEMALOCACTION)) {
2068                                if (locationUriPairs == null) {
2069                                    locationUriPairs = new Hashtable();
2070                                }
2071                                parseSchemaLocation(fStringPool.toString(attrList.getAttValue(index)), locationUriPairs);
2072                            } else if (localpart == fStringPool.addSymbol(SchemaSymbols.XSI_NONAMESPACESCHEMALOCACTION)) {
2073                                if (locationUriPairs == null) {
2074                                    locationUriPairs = new Hashtable();
2075                                }
2076                                locationUriPairs.put(fStringPool.toString(attrList.getAttValue(index)), "");
2077                                if (fNamespacesScope != null) {
2078                                    //bind prefix "" to URI "" in this case
2079                                    fNamespacesScope.setNamespaceForPrefix( fStringPool.addSymbol(""), 
2080                                                                            fStringPool.addSymbol(""));
2081                                }
2082                            } else if (localpart == fStringPool.addSymbol(SchemaSymbols.XSI_TYPE)) {
2083                                fXsiTypeAttValue = attrList.getAttValue(index);
2084                            }
2085                            // REVISIT: should we break here? 
2086                            //break;
2087                        }
2088                    }
2089                    index = attrList.getNextAttr(index);
2090                }
2091
2092                // try to resolve all the grammars here
2093                if (locationUriPairs != null) {
2094                    Enumeration locations = locationUriPairs.keys();
2095
2096                    while (locations.hasMoreElements()) {
2097                        String loc = (String) locations.nextElement();
2098                        String uri = (String) locationUriPairs.get(loc);
2099                        resolveSchemaGrammar( loc, uri);
2100                        //schemaCandidateURIs.removeElement(uri);
2101                    }
2102                }
2103
2104                //TO DO: This should be a feature that can be turned on or off
2105                /*****
2106                for (int i=0; i< schemaCandidateURIs.size(); i++) {
2107                
2108                    String uri = (String) schemaCandidateURIs.elementAt(i);
2109                    resolveSchemaGrammar(uri);
2110                }
2111                /*****/
2112
2113            }
2114
2115        }
2116
2117        // bind element to URI
2118        int prefix = element.prefix != -1 ? element.prefix : 0;
2119        int uri    = fNamespacesScope.getNamespaceForPrefix(prefix);
2120        if (element.prefix != -1 || uri != -1) {
2121            element.uri = uri;
2122            if (element.uri == -1) {
2123                Object[] args = { fStringPool.toString(element.prefix)};
2124                fErrorReporter.reportError(fErrorReporter.getLocator(),
2125                                           XMLMessages.XMLNS_DOMAIN,
2126                                           XMLMessages.MSG_PREFIX_DECLARED,
2127                                           XMLMessages.NC_PREFIX_DECLARED,
2128                                           args,
2129                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2130            }
2131        }
2132
2133
2134        if (fAttrListHandle != -1) {
2135            int index = attrList.getFirstAttr(fAttrListHandle);
2136            while (index != -1) {
2137                int attName = attrList.getAttrName(index);
2138                if (!fStringPool.equalNames(attName, fNamespacesPrefix)) {
2139                    int attPrefix = attrList.getAttrPrefix(index);
2140                    if (attPrefix != fNamespacesPrefix) {
2141                        if (attPrefix != -1 ) {
2142                            int attrUri = fNamespacesScope.getNamespaceForPrefix(attPrefix);
2143                            if (attrUri == -1) {
2144                                Object[] args = { fStringPool.toString(attPrefix)};
2145                                fErrorReporter.reportError(fErrorReporter.getLocator(),
2146                                                           XMLMessages.XMLNS_DOMAIN,
2147                                                           XMLMessages.MSG_PREFIX_DECLARED,
2148                                                           XMLMessages.NC_PREFIX_DECLARED,
2149                                                           args,
2150                                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2151                            }
2152                            attrList.setAttrURI(index, attrUri);
2153                        }
2154                    }
2155                }
2156                index = attrList.getNextAttr(index);
2157            }
2158        }
2159
2160    } // bindNamespacesToElementAndAttributes(QName,XMLAttrList)
2161
2162    void parseSchemaLocation(String schemaLocationStr, Hashtable locationUriPairs){
2163        if (locationUriPairs != null) {
2164            StringTokenizer tokenizer = new StringTokenizer(schemaLocationStr, " \n\t\r", false);
2165            int tokenTotal = tokenizer.countTokens();
2166            if (tokenTotal % 2 != 0 ) {
2167                // TO DO: report warning - malformed schemaLocation string
2168            } else {
2169                while (tokenizer.hasMoreTokens()) {
2170                    String uri = tokenizer.nextToken();
2171                    String location = tokenizer.nextToken();
2172
2173                    locationUriPairs.put(location, uri);
2174                }
2175            }
2176        } else {
2177            // TO DO: should report internal error here
2178        }
2179
2180    }// parseSchemaLocaltion(String, Hashtable)
2181    private void resolveSchemaGrammar( String loc, String uri) throws Exception {
2182
2183        SchemaGrammar grammar = (SchemaGrammar) fGrammarResolver.getGrammar(uri);
2184
2185        if (grammar == null) {
2186            DOMParser parser = new DOMParser();
2187            parser.setEntityResolver( new Resolver(fEntityHandler) );
2188            parser.setErrorHandler(  new ErrorHandler() );
2189
2190            try {
2191                parser.setFeature("http://xml.org/sax/features/validation", false);
2192                parser.setFeature("http://xml.org/sax/features/namespaces", true);
2193                parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
2194            } catch (  org.xml.sax.SAXNotRecognizedException e ) {
2195                e.printStackTrace();
2196            } catch ( org.xml.sax.SAXNotSupportedException e ) {
2197                e.printStackTrace();
2198            }
2199
2200            // expand it before passing it to the parser
2201            InputSource source = null;
2202            EntityResolver currentER = parser.getEntityResolver();
2203            if (currentER != null) {
2204                source = currentER.resolveEntity("", loc);
2205            }
2206            if (source == null) {
2207                loc = fEntityHandler.expandSystemId(loc);
2208                source = new InputSource(loc);
2209            }
2210            try {
2211                parser.parse( source );
2212            } catch ( IOException e ) {
2213                e.printStackTrace();
2214            } catch ( SAXException e ) {
2215                //System.out.println("loc = "+loc);
2216                //e.printStackTrace();
2217                reportRecoverableXMLError( XMLMessages.MSG_GENERIC_SCHEMA_ERROR, 
2218                                           XMLMessages.SCHEMA_GENERIC_ERROR, e.getMessage() );
2219            }
2220
2221            Document     document   = parser.getDocument(); //Our Grammar
2222
2223            TraverseSchema tst = null;
2224            try {
2225                if (DEBUG_SCHEMA_VALIDATION) {
2226                    System.out.println("I am geting the Schema Document");
2227                }
2228
2229                Element root   = document.getDocumentElement();// This is what we pass to TraverserSchema
2230                if (root == null) {
2231                    reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR, XMLMessages.SCHEMA_GENERIC_ERROR, "Can't get back Schema document's root element :" + loc); 
2232                } else {
2233                    if (uri == null || !uri.equals(root.getAttribute(SchemaSymbols.ATT_TARGETNAMESPACE)) ) {
2234                        reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR, XMLMessages.SCHEMA_GENERIC_ERROR, "Schema in " + loc + " has a different target namespace " + 
2235                                                  "from the one specified in the instance document :" + uri); 
2236                    }
2237                    grammar = new SchemaGrammar();
2238                    grammar.setGrammarDocument(document);
2239                    tst = new TraverseSchema( root, fStringPool, (SchemaGrammar)grammar, fGrammarResolver, fErrorReporter, source.getSystemId());
2240                    fGrammarResolver.putGrammar(document.getDocumentElement().getAttribute("targetNamespace"), grammar);
2241                }
2242            } catch (Exception e) {
2243                e.printStackTrace(System.err);
2244            }
2245        }
2246
2247    }
2248
2249    private void resolveSchemaGrammar(String uri) throws Exception{
2250
2251        resolveSchemaGrammar(uri, uri);
2252
2253    }
2254
2255    static class Resolver implements EntityResolver {
2256
2257        //
2258        // Constants
2259        //
2260
2261        private static final String SYSTEM[] = {
2262            "http://www.w3.org/TR/2000/WD-xmlschema-1-20000407/structures.dtd",
2263            "http://www.w3.org/TR/2000/WD-xmlschema-1-20000407/datatypes.dtd",
2264            "http://www.w3.org/TR/2000/WD-xmlschema-1-20000407/versionInfo.ent",
2265        };
2266        private static final String PATH[] = {
2267            "/org/apache/xerces/validators/schema/structures.dtd",
2268            "/org/apache/xerces/validators/schema/datatypes.dtd",
2269            "/org/apache/xerces/validators/schema/versionInfo.ent",
2270        };
2271
2272        //
2273        // Data
2274        //
2275
2276        private DefaultEntityHandler fEntityHandler;
2277
2278        //
2279        // Constructors
2280        //
2281
2282        public Resolver(DefaultEntityHandler handler) {
2283            fEntityHandler = handler;
2284        }
2285
2286        //
2287        // EntityResolver methods
2288        //
2289
2290        public InputSource resolveEntity(String publicId, String systemId)
2291        throws IOException, SAXException {
2292            // looking for the schema DTDs?
2293            for (int i = 0; i < SYSTEM.length; i++) {
2294                if (systemId.equals(SYSTEM[i])) {
2295                    InputStream stream = getClass().getResourceAsStream(PATH[i]);
2296                    if (stream != null) {
2297                        InputSource source = new InputSource(stream);
2298                        source.setPublicId(publicId);
2299                        source.setSystemId(systemId);
2300                        return source;
2301                    }
2302                }
2303            }
2304
2305            // first try to resolve using user's entity resolver
2306            EntityResolver resolver = fEntityHandler.getEntityResolver();
2307            if (resolver != null) {
2308                InputSource source = resolver.resolveEntity(publicId, systemId);
2309                if (source != null) {
2310                    return source;
2311                }
2312            }
2313
2314            // use default resolution
2315            return new InputSource(fEntityHandler.expandSystemId(systemId));
2316
2317        } // resolveEntity(String,String):InputSource
2318
2319    } // class Resolver
2320
2321    static class ErrorHandler implements org.xml.sax.ErrorHandler {
2322
2323        /** Warning. */
2324        public void warning(SAXParseException ex) {
2325            System.err.println("[Warning] "+
2326                               getLocationString(ex)+": "+
2327                               ex.getMessage());
2328        }
2329
2330        /** Error. */
2331        public void error(SAXParseException ex) {
2332            System.err.println("[Error] "+
2333                               getLocationString(ex)+": "+
2334                               ex.getMessage());
2335        }
2336
2337        /** Fatal error. */
2338        public void fatalError(SAXParseException ex)  {
2339            System.err.println("[Fatal Error] "+
2340                               getLocationString(ex)+": "+
2341                               ex.getMessage());
2342            //throw ex;
2343        }
2344
2345        //
2346        // Private methods
2347        //
2348
2349        /** Returns a string of the location. */
2350        private String getLocationString(SAXParseException ex) {
2351            StringBuffer str = new StringBuffer();
2352
2353            String systemId_ = ex.getSystemId();
2354            if (systemId_ != null) {
2355                int index = systemId_.lastIndexOf('/');
2356                if (index != -1)
2357                    systemId_ = systemId_.substring(index + 1);
2358                str.append(systemId_);
2359            }
2360            str.append(':');
2361            str.append(ex.getLineNumber());
2362            str.append(':');
2363            str.append(ex.getColumnNumber());
2364
2365            return str.toString();
2366
2367        } // getLocationString(SAXParseException):String
2368    }
2369
2370    private int attributeTypeName(XMLAttributeDecl attrDecl) {
2371        switch (attrDecl.type) {
2372        case XMLAttributeDecl.TYPE_ENTITY: {
2373                return attrDecl.list ? fENTITIESSymbol : fENTITYSymbol;
2374            }
2375        case XMLAttributeDecl.TYPE_ENUMERATION: {
2376                String enumeration = fStringPool.stringListAsString(attrDecl.enumeration);
2377                return fStringPool.addString(enumeration);
2378            }
2379        case XMLAttributeDecl.TYPE_ID: {
2380                return fIDSymbol;
2381            }
2382        case XMLAttributeDecl.TYPE_IDREF: {
2383                return attrDecl.list ? fIDREFSSymbol : fIDREFSymbol;
2384            }
2385        case XMLAttributeDecl.TYPE_NMTOKEN: {
2386                return attrDecl.list ? fNMTOKENSSymbol : fNMTOKENSSymbol;
2387            }
2388        case XMLAttributeDecl.TYPE_NOTATION: {
2389                return fNOTATIONSymbol;
2390            }
2391        }
2392        return fCDATASymbol;
2393    }
2394
2395    /** Validates element and attributes. */
2396    private void validateElementAndAttributes(QName element, 
2397                                              XMLAttrList attrList) 
2398        throws Exception {
2399
2400        if ((fElementDepth >= 0 && fValidationFlagStack[fElementDepth] != 0 )|| 
2401            (fGrammar == null && !fValidating && !fNamespacesEnabled) ) {
2402            fCurrentElementIndex = -1;
2403            fCurrentContentSpecType = -1;
2404            fInElementContent = false;
2405            if (fAttrListHandle != -1) {
2406                fAttrList.endAttrList();
2407                int index = fAttrList.getFirstAttr(fAttrListHandle);
2408                while (index != -1) {
2409                    if (fStringPool.equalNames(fAttrList.getAttrName(index), fXMLLang)) {
2410                        fDocumentScanner.checkXMLLangAttributeValue(fAttrList.getAttValue(index));
2411                        break;
2412                    }
2413                    index = fAttrList.getNextAttr(index);
2414                }
2415            }
2416            return;
2417        }
2418
2419        int elementIndex = -1;
2420        int contentSpecType = -1;
2421
2422        boolean skipThisOne = false;
2423        boolean laxThisOne = false;
2424
2425        if ( fGrammarIsSchemaGrammar && fContentLeafStack[fElementDepth] != null ) {
2426            ContentLeafNameTypeVector cv = fContentLeafStack[fElementDepth];
2427
2428            QName[] fElemMap = cv.leafNames;
2429            for (int i=0; i<cv.leafCount; i++) {
2430                int type = cv.leafTypes[i]  ;
2431                //System.out.println("******* see a ANY_OTHER_SKIP, "+type+","+element+","+fElemMap[i]+"\n*******");
2432
2433                if (type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
2434                    if (fElemMap[i].uri==element.uri
2435                        && fElemMap[i].localpart == element.localpart)
2436                        break;
2437                } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY) {
2438                    int uri = fElemMap[i].uri;
2439                    if (uri == -1 || uri == element.uri) {
2440                        break;
2441                    }
2442                } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL) {
2443                    if (element.uri == -1) {
2444                        break;
2445                    }
2446                } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
2447                    if (fElemMap[i].uri != element.uri) {
2448                        break;
2449                    }
2450                } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_SKIP) {
2451                    int uri = fElemMap[i].uri;
2452                    if (uri == -1 || uri == element.uri) {
2453                        skipThisOne = true;
2454                        break;
2455                    }
2456                } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL_SKIP) {
2457                    if (element.uri == -1) {
2458                        skipThisOne = true;
2459                        break;
2460                    }
2461                } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER_SKIP) {
2462                    if (fElemMap[i].uri != element.uri) {
2463                        skipThisOne = true;
2464                        break;
2465                    }
2466                } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_LAX) {
2467                    int uri = fElemMap[i].uri;
2468                    if (uri == -1 || uri == element.uri) {
2469                        laxThisOne = true;
2470                        break;
2471                    }
2472                } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_LOCAL_LAX) {
2473                    if (element.uri == -1) {
2474                        laxThisOne = true;
2475                        break;
2476                    }
2477                } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER_LAX) {
2478                    if (fElemMap[i].uri != element.uri) {
2479                        laxThisOne = true;
2480                        break;
2481                    }
2482                }
2483
2484            }
2485
2486        }
2487
2488        if (skipThisOne) {
2489            fNeedValidationOff = true;
2490        } else {
2491
2492            //REVISIT: is this the right place to check on if the Schema has changed?
2493
2494            if ( fNamespacesEnabled && fValidating && element.uri != fGrammarNameSpaceIndex && element.uri != -1  ) {
2495                fGrammarNameSpaceIndex = element.uri;
2496
2497                boolean success = switchGrammar(fGrammarNameSpaceIndex);
2498
2499                if (!success && !laxThisOne) {
2500                    reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR, XMLMessages.SCHEMA_GENERIC_ERROR, 
2501                                              "Grammar with uri : " + fStringPool.toString(fGrammarNameSpaceIndex) 
2502                                              + " , can not found");
2503                }
2504            }
2505
2506
2507            if ( fGrammar != null ) {
2508                if (DEBUG_SCHEMA_VALIDATION) {
2509                    System.out.println("*******Lookup element: uri: " + fStringPool.toString(element.uri)+
2510                                       "localpart: '" + fStringPool.toString(element.localpart)
2511                                       +"' and scope : " + fCurrentScope+"\n");
2512                }
2513
2514                elementIndex = fGrammar.getElementDeclIndex(element,fCurrentScope);
2515
2516                if (elementIndex == -1 ) {
2517                    elementIndex = fGrammar.getElementDeclIndex(element, TOP_LEVEL_SCOPE);
2518                }
2519
2520                if (elementIndex == -1) {
2521                    // if validating based on a Schema, try to resolve the element again by look it up in its ancestor types
2522                    if (fGrammarIsSchemaGrammar && fCurrentElementIndex != -1) {
2523                        TraverseSchema.ComplexTypeInfo baseTypeInfo = null;
2524                        baseTypeInfo = ((SchemaGrammar)fGrammar).getElementComplexTypeInfo(fCurrentElementIndex);
2525                        //TO DO: 
2526                        //      should check if baseTypeInfo is from the same Schema.
2527                        while (baseTypeInfo != null) {
2528                            elementIndex = fGrammar.getElementDeclIndex(element, baseTypeInfo.scopeDefined);
2529                            if (elementIndex > -1 ) {
2530                                break;
2531                            }
2532                            baseTypeInfo = baseTypeInfo.baseComplexTypeInfo;
2533                        }
2534                    }
2535                    //if still can't resolve it, try TOP_LEVEL_SCOPE AGAIN
2536                    /****
2537                    if ( element.uri == -1 && elementIndex == -1 
2538                    && fNamespacesScope != null 
2539                    && fNamespacesScope.getNamespaceForPrefix(StringPool.EMPTY_STRING) != -1 ) {
2540                    elementIndex = fGrammar.getElementDeclIndex(element.localpart, TOP_LEVEL_SCOPE);
2541                    // REVISIT:
2542                    // this is a hack to handle the situation where namespace prefix "" is bound to nothing, and there
2543                    // is a "noNamespaceSchemaLocation" specified, and element 
2544                    element.uri = StringPool.EMPTY_STRING;
2545                    }
2546                    /****/
2547
2548                    /****/
2549                    if (elementIndex == -1) {
2550                        if (laxThisOne) {
2551                            fNeedValidationOff = true;
2552                        } else
2553                            if (DEBUG_SCHEMA_VALIDATION)
2554                            System.out.println("!!! can not find elementDecl in the grammar, " +
2555                                               " the element localpart: " + element.localpart +
2556                                               "["+fStringPool.toString(element.localpart) +"]" +
2557                                               " the element uri: " + element.uri + 
2558                                               "["+fStringPool.toString(element.uri) +"]" +
2559                                               " and the current enclosing scope: " + fCurrentScope );
2560                    }
2561                    /****/
2562                }
2563
2564                if (DEBUG_SCHEMA_VALIDATION) {
2565                    fGrammar.getElementDecl(elementIndex, fTempElementDecl);
2566                    System.out.println("elementIndex: " + elementIndex+" \n and itsName : '" 
2567                                       + fStringPool.toString(fTempElementDecl.name.localpart)
2568                                       +"' \n its ContentType:" + fTempElementDecl.type
2569                                       +"\n its ContentSpecIndex : " + fTempElementDecl.contentSpecIndex +"\n"+
2570                                       " and the current enclosing scope: " + fCurrentScope);
2571                }
2572            }
2573
2574            contentSpecType =  getContentSpecType(elementIndex);
2575
2576            if (fGrammarIsSchemaGrammar && elementIndex != -1) {
2577
2578                // handle "xsi:type" right here
2579                if (fXsiTypeAttValue > -1) {
2580                    String xsiType = fStringPool.toString(fXsiTypeAttValue);
2581                    int colonP = xsiType.indexOf(":");
2582                    String prefix = "";
2583                    String localpart = xsiType;
2584                    if (colonP > -1) {
2585                        prefix = xsiType.substring(0,colonP);
2586                        localpart = xsiType.substring(colonP+1);
2587                    }
2588
2589                    String uri = "";
2590                    int uriIndex = -1;
2591                    if (fNamespacesScope != null) {
2592                        uriIndex = fNamespacesScope.getNamespaceForPrefix(fStringPool.addSymbol(prefix));
2593                        if (uriIndex > -1) {
2594                            uri = fStringPool.toString(uriIndex);
2595                            if (uriIndex != fGrammarNameSpaceIndex) {
2596                                fGrammarNameSpaceIndex = fCurrentSchemaURI = uriIndex;
2597                                boolean success = switchGrammar(fCurrentSchemaURI);
2598                                if (!success && !fNeedValidationOff) {
2599                                    reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR, 
2600                                                              XMLMessages.SCHEMA_GENERIC_ERROR, 
2601                                                              "Grammar with uri : " 
2602                                                              + fStringPool.toString(fCurrentSchemaURI) 
2603                                                              + " , can not found");
2604                                }
2605                            }
2606                        }
2607                    }
2608
2609
2610                    Hashtable complexRegistry = ((SchemaGrammar)fGrammar).getComplexTypeRegistry();
2611                    DatatypeValidatorFactoryImpl dataTypeReg = ((SchemaGrammar)fGrammar).getDatatypeRegistry();
2612                    if (complexRegistry==null || dataTypeReg == null) {
2613                        reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR, 
2614                                                  XMLMessages.SCHEMA_GENERIC_ERROR, 
2615                                                  fErrorReporter.getLocator().getSystemId()
2616                                                  +" line"+fErrorReporter.getLocator().getLineNumber()
2617                                                  +", canot resolve xsi:type = " + xsiType+"  ---2");
2618                    } else {
2619                        TraverseSchema.ComplexTypeInfo typeInfo = 
2620                        (TraverseSchema.ComplexTypeInfo) complexRegistry.get(uri+","+localpart);
2621                        //TO DO:
2622                        //      here need to check if this substitution is legal based on the current active grammar,
2623                        //      this should be easy, cause we already saved final, block and base type information in 
2624                        //      the SchemaGrammar.
2625
2626                        if (typeInfo==null) {
2627                            if (uri.length() == 0 || uri.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA) ) {
2628                                fXsiTypeValidator = dataTypeReg.getDatatypeValidator(localpart);
2629                            } else
2630                                fXsiTypeValidator = dataTypeReg.getDatatypeValidator(uri+","+localpart);
2631                            if ( fXsiTypeValidator == null )
2632                                reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR, 
2633                                                          XMLMessages.SCHEMA_GENERIC_ERROR, 
2634                                                          "unresolved type : "+uri+","+localpart 
2635                                                          +" found  in xsi:type handling");
2636                        } else
2637                            elementIndex = typeInfo.templateElementIndex;
2638                    }
2639
2640                    fXsiTypeAttValue = -1;
2641                }
2642
2643                //Change the current scope to be the one defined by this element.
2644                fCurrentScope = ((SchemaGrammar) fGrammar).getElementDefinedScope(elementIndex);
2645
2646                //       here need to check if we need to switch Grammar by asking SchemaGrammar whether 
2647                //       this element actually is of a type in another Schema.
2648                String anotherSchemaURI = ((SchemaGrammar)fGrammar).getElementFromAnotherSchemaURI(elementIndex);
2649                if (anotherSchemaURI != null) {
2650                    //before switch Grammar, set the elementIndex to be the template elementIndex of its type
2651                    if (contentSpecType != -1 
2652                        && contentSpecType != XMLElementDecl.TYPE_SIMPLE
2653                        && contentSpecType != XMLElementDecl.TYPE_EMPTY ) {
2654                        TraverseSchema.ComplexTypeInfo typeInfo = ((SchemaGrammar) fGrammar).getElementComplexTypeInfo(elementIndex);
2655                        if (typeInfo != null) {
2656                            elementIndex = typeInfo.templateElementIndex;
2657                        }
2658
2659                    }
2660
2661                    // now switch the grammar
2662                    fGrammarNameSpaceIndex = fCurrentSchemaURI = fStringPool.addSymbol(anotherSchemaURI);
2663                    boolean success = switchGrammar(fCurrentSchemaURI);
2664                    if (!success && !fNeedValidationOff) {
2665                        reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR, 
2666                                                  XMLMessages.SCHEMA_GENERIC_ERROR, 
2667                                                  "Grammar with uri : " 
2668                                                  + fStringPool.toString(fCurrentSchemaURI) 
2669                                                  + " , can not found");
2670                    }
2671                }
2672
2673            }
2674
2675            if (contentSpecType == -1 && fValidating && !fNeedValidationOff ) {
2676                reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_NOT_DECLARED,
2677                                          XMLMessages.VC_ELEMENT_VALID,
2678                                          element.rawname);
2679            }
2680            if (fGrammar != null && fGrammarIsSchemaGrammar && elementIndex != -1) {
2681                fAttrListHandle = addDefaultAttributes(elementIndex, attrList, fAttrListHandle, fValidating, fStandaloneReader != -1);
2682            }
2683            if (fAttrListHandle != -1) {
2684                fAttrList.endAttrList();
2685            }
2686
2687            if (DEBUG_PRINT_ATTRIBUTES) {
2688                String elementStr = fStringPool.toString(element.rawname);
2689                System.out.print("startElement: <" + elementStr);
2690                if (fAttrListHandle != -1) {
2691                    int index = attrList.getFirstAttr(fAttrListHandle);
2692                    while (index != -1) {
2693                        System.out.print(" " + fStringPool.toString(attrList.getAttrName(index)) + "=\"" +
2694                                         fStringPool.toString(attrList.getAttValue(index)) + "\"");
2695                        index = attrList.getNextAttr(index);
2696                    }
2697                }
2698                System.out.println(">");
2699            }
2700            // REVISIT: Validation. Do we need to recheck for the xml:lang
2701            //          attribute? It was already checked above -- perhaps
2702            //          this is to check values that are defaulted in? If
2703            //          so, this check could move to the attribute decl
2704            //          callback so we can check the default value before
2705            //          it is used.
2706            if (fAttrListHandle != -1 && !fNeedValidationOff ) {
2707                int index = fAttrList.getFirstAttr(fAttrListHandle);
2708                while (index != -1) {
2709                    int attrNameIndex = attrList.getAttrName(index);
2710
2711                    if (fStringPool.equalNames(attrNameIndex, fXMLLang)) {
2712                        fDocumentScanner.checkXMLLangAttributeValue(attrList.getAttValue(index));
2713                        // break;
2714                    }
2715                    // here, we validate every "user-defined" attributes
2716                    int _xmlns = fStringPool.addSymbol("xmlns");
2717
2718                    if (attrNameIndex != _xmlns && attrList.getAttrPrefix(index) != _xmlns)
2719                        if (fGrammar != null) {
2720                            fAttrNameLocator = getLocatorImpl(fAttrNameLocator);
2721                            fTempQName.setValues(attrList.getAttrPrefix(index), 
2722                                                 attrList.getAttrLocalpart(index),
2723                                                 attrList.getAttrName(index),
2724                                                 attrList.getAttrURI(index) );
2725                            int attDefIndex = getAttDefByElementIndex(elementIndex, fTempQName);
2726
2727                            if (fTempQName.uri != fXsiURI)
2728                                if (attDefIndex == -1 ) {
2729                                    if (fValidating) {
2730                                        // REVISIT - cache the elem/attr tuple so that we only give
2731                                        //  this error once for each unique occurrence
2732                                        Object[] args = { fStringPool.toString(element.rawname),
2733                                            fStringPool.toString(attrList.getAttrName(index))};
2734
2735                                        /*****/
2736                                        fErrorReporter.reportError(fAttrNameLocator,
2737                                                                   XMLMessages.XML_DOMAIN,
2738                                                                   XMLMessages.MSG_ATTRIBUTE_NOT_DECLARED,
2739                                                                   XMLMessages.VC_ATTRIBUTE_VALUE_TYPE,
2740                                                                   args,
2741                                                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);   
2742                                        /******/
2743                                    }
2744                                } else {
2745
2746                                    fGrammar.getAttributeDecl(attDefIndex, fTempAttDecl); 
2747
2748                                    int attributeType = attributeTypeName(fTempAttDecl);
2749                                    attrList.setAttType(index, attributeType);
2750
2751                                    if (fValidating) {
2752
2753                                        if (fGrammarIsDTDGrammar && 
2754                                            (fTempAttDecl.type == XMLAttributeDecl.TYPE_ENTITY ||
2755                                             fTempAttDecl.type == XMLAttributeDecl.TYPE_ENUMERATION ||
2756                                             fTempAttDecl.type == XMLAttributeDecl.TYPE_ID ||
2757                                             fTempAttDecl.type == XMLAttributeDecl.TYPE_IDREF ||
2758                                             fTempAttDecl.type == XMLAttributeDecl.TYPE_NMTOKEN ||
2759                                             fTempAttDecl.type == XMLAttributeDecl.TYPE_NOTATION)
2760                                           ) {
2761                                            validateDTDattribute(element, attrList.getAttValue(index), fTempAttDecl);
2762                                        }
2763
2764                                        // check to see if this attribute matched an attribute wildcard
2765                                        else if ( fGrammarIsSchemaGrammar && 
2766                                                  (fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_ANY 
2767                                                   ||fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_LIST
2768                                                   ||fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_LOCAL 
2769                                                   ||fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_OTHER) ) {
2770
2771                                            if (fTempAttDecl.defaultType == XMLAttributeDecl.PROCESSCONTENTS_SKIP) {
2772                                                // attribute should just be bypassed, 
2773                                            } else if ( fTempAttDecl.defaultType == XMLAttributeDecl.PROCESSCONTENTS_STRICT
2774                                                        || fTempAttDecl.defaultType == XMLAttributeDecl.PROCESSCONTENTS_LAX) {
2775
2776                                                boolean reportError = false;
2777                                                boolean processContentStrict = 
2778                                                fTempAttDecl.defaultType == XMLAttributeDecl.PROCESSCONTENTS_STRICT;
2779
2780                                                if (fTempQName.uri == -1) {
2781                                                    if (processContentStrict) {
2782                                                        reportError = true;
2783                                                    }
2784                                                } else {
2785                                                    Grammar aGrammar = 
2786                                                    fGrammarResolver.getGrammar(fStringPool.toString(fTempQName.uri));
2787
2788                                                    if (aGrammar == null || !(aGrammar instanceof SchemaGrammar) ) {
2789                                                        if (processContentStrict) {
2790                                                            reportError = true;
2791                                                        }
2792                                                    } else {
2793                                                        SchemaGrammar sGrammar = (SchemaGrammar) aGrammar;
2794                                                        Hashtable attRegistry = sGrammar.getAttirubteDeclRegistry();
2795                                                        if (attRegistry == null) {
2796                                                            if (processContentStrict) {
2797                                                                reportError = true;
2798                                                            }
2799                                                        } else {
2800                                                            XMLAttributeDecl attDecl = (XMLAttributeDecl) attRegistry.get(fStringPool.toString(fTempQName.localpart));
2801                                                            if (attDecl == null) {
2802                                                                if (processContentStrict) {
2803                                                                    reportError = true;
2804                                                                }
2805                                                            } else {
2806                                                                DatatypeValidator attDV = attDecl.datatypeValidator;
2807                                                                if (attDV == null) {
2808                                                                    if (processContentStrict) {
2809                                                                        reportError = true;
2810                                                                    }
2811                                                                } else {
2812                                                                    try {
2813                                                                        String  unTrimValue = fStringPool.toString(attrList.getAttValue(index));
2814                                                                        String  value       = unTrimValue.trim();
2815                                                                        if (attDecl.type == XMLAttributeDecl.TYPE_ID ) {
2816                                                                            this.fStoreIDRef.setDatatypeObject( fValID.validate( value, null ) );
2817                                                                        }
2818                                                                        if (attDecl.type == XMLAttributeDecl.TYPE_IDREF ) {
2819                                                                            attDV.validate(value, this.fStoreIDRef );
2820                                                                        } else
2821                                                                            attDV.validate(unTrimValue, null );
2822                                                                    } catch (InvalidDatatypeValueException idve) {
2823                                                                        fErrorReporter.reportError(fErrorReporter.getLocator(),
2824                                                                                                   SchemaMessageProvider.SCHEMA_DOMAIN,
2825                                                                                                   SchemaMessageProvider.DatatypeError,
2826                                                                                                   SchemaMessageProvider.MSG_NONE,
2827                                                                                                   new Object [] { idve.getMessage()},
2828                                                                                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2829                                                                    }
2830                                                                }
2831                                                            }
2832                                                        }
2833                                                    }
2834                                                }
2835                                                if (reportError) {
2836                                                    Object[] args = { fStringPool.toString(element.rawname),
2837                                                        "ANY---"+fStringPool.toString(attrList.getAttrName(index))};
2838
2839                                                    fErrorReporter.reportError(fAttrNameLocator,    
2840                                                                               XMLMessages.XML_DOMAIN,
2841                                                                               XMLMessages.MSG_ATTRIBUTE_NOT_DECLARED,
2842                                                                               XMLMessages.VC_ATTRIBUTE_VALUE_TYPE,
2843                                                                               args,
2844                                                                               XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2845
2846                                                }
2847                                            }
2848                                        } else if (fTempAttDecl.datatypeValidator == null) {
2849                                            Object[] args = { fStringPool.toString(element.rawname),
2850                                                fStringPool.toString(attrList.getAttrName(index))};
2851
2852                                            System.out.println("[Error] Datatypevalidator for attribute " + fStringPool.toString(attrList.getAttrName(index))
2853                                                               + " not found in element type " + fStringPool.toString(element.rawname));
2854                                            //REVISIT : is this the right message?
2855                                            /****/
2856                                            fErrorReporter.reportError(fAttrNameLocator,    
2857                                                                       XMLMessages.XML_DOMAIN,
2858                                                                       XMLMessages.MSG_ATTRIBUTE_NOT_DECLARED,
2859                                                                       XMLMessages.VC_ATTRIBUTE_VALUE_TYPE,
2860                                                                       args,
2861                                                                       XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);   
2862                                            /****/
2863                                        } else {
2864                                            try {
2865                                                String  unTrimValue = fStringPool.toString(attrList.getAttValue(index));
2866                                                String  value       = unTrimValue.trim();
2867                                                if (fTempAttDecl.type == XMLAttributeDecl.TYPE_ID ) {
2868                                                    this.fStoreIDRef.setDatatypeObject( fValID.validate( value, null ) );
2869                                                } else if (fTempAttDecl.type == XMLAttributeDecl.TYPE_IDREF ) {
2870                                                    fTempAttDecl.datatypeValidator.validate(value, this.fStoreIDRef );
2871                                                } else {
2872                                                    fTempAttDecl.datatypeValidator.validate(unTrimValue, null );
2873                                                }
2874
2875                                            } catch (InvalidDatatypeValueException idve) {
2876                                                fErrorReporter.reportError(fErrorReporter.getLocator(),
2877                                                                           SchemaMessageProvider.SCHEMA_DOMAIN,
2878                                                                           SchemaMessageProvider.DatatypeError,
2879                                                                           SchemaMessageProvider.MSG_NONE,
2880                                                                           new Object [] { idve.getMessage()},
2881                                                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2882                                            }
2883                                        }
2884                                    } // end of if (fValidating)
2885
2886
2887                                } // end of if (attDefIndex == -1) else
2888
2889                        }// end of if (fGrammar != null)
2890                    index = fAttrList.getNextAttr(index);
2891                }
2892            }
2893        }
2894        if (fAttrListHandle != -1) {
2895            int index = attrList.getFirstAttr(fAttrListHandle);
2896            while (index != -1) {
2897                int attName = attrList.getAttrName(index);
2898                if (!fStringPool.equalNames(attName, fNamespacesPrefix)) {
2899                    int attPrefix = attrList.getAttrPrefix(index);
2900                    if (attPrefix != fNamespacesPrefix) {
2901                        if (attPrefix != -1) {
2902                            int uri = fNamespacesScope.getNamespaceForPrefix(attPrefix);
2903                            if (uri == -1) {
2904                                Object[] args = { fStringPool.toString(attPrefix)};
2905                                fErrorReporter.reportError(fErrorReporter.getLocator(),
2906                                                           XMLMessages.XMLNS_DOMAIN,
2907                                                           XMLMessages.MSG_PREFIX_DECLARED,
2908                                                           XMLMessages.NC_PREFIX_DECLARED,
2909                                                           args,
2910                                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2911                            }
2912                            attrList.setAttrURI(index, uri);
2913                        }
2914                    }
2915                }
2916                index = attrList.getNextAttr(index);
2917            }
2918        }
2919
2920        fCurrentElementIndex = elementIndex;
2921        fCurrentContentSpecType = contentSpecType;
2922
2923        if (fValidating && contentSpecType == XMLElementDecl.TYPE_SIMPLE) {
2924            fBufferDatatype = true;
2925            fDatatypeBuffer.setLength(0);
2926        }
2927
2928        fInElementContent = (contentSpecType == XMLElementDecl.TYPE_CHILDREN);
2929
2930    } // validateElementAndAttributes(QName,XMLAttrList)
2931
2932
2933    //validate attributes in DTD fashion
2934    private void validateDTDattribute(QName element, int attValue, 
2935                                      XMLAttributeDecl attributeDecl) throws Exception{
2936        AttributeValidator av = null;
2937        switch (attributeDecl.type) {
2938        case XMLAttributeDecl.TYPE_ENTITY:
2939            {
2940                boolean isAlistAttribute = attributeDecl.list;//Caveat - Save this information because invalidStandaloneAttDef
2941                String  unTrimValue      = fStringPool.toString(attValue);
2942                String  value            = unTrimValue.trim();
2943                //System.out.println("value = " + value );
2944                                                               //changes fTempAttDef
2945                if (fValidationEnabled) {
2946                    if (value != unTrimValue) {
2947                        if (invalidStandaloneAttDef(element, attributeDecl.name)) {
2948                            reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
2949                                                      XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
2950                                                      fStringPool.toString(attributeDecl.name.rawname), unTrimValue, value);
2951                        }
2952                    }
2953                }
2954
2955                try {
2956                    if ( isAlistAttribute ) {
2957                        fValENTITIES.validate( value, null );
2958                    } else {
2959                        fValENTITY.validate( value, null );
2960                    }
2961                } catch ( InvalidDatatypeValueException ex ) {
2962                    if ( ex.getMajorCode() != 1 && ex.getMinorCode() != -1 ) {
2963                        reportRecoverableXMLError(ex.getMajorCode(),
2964                                                  ex.getMinorCode(),
2965                                                  fStringPool.toString( attributeDecl.name.rawname), value );
2966                    } else {
2967                        System.err.println("Error: " + ex.getLocalizedMessage() );//Should not happen
2968                    }
2969                }
2970
2971                /*if (attributeDecl.list) {
2972                    av = fAttValidatorENTITIES;
2973                }
2974                else {
2975                    av = fAttValidatorENTITY;
2976                }*/
2977
2978            }
2979            break;
2980        case XMLAttributeDecl.TYPE_ENUMERATION:
2981            av = fAttValidatorENUMERATION;
2982            break;
2983        case XMLAttributeDecl.TYPE_ID:
2984            {
2985                String  unTrimValue = fStringPool.toString(attValue);
2986                String  value       = unTrimValue.trim();
2987                if (fValidationEnabled) {
2988                    if (value != unTrimValue) {
2989                        if (invalidStandaloneAttDef(element, attributeDecl.name)) {
2990                            reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
2991                                                      XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
2992                                                      fStringPool.toString(attributeDecl.name.rawname), unTrimValue, value);
2993                        }
2994                    }
2995                }
2996                try {
2997                    //this.fIdDefs = (Hashtable) fValID.validate( value, null );
2998                    //System.out.println("this.fIdDefs = " + this.fIdDefs );
2999
3000                    this.fStoreIDRef.setDatatypeObject( fValID.validate( value, null ) );
3001                } catch ( InvalidDatatypeValueException ex ) {
3002                    reportRecoverableXMLError(ex.getMajorCode(),
3003                                              ex.getMinorCode(),
3004                                              fStringPool.toString( attributeDecl.name.rawname), value );
3005                }
3006            }
3007            break;
3008        case XMLAttributeDecl.TYPE_IDREF:
3009            {
3010                String  unTrimValue = fStringPool.toString(attValue);
3011                String  value       = unTrimValue.trim();
3012                boolean isAlistAttribute = attributeDecl.list;//Caveat - Save this information because invalidStandaloneAttDef
3013                                                              //changes fTempAttDef
3014                if (fValidationEnabled) {
3015                    if (value != unTrimValue) {
3016                        if (invalidStandaloneAttDef(element, attributeDecl.name)) {
3017                            reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
3018                                                      XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
3019                                                      fStringPool.toString(attributeDecl.name.rawname), unTrimValue, value);
3020                        }
3021                    }
3022                }
3023                try {
3024                    if ( isAlistAttribute ) {
3025                        fValIDRefs.validate( value, this.fStoreIDRef );
3026                    } else {
3027                        fValIDRef.validate( value, this.fStoreIDRef );
3028                    }
3029                } catch ( InvalidDatatypeValueException ex ) {
3030                    if ( ex.getMajorCode() != 1 && ex.getMinorCode() != -1 ) {
3031                        reportRecoverableXMLError(ex.getMajorCode(),
3032                                                  ex.getMinorCode(),
3033                                                  fStringPool.toString( attributeDecl.name.rawname), value );
3034                    } else {
3035                        System.err.println("Error: " + ex.getLocalizedMessage() );//Should not happen
3036                    }
3037                }
3038
3039            }
3040            break;
3041        case XMLAttributeDecl.TYPE_NOTATION:
3042            {
3043                /* WIP
3044                String  unTrimValue = fStringPool.toString(attValue);
3045             String  value       = unTrimValue.trim();
3046             if (fValidationEnabled) {
3047                 if (value != unTrimValue) {
3048                     if (invalidStandaloneAttDef(element, attributeDecl.name)) {
3049                         reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
3050                                                   XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
3051                                                   fStringPool.toString(attributeDecl.name.rawname), unTrimValue, value);
3052                     }
3053                 }
3054             }
3055             try {
3056                 //this.fIdDefs = (Hashtable) fValID.validate( value, null );
3057                 //System.out.println("this.fIdDefs = " + this.fIdDefs );
3058
3059                 this.fStoreIDRef.setDatatypeObject( fValID.validate( value, null ) );
3060             } catch ( InvalidDatatypeValueException ex ) {
3061                 reportRecoverableXMLError(ex.getMajorCode(),
3062                                           ex.getMinorCode(),
3063                                           fStringPool.toString( attributeDecl.name.rawname), value );
3064             }
3065          }
3066            */
3067            av = fAttValidatorNOTATION;
3068
3069
3070            }
3071            break;
3072        case XMLAttributeDecl.TYPE_NMTOKEN:
3073            {
3074                String  unTrimValue = fStringPool.toString(attValue);
3075                String  value       = unTrimValue.trim();
3076                boolean isAlistAttribute = attributeDecl.list;//Caveat - Save this information because invalidStandaloneAttDef
3077                //changes fTempAttDef
3078                if (fValidationEnabled) {
3079                    if (value != unTrimValue) {
3080                        if (invalidStandaloneAttDef(element, attributeDecl.name)) {
3081                            reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
3082                                                      XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
3083                                                      fStringPool.toString(attributeDecl.name.rawname), unTrimValue, value);
3084                        }
3085                    }
3086                }
3087                try {
3088                    if ( isAlistAttribute ) {
3089                        fValNMTOKENS.validate( value, null );
3090                    } else {
3091                        fValNMTOKEN.validate( value, null );
3092                    }
3093                } catch ( InvalidDatatypeValueException ex ) {
3094                    reportRecoverableXMLError(XMLMessages.MSG_NMTOKEN_INVALID,
3095                                              XMLMessages.VC_NAME_TOKEN,
3096                                              fStringPool.toString(attributeDecl.name.rawname), value);//TODO NMTOKENS messge
3097                }
3098
3099            }
3100            break;
3101        }
3102        if ( av != null )
3103            av.normalize(element, attributeDecl.name, attValue, 
3104                         attributeDecl.type, attributeDecl.enumeration);
3105    }
3106
3107    /** Character data in content. */
3108    private void charDataInContent() {
3109
3110        if (DEBUG_ELEMENT_CHILDREN) {
3111            System.out.println("charDataInContent()");
3112        }
3113        if (fElementChildren.length <= fElementChildrenLength) {
3114            QName[] newarray = new QName[fElementChildren.length * 2];
3115            System.arraycopy(fElementChildren, 0, newarray, 0, fElementChildren.length);
3116            fElementChildren = newarray;
3117        }
3118        QName qname = fElementChildren[fElementChildrenLength];
3119        if (qname == null) {
3120            for (int i = fElementChildrenLength; i < fElementChildren.length; i++) {
3121                fElementChildren[i] = new QName();
3122            }
3123            qname = fElementChildren[fElementChildrenLength];
3124        }
3125        qname.clear();
3126        fElementChildrenLength++;
3127
3128    } // charDataInCount()
3129
3130    /**
3131     * Check that the content of an element is valid.
3132     * <p>
3133     * This is the method of primary concern to the validator. This method is called
3134     * upon the scanner reaching the end tag of an element. At that time, the
3135     * element's children must be structurally validated, so it calls this method.
3136     * The index of the element being checked (in the decl pool), is provided as
3137     * well as an array of element name indexes of the children. The validator must
3138     * confirm that this element can have these children in this order.
3139     * <p>
3140     * This can also be called to do 'what if' testing of content models just to see
3141     * if they would be valid.
3142     * <p>
3143     * Note that the element index is an index into the element decl pool, whereas
3144     * the children indexes are name indexes, i.e. into the string pool.
3145     * <p>
3146     * A value of -1 in the children array indicates a PCDATA node. All other
3147     * indexes will be positive and represent child elements. The count can be
3148     * zero, since some elements have the EMPTY content model and that must be
3149     * confirmed.
3150     *
3151     * @param elementIndex The index within the <code>ElementDeclPool</code> of this
3152     *                     element.
3153     * @param childCount The number of entries in the <code>children</code> array.
3154     * @param children The children of this element.  Each integer is an index within
3155     *                 the <code>StringPool</code> of the child element name.  An index
3156     *                 of -1 is used to indicate an occurrence of non-whitespace character
3157     *                 data.
3158     *
3159     * @return The value -1 if fully valid, else the 0 based index of the child
3160     *         that first failed. If the value returned is equal to the number
3161     *         of children, then additional content is required to reach a valid
3162     *         ending state.
3163     *
3164     * @exception Exception Thrown on error.
3165     */
3166    private int checkContent(int elementIndex, 
3167                             QName[] children,
3168                             int childOffset, 
3169                             int childCount) throws Exception {
3170
3171        // Get the element name index from the element
3172        // REVISIT: Validation
3173        final int elementType = fCurrentElement.rawname;
3174
3175        if (DEBUG_PRINT_CONTENT) {
3176            String strTmp = fStringPool.toString(elementType);
3177            System.out.println("Name: "+strTmp+", "+
3178                               "Count: "+childCount+", "+
3179                               "ContentSpecType: " +fCurrentContentSpecType); //+getContentSpecAsString(elementIndex));
3180            for (int index = childOffset; index < (childOffset+childCount)  && index < 10; index++) {
3181                if (index == 0) {
3182                    System.out.print("  (");
3183                }
3184                String childName = (children[index].localpart == -1) ? "#PCDATA" : fStringPool.toString(children[index].localpart);
3185                if (index + 1 == childCount) {
3186                    System.out.println(childName + ")");
3187                } else if (index + 1 == 10) {
3188                    System.out.println(childName + ",...)");
3189                } else {
3190                    System.out.print(childName + ",");
3191                }
3192            }
3193        }
3194
3195        // Get out the content spec for this element
3196        final int contentType = fCurrentContentSpecType;
3197
3198// debugging
3199//System.out.println("~~~~~~in checkContent, fCurrentContentSpecType : " + fCurrentContentSpecType);
3200
3201        //
3202        //  Deal with the possible types of content. We try to optimized here
3203        //  by dealing specially with content models that don't require the
3204        //  full DFA treatment.
3205        //
3206        if (contentType == XMLElementDecl.TYPE_EMPTY) {
3207            //
3208            //  If the child count is greater than zero, then this is
3209            //  an error right off the bat at index 0.
3210            //
3211            if (childCount != 0) {
3212                return 0;
3213            }
3214        } else if (contentType == XMLElementDecl.TYPE_ANY) {
3215            //
3216            //  This one is open game so we don't pass any judgement on it
3217            //  at all. Its assumed to fine since it can hold anything.
3218            //
3219        } else if (contentType == XMLElementDecl.TYPE_MIXED ||  
3220                   contentType == XMLElementDecl.TYPE_CHILDREN) {
3221            // Get the content model for this element, faulting it in if needed
3222            XMLContentModel cmElem = null;
3223            try {
3224                cmElem = getElementContentModel(elementIndex);
3225                int result = cmElem.validateContent(children, childOffset, childCount);
3226                if (result != -1 && fGrammarIsSchemaGrammar) {
3227                    // REVISIT: not optimized for performance, 
3228                    EquivClassComparator comparator = new EquivClassComparator(fGrammarResolver, fStringPool);
3229                    cmElem.setEquivClassComparator(comparator);
3230                    result = cmElem.validateContentSpecial(children, childOffset, childCount);
3231                }
3232                return result;
3233            } catch (CMException excToCatch) {
3234                // REVISIT - Translate the caught exception to the protected error API
3235                int majorCode = excToCatch.getErrorCode();
3236                fErrorReporter.reportError(fErrorReporter.getLocator(),
3237                                           ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
3238                                           majorCode,
3239                                           0,
3240                                           null,
3241                                           XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
3242            }
3243        } else if (contentType == -1) {
3244            reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_NOT_DECLARED,
3245                                      XMLMessages.VC_ELEMENT_VALID,
3246                                      elementType);
3247        } else if (contentType == XMLElementDecl.TYPE_SIMPLE ) {
3248
3249            XMLContentModel cmElem = null;
3250            if (childCount > 0) {
3251                fErrorReporter.reportError(fErrorReporter.getLocator(),
3252                                           SchemaMessageProvider.SCHEMA_DOMAIN,
3253                                           SchemaMessageProvider.DatatypeError,
3254                                           SchemaMessageProvider.MSG_NONE,
3255                                           new Object [] { "In element '"+fStringPool.toString(elementType)+"' : "+
3256                                               "Can not have element children within a simple type content"},
3257                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
3258            } else {
3259                try {
3260
3261                    fGrammar.getElementDecl(elementIndex, fTempElementDecl);
3262
3263                    DatatypeValidator dv = fTempElementDecl.datatypeValidator;
3264
3265                    // If there is xsi:type validator, substitute it.
3266                    if ( fXsiTypeValidator != null ) {
3267                        dv = fXsiTypeValidator;
3268                        fXsiTypeValidator = null;
3269                    }
3270
3271                    if (dv == null) {
3272                        System.out.println("Internal Error: this element have a simpletype "+
3273                                           "but no datatypevalidator was found, element "+fTempElementDecl.name
3274                                           +",locapart: "+fStringPool.toString(fTempElementDecl.name.localpart));
3275                    } else {
3276                        dv.validate(fDatatypeBuffer.toString(), null);
3277                    }
3278
3279                } catch (InvalidDatatypeValueException idve) {
3280                    fErrorReporter.reportError(fErrorReporter.getLocator(),
3281                                               SchemaMessageProvider.SCHEMA_DOMAIN,
3282                                               SchemaMessageProvider.DatatypeError,
3283                                               SchemaMessageProvider.MSG_NONE,
3284                                               new Object [] { idve.getMessage()},
3285                                               XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
3286                }
3287            }
3288        } else {
3289            fErrorReporter.reportError(fErrorReporter.getLocator(),
3290                                       ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
3291                                       ImplementationMessages.VAL_CST,
3292                                       0,
3293                                       null,
3294                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
3295        }
3296
3297        // We succeeded
3298        return -1;
3299
3300    } // checkContent(int,int,int[]):int
3301
3302
3303    /** 
3304     * Checks that all declared elements refer to declared elements
3305     * in their content models. This method calls out to the error
3306     * handler to indicate warnings.
3307     */
3308    /*private void checkDeclaredElements() throws Exception {
3309
3310                //****DEBUG****
3311                if (DEBUG) print("(???) XMLValidator.checkDeclaredElements\n");
3312                //****DEBUG****
3313
3314        for (int i = 0; i < fElementCount; i++) {
3315            int type = fGrammar.getContentSpecType(i);
3316            if (type == XMLElementDecl.TYPE_MIXED || type == XMLElementDecl.TYPE_CHILDREN) {
3317                int chunk = i >> CHUNK_SHIFT;
3318                int index = i &  CHUNK_MASK;
3319                int contentSpecIndex = fContentSpec[chunk][index];
3320                checkDeclaredElements(i, contentSpecIndex);
3321            }
3322        }
3323    }
3324    */
3325
3326    private void printChildren() {
3327        if (DEBUG_ELEMENT_CHILDREN) {
3328            System.out.print('[');
3329            for (int i = 0; i < fElementChildrenLength; i++) {
3330                System.out.print(' ');
3331                QName qname = fElementChildren[i];
3332                if (qname != null) {
3333                    System.out.print(fStringPool.toString(qname.rawname));
3334                } else {
3335                    System.out.print("null");
3336                }
3337                if (i < fElementChildrenLength - 1) {
3338                    System.out.print(", ");
3339                }
3340                System.out.flush();
3341            }
3342            System.out.print(" ]");
3343            System.out.println();
3344        }
3345    }
3346
3347    private void printStack() {
3348        if (DEBUG_ELEMENT_CHILDREN) {
3349            System.out.print('{');
3350            for (int i = 0; i <= fElementDepth; i++) {
3351                System.out.print(' ');
3352                System.out.print(fElementChildrenOffsetStack[i]);
3353                if (i < fElementDepth) {
3354                    System.out.print(", ");
3355                }
3356                System.out.flush();
3357            }
3358            System.out.print(" }");
3359            System.out.println();
3360        }
3361    }
3362
3363
3364    //
3365    // Interfaces
3366    //
3367
3368    /**
3369     * AttributeValidator.
3370     */
3371    public interface AttributeValidator {
3372
3373        //
3374        // AttributeValidator methods
3375        //
3376
3377        /** Normalize. */
3378        public int normalize(QName element, QName attribute, 
3379                             int attValue, int attType, int enumHandle) 
3380        throws Exception;
3381
3382    } // interface AttributeValidator
3383
3384
3385    /** Returns true if invalid standalone attribute definition. */
3386    boolean invalidStandaloneAttDef(QName element, QName attribute) {
3387        if (fStandaloneReader == -1) {
3388            return false;
3389        }
3390        // we are normalizing a default att value...  this ok?
3391        if (element.rawname == -1) {
3392            return false;
3393        }
3394        return getAttDefIsExternal(element, attribute);
3395    }
3396
3397
3398    //
3399    // Classes
3400    //
3401
3402
3403    /**
3404     * AttValidatorNOTATION.
3405     */
3406    final class AttValidatorNOTATION 
3407    implements AttributeValidator {
3408
3409        //
3410        // AttributeValidator methods
3411        //
3412
3413        /** Normalize. */
3414        public int normalize(QName element, QName attribute, 
3415                             int attValueHandle, int attType, 
3416                             int enumHandle) throws Exception {
3417            //
3418            // Normalize attribute based upon attribute type...
3419            //
3420            String attValue = fStringPool.toString(attValueHandle);
3421            String newAttValue = attValue.trim();
3422            if (fValidating) {
3423                // REVISIT - can we release the old string?
3424                if (newAttValue != attValue) {
3425                    if (invalidStandaloneAttDef(element, attribute)) {
3426                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
3427                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
3428                                                  fStringPool.toString(attribute.rawname), attValue, newAttValue);
3429                    }
3430                    attValueHandle = fStringPool.addSymbol(newAttValue);
3431                } else {
3432                    attValueHandle = fStringPool.addSymbol(attValueHandle);
3433                }
3434                //
3435                // NOTATION - check that the value is in the AttDef enumeration (V_TAGo)
3436                //
3437                if (!fStringPool.stringInList(enumHandle, attValueHandle)) {
3438                    reportRecoverableXMLError(XMLMessages.MSG_ATTRIBUTE_VALUE_NOT_IN_LIST,
3439                                              XMLMessages.VC_NOTATION_ATTRIBUTES,
3440                                              fStringPool.toString(attribute.rawname),
3441                                              newAttValue, fStringPool.stringListAsString(enumHandle));
3442                }
3443            } else if (newAttValue != attValue) {
3444                // REVISIT - can we release the old string?
3445                attValueHandle = fStringPool.addSymbol(newAttValue);
3446            }
3447            return attValueHandle;
3448
3449        } // normalize(QName,QName,int,int,int):int
3450
3451        //
3452        // Package methods
3453        //
3454
3455        /** Returns true if invalid standalone attribute definition. */
3456        boolean invalidStandaloneAttDef(QName element, QName attribute) {
3457            if (fStandaloneReader == -1) {
3458                return false;
3459            }
3460            // we are normalizing a default att value...  this ok?
3461            if (element.rawname == -1) {
3462                return false;
3463            }
3464            return getAttDefIsExternal(element, attribute);
3465        }
3466
3467    } // class AttValidatorNOTATION
3468
3469    /**
3470     * AttValidatorENUMERATION.
3471     */
3472    final class AttValidatorENUMERATION 
3473    implements AttributeValidator {
3474
3475        //
3476        // AttributeValidator methods
3477        //
3478
3479        /** Normalize. */
3480        public int normalize(QName element, QName attribute, 
3481                             int attValueHandle, int attType, 
3482                             int enumHandle) throws Exception {
3483            //
3484            // Normalize attribute based upon attribute type...
3485            //
3486            String attValue = fStringPool.toString(attValueHandle);
3487            String newAttValue = attValue.trim();
3488            if (fValidating) {
3489                // REVISIT - can we release the old string?
3490                if (newAttValue != attValue) {
3491                    if (invalidStandaloneAttDef(element, attribute)) {
3492                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
3493                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
3494                                                  fStringPool.toString(attribute.rawname), attValue, newAttValue);
3495                    }
3496                    attValueHandle = fStringPool.addSymbol(newAttValue);
3497                } else {
3498                    attValueHandle = fStringPool.addSymbol(attValueHandle);
3499                }
3500                //
3501                // ENUMERATION - check that value is in the AttDef enumeration (V_TAG9)
3502                //
3503                if (!fStringPool.stringInList(enumHandle, attValueHandle)) {
3504                    reportRecoverableXMLError(XMLMessages.MSG_ATTRIBUTE_VALUE_NOT_IN_LIST,
3505                                              XMLMessages.VC_ENUMERATION,
3506                                              fStringPool.toString(attribute.rawname),
3507                                              newAttValue, fStringPool.stringListAsString(enumHandle));
3508                }
3509            } else if (newAttValue != attValue) {
3510                // REVISIT - can we release the old string?
3511                attValueHandle = fStringPool.addSymbol(newAttValue);
3512            }
3513            return attValueHandle;
3514
3515        } // normalize(QName,QName,int,int,int):int
3516
3517        //
3518        // Package methods
3519        //
3520
3521        /** Returns true if invalid standalone attribute definition. */
3522        boolean invalidStandaloneAttDef(QName element, QName attribute) {
3523            if (fStandaloneReader == -1) {
3524                return false;
3525            }
3526            // we are normalizing a default att value...  this ok?
3527            if (element.rawname == -1) {
3528                return false;
3529            }
3530            return getAttDefIsExternal(element, attribute);
3531        }
3532
3533    } // class AttValidatorENUMERATION
3534
3535} // class XMLValidator