KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > apache > xerces > validators > common > XMLValidator


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999,2000,2001 The Apache Software Foundation.
6  * All rights 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.enhydra.apache.xerces.validators.common;
59
60 import java.io.IOException JavaDoc;
61 import java.util.Enumeration JavaDoc;
62 import java.util.Hashtable JavaDoc;
63 import java.util.Stack JavaDoc;
64 import java.util.StringTokenizer JavaDoc;
65 import java.util.Vector JavaDoc;
66
67 import org.enhydra.apache.xerces.framework.XMLAttrList;
68 import org.enhydra.apache.xerces.framework.XMLContentSpec;
69 import org.enhydra.apache.xerces.framework.XMLDocumentHandler;
70 import org.enhydra.apache.xerces.framework.XMLDocumentScanner;
71 import org.enhydra.apache.xerces.framework.XMLErrorReporter;
72 import org.enhydra.apache.xerces.parsers.DOMParser;
73 import org.enhydra.apache.xerces.readers.DefaultEntityHandler;
74 import org.enhydra.apache.xerces.readers.XMLEntityHandler;
75 import org.enhydra.apache.xerces.utils.ImplementationMessages;
76 import org.enhydra.apache.xerces.utils.IntStack;
77 import org.enhydra.apache.xerces.utils.NamespacesScope;
78 import org.enhydra.apache.xerces.utils.QName;
79 import org.enhydra.apache.xerces.utils.StringPool;
80 import org.enhydra.apache.xerces.utils.XMLMessages;
81 import org.enhydra.apache.xerces.validators.datatype.AnySimpleType;
82 import org.enhydra.apache.xerces.validators.datatype.DatatypeValidator;
83 import org.enhydra.apache.xerces.validators.datatype.DatatypeValidatorFactoryImpl;
84 import org.enhydra.apache.xerces.validators.datatype.ENTITYDatatypeValidator;
85 import org.enhydra.apache.xerces.validators.datatype.IDDatatypeValidator;
86 import org.enhydra.apache.xerces.validators.datatype.IDREFDatatypeValidator;
87 import org.enhydra.apache.xerces.validators.datatype.InvalidDatatypeValueException;
88 import org.enhydra.apache.xerces.validators.datatype.NOTATIONDatatypeValidator;
89 import org.enhydra.apache.xerces.validators.datatype.StateMessageDatatype;
90 import org.enhydra.apache.xerces.validators.datatype.UnionDatatypeValidator;
91 import org.enhydra.apache.xerces.validators.dtd.DTDGrammar;
92 import org.enhydra.apache.xerces.validators.schema.GeneralAttrCheck;
93 import org.enhydra.apache.xerces.validators.schema.SchemaGrammar;
94 import org.enhydra.apache.xerces.validators.schema.SchemaMessageProvider;
95 import org.enhydra.apache.xerces.validators.schema.SchemaSymbols;
96 import org.enhydra.apache.xerces.validators.schema.SubstitutionGroupComparator;
97 import org.enhydra.apache.xerces.validators.schema.TraverseSchema;
98 import org.enhydra.apache.xerces.validators.schema.identity.Field;
99 import org.enhydra.apache.xerces.validators.schema.identity.FieldActivator;
100 import org.enhydra.apache.xerces.validators.schema.identity.IDValue;
101 import org.enhydra.apache.xerces.validators.schema.identity.IdentityConstraint;
102 import org.enhydra.apache.xerces.validators.schema.identity.Key;
103 import org.enhydra.apache.xerces.validators.schema.identity.KeyRef;
104 import org.enhydra.apache.xerces.validators.schema.identity.Selector;
105 import org.enhydra.apache.xerces.validators.schema.identity.Unique;
106 import org.enhydra.apache.xerces.validators.schema.identity.ValueStore;
107 import org.enhydra.apache.xerces.validators.schema.identity.XPathMatcher;
108 import org.w3c.dom.Document JavaDoc;
109 import org.w3c.dom.Element JavaDoc;
110 import org.xml.sax.EntityResolver JavaDoc;
111 import org.xml.sax.InputSource JavaDoc;
112 import org.xml.sax.Locator JavaDoc;
113 import org.xml.sax.SAXException JavaDoc;
114 import org.xml.sax.SAXParseException JavaDoc;
115 import org.xml.sax.helpers.LocatorImpl JavaDoc;
116
117 /**
118  * This class is the super all-in-one validator used by the parser.
119  *
120  * @version $Id: XMLValidator.java,v 1.2 2005/01/26 08:28:44 jkjome Exp $
121  */

122 public final class XMLValidator
123     implements DefaultEntityHandler.EventHandler,
124                XMLEntityHandler.CharDataHandler,
125                XMLDocumentScanner.EventHandler,
126                NamespacesScope.NamespacesHandler,
127                FieldActivator // for identity constraints
128
{
129
130    //
131
// Constants
132
//
133

134    // debugging
135

136    private static final boolean PRINT_EXCEPTION_STACK_TRACE = false;
137    private static final boolean DEBUG_PRINT_ATTRIBUTES = false;
138    private static final boolean DEBUG_PRINT_CONTENT = false;
139    private static final boolean DEBUG_SCHEMA_VALIDATION = false;
140    private static final boolean DEBUG_ELEMENT_CHILDREN = false;
141
142    /** Compile to true to debug identity constraints. */
143    protected static final boolean DEBUG_IDENTITY_CONSTRAINTS = false;
144
145    /** Compile to true to debug value stores. */
146    protected static final boolean DEBUG_VALUE_STORES = false;
147
148    // Chunk size constants
149

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

155    private Hashtable JavaDoc fIdDefs = new Hashtable JavaDoc();
156    private Hashtable JavaDoc fIdREFDefs = new Hashtable JavaDoc();
157
158    private StateMessageDatatype fValidateIDRef = new StateMessageDatatype() {
159       private Hashtable JavaDoc fIdDefs;
160       public Object JavaDoc getDatatypeObject(){
161          return(Object JavaDoc) fIdDefs;
162       }
163       public int getDatatypeState(){
164          return IDREFDatatypeValidator.IDREF_VALIDATE;
165       }
166       public void setDatatypeObject( Object JavaDoc data ){
167          fIdDefs = (Hashtable JavaDoc) data;
168       }
169    };
170
171    private StateMessageDatatype fCheckIDRef = new StateMessageDatatype() {
172       private Object JavaDoc[] fLists;
173       public Object JavaDoc getDatatypeObject(){
174          return(Object JavaDoc) fLists;
175       }
176       public int getDatatypeState(){
177          return IDREFDatatypeValidator.IDREF_CHECKID;
178       }
179       public void setDatatypeObject( Object JavaDoc data ){
180         fLists = (Object JavaDoc[]) data;
181       }
182    };
183
184    private StateMessageDatatype fValidateEntity = new StateMessageDatatype() {
185       private Object JavaDoc fData;
186       public Object JavaDoc getDatatypeObject(){
187          return fData;
188       }
189       public int getDatatypeState(){
190          return ENTITYDatatypeValidator.ENTITY_VALIDATE;
191       }
192       public void setDatatypeObject( Object JavaDoc data ){
193          fData = data;
194       }
195    };
196
197    //
198
// Data
199
//
200

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

204    // attribute validators
205

206    private AttributeValidator fAttValidatorNOTATION = new AttValidatorNOTATION();
207    private AttributeValidator fAttValidatorENUMERATION = new AttValidatorENUMERATION();
208    private AttributeValidator fAttValidatorDATATYPE = null;
209
210    // Package access for use by AttributeValidator classes.
211

212    StringPool fStringPool = null;
213    boolean fValidating = false;
214    boolean fInElementContent = false;
215    int fStandaloneReader = -1;
216
217
218    // settings
219

220    private boolean fValidationEnabled = false;
221    private boolean fDynamicValidation = false;
222    private boolean fSchemaValidation = true;
223    private boolean fSchemaValidationFullChecking = false;
224    private boolean fValidationEnabledByDynamic = false;
225    private boolean fDynamicDisabledByValidation = false;
226    private boolean fWarningOnDuplicateAttDef = false;
227    private boolean fWarningOnUndeclaredElements = false;
228    private boolean fNormalizeAttributeValues = true;
229    private boolean fLoadDTDGrammar = true;
230    // expose normalized values for element/attribute content
231
// default: expose Infoset
232
private boolean fNormalizeContents = false;
233
234    // REVISIT: normalization
235
// would not work properly for UNION types since we don't have
236
// correct whiteSpace facet to normalize values.
237
//
238

239    // Private temporary variables
240

241   private Hashtable JavaDoc fLocationUriPairs = new Hashtable JavaDoc(10);
242
243
244    // declarations
245

246    private String JavaDoc fExternalSchemas = null;
247    private String JavaDoc fExternalNoNamespaceSchema = null;
248    private DOMParser fSchemaGrammarParser = null;
249    private int fDeclaration[];
250    private XMLErrorReporter fErrorReporter = null;
251    private DefaultEntityHandler fEntityHandler = null;
252    private QName fCurrentElement = new QName();
253
254    private ContentLeafNameTypeVector[] fContentLeafStack = new ContentLeafNameTypeVector[8];
255
256    //OTWI: on-the-way-in
257
// store the content model
258
private XMLContentModel[] fContentModelStack = new XMLContentModel[8];
259    // >= 0 normal state; -1: error; -2: on-the-way-out
260
private int[] fContentModelStateStack = new int[8];
261    // how many child elements have succefully validated
262
private int[] fContentModelEleCount = new int[8];
263
264    private int[] fValidationFlagStack = new int[8];
265
266    private int[] fScopeStack = new int[8];
267    private int[] fGrammarNameSpaceIndexStack = new int[8];
268
269    private int[] fElementEntityStack = new int[8];
270    private int[] fElementIndexStack = new int[8];
271    private int[] fContentSpecTypeStack = new int[8];
272
273    private static final int sizeQNameParts = 8;
274    private QName[] fElementQNamePartsStack = new QName[sizeQNameParts];
275
276    private QName[] fElementChildren = new QName[32];
277    private int fElementChildrenLength = 0;
278    private int[] fElementChildrenOffsetStack = new int[32];
279    private int fElementDepth = -1;
280
281    private boolean fNamespacesEnabled = false;
282    private NamespacesScope fNamespacesScope = null;
283    private int fNamespacesPrefix = -1;
284    private QName fRootElement = new QName();
285    private int fAttrListHandle = -1;
286    private int fCurrentElementEntity = -1;
287    private int fCurrentElementIndex = -1;
288    private int fCurrentContentSpecType = -1;
289    private boolean fSeenDoctypeDecl = false;
290
291    private final int TOP_LEVEL_SCOPE = -1;
292    private int fCurrentScope = TOP_LEVEL_SCOPE;
293    private int fCurrentSchemaURI = StringPool.EMPTY_STRING;
294    private int fEmptyURI = StringPool.EMPTY_STRING;
295    private int fXsiPrefix = - 1;
296    private int fXsiURI = -2;
297    private int fXsiTypeAttValue = -1;
298    private DatatypeValidator fXsiTypeValidator = null;
299
300    private boolean fNil = false;
301
302    private Grammar fGrammar = null;
303    private int fGrammarNameSpaceIndex = StringPool.EMPTY_STRING;
304    private GrammarResolver fGrammarResolver = null;
305
306
307    // state and stuff
308

309    private boolean fScanningDTD = false;
310    private XMLDocumentScanner fDocumentScanner = null;
311    private boolean fCalledStartDocument = false;
312    private XMLDocumentHandler fDocumentHandler = null;
313    private XMLDocumentHandler.DTDHandler fDTDHandler = null;
314    private boolean fSeenRootElement = false;
315    private XMLAttrList fAttrList = null;
316    private int fXMLLang = -1;
317    private LocatorImpl JavaDoc fAttrNameLocator = null;
318    private boolean fCheckedForSchema = false;
319    private boolean fDeclsAreExternal = false;
320    private StringPool.CharArrayRange fCurrentElementCharArrayRange = null;
321    private char[] fCharRefData = null;
322    private boolean fSendCharDataAsCharArray = false;
323    private boolean fBufferDatatype = false;
324    // holds normalized or unnormalized string element value,
325
private StringBuffer JavaDoc fDatatypeBuffer = new StringBuffer JavaDoc();
326
327    private QName fTempQName = new QName();
328    private XMLAttributeDecl fTempAttDecl = new XMLAttributeDecl();
329    private XMLAttributeDecl fTempAttributeDecl = new XMLAttributeDecl();
330    private XMLElementDecl fTempElementDecl = new XMLElementDecl();
331
332    private boolean fGrammarIsDTDGrammar = false;
333    private boolean fGrammarIsSchemaGrammar = false;
334
335    private boolean fNeedValidationOff = false;
336
337    //Schema Normalization
338
private static final boolean DEBUG_NORMALIZATION = false;
339     private DatatypeValidator fCurrentDV = null; //current datatype validator
340
private boolean fFirstChunk = true; // got first chunk in characters() (SAX)
341
private boolean fTrailing = false; // Previous chunk had a trailing space
342
private short fWhiteSpace = DatatypeValidator.COLLAPSE; //whiteSpace: preserve/replace/collapse
343
private StringBuffer JavaDoc fNormalizedStr = new StringBuffer JavaDoc(CHUNK_SIZE); //holds normalized str value
344
private StringBuffer JavaDoc fUnnormalizedStr = new StringBuffer JavaDoc(CHUNK_SIZE); //holds unnormalized str value
345

346
347
348    // symbols
349

350    private int fEMPTYSymbol = -1;
351    private int fANYSymbol = -1;
352    private int fMIXEDSymbol = -1;
353    private int fCHILDRENSymbol = -1;
354    private int fCDATASymbol = -1;
355    private int fIDSymbol = -1;
356    private int fIDREFSymbol = -1;
357    private int fIDREFSSymbol = -1;
358    private int fENTITYSymbol = -1;
359    private int fENTITIESSymbol = -1;
360    private int fNMTOKENSymbol = -1;
361    private int fNMTOKENSSymbol = -1;
362    private int fNOTATIONSymbol = -1;
363    private int fENUMERATIONSymbol = -1;
364    private int fREQUIREDSymbol = -1;
365    private int fFIXEDSymbol = -1;
366    private int fDATATYPESymbol = -1;
367    private int fEpsilonIndex = -1;
368
369
370    //Datatype Registry
371

372    private DatatypeValidatorFactoryImpl fDataTypeReg = null;
373    private DatatypeValidator fValID = null;
374    private DatatypeValidator fValIDRef = null;
375    private DatatypeValidator fValIDRefs = null;
376    private DatatypeValidator fValENTITY = null;
377    private DatatypeValidator fValENTITIES = null;
378    private DatatypeValidator fValNMTOKEN = null;
379    private DatatypeValidator fValNMTOKENS = null;
380    private DatatypeValidator fValNOTATION = null;
381
382     // identity constraint information
383

384     /**
385      * Stack of active XPath matchers for identity constraints. All
386      * active XPath matchers are notified of startElement, characters
387      * and endElement callbacks in order to perform their matches.
388      * <p>
389      * For each element with identity constraints, the selector of
390      * each identity constraint is activated. When the selector matches
391      * its XPath, then all the fields of the identity constraint are
392      * activated.
393      * <p>
394      * <strong>Note:</strong> Once the activation scope is left, the
395      * XPath matchers are automatically removed from the stack of
396      * active matchers and no longer receive callbacks.
397      */

398     protected XPathMatcherStack fMatcherStack = new XPathMatcherStack();
399
400     /** Cache of value stores for identity constraint fields. */
401     protected ValueStoreCache fValueStoreCache = new ValueStoreCache();
402
403     // store the substitution group comparator
404
protected SubstitutionGroupComparator fSGComparator = null;
405
406     // on which grammars we have checked UPA
407
protected Hashtable JavaDoc UPACheckedGrammarURIs = new Hashtable JavaDoc();
408     protected static Object JavaDoc fgNullObject = new Object JavaDoc();
409
410    //
411
// Constructors
412
//
413

414    /** Constructs an XML validator. */
415    public XMLValidator(StringPool stringPool,
416                        XMLErrorReporter errorReporter,
417                        DefaultEntityHandler entityHandler,
418                        XMLDocumentScanner documentScanner) {
419
420       // keep references
421
fStringPool = stringPool;
422       fErrorReporter = errorReporter;
423       fEntityHandler = entityHandler;
424       fDocumentScanner = documentScanner;
425
426       fValidateEntity.setDatatypeObject(new Object JavaDoc[]{entityHandler, stringPool});
427       fValidateIDRef.setDatatypeObject(fIdREFDefs);
428       fCheckIDRef.setDatatypeObject(new Object JavaDoc[]{fIdDefs, fIdREFDefs});
429
430       fEmptyURI = fStringPool.addSymbol("");
431       fXsiURI = fStringPool.addSymbol(SchemaSymbols.URI_XSI);
432       // initialize
433
fAttrList = new XMLAttrList(fStringPool);
434       entityHandler.setEventHandler(this);
435       entityHandler.setCharDataHandler(this);
436       fDocumentScanner.setEventHandler(this);
437
438       for (int i = 0; i < sizeQNameParts; i++) {
439          fElementQNamePartsStack[i] = new QName();
440       }
441       init();
442
443    } // <init>(StringPool,XMLErrorReporter,DefaultEntityHandler,XMLDocumentScanner)
444

445    public void setGrammarResolver(GrammarResolver grammarResolver){
446       fGrammarResolver = grammarResolver;
447     }
448
449    //
450
// Public methods
451
//
452

453    // initialization
454

455    /** Set char data processing preference and handlers. */
456    public void initHandlers(boolean sendCharDataAsCharArray,
457                             XMLDocumentHandler docHandler,
458                             XMLDocumentHandler.DTDHandler dtdHandler) {
459
460       fSendCharDataAsCharArray = sendCharDataAsCharArray;
461       fEntityHandler.setSendCharDataAsCharArray(fSendCharDataAsCharArray);
462       fDocumentHandler = docHandler;
463       fDTDHandler = dtdHandler;
464
465    } // initHandlers(boolean,XMLDocumentHandler,XMLDocumentHandler.DTDHandler)
466

467    /** Reset or copy. */
468    public void resetOrCopy(StringPool stringPool) throws Exception JavaDoc {
469       fAttrList = new XMLAttrList(stringPool);
470       resetCommon(stringPool);
471    }
472
473    /** Reset. */
474    public void reset(StringPool stringPool) throws Exception JavaDoc {
475       fAttrList.reset(stringPool);
476       resetCommon(stringPool);
477    }
478
479
480    // settings
481

482    /**
483     * Turning on validation/dynamic turns on validation if it is off, and
484     * this is remembered. Turning off validation DISABLES validation/dynamic
485     * if it is on. Turning off validation/dynamic DOES NOT turn off
486     * validation if it was explicitly turned on, only if it was turned on
487     * BECAUSE OF the call to turn validation/dynamic on. Turning on
488     * validation will REENABLE and turn validation/dynamic back on if it
489     * was disabled by a call that turned off validation while
490     * validation/dynamic was enabled.
491     */

492    public void setValidationEnabled(boolean flag) throws Exception JavaDoc {
493       fValidationEnabled = flag;
494       fValidationEnabledByDynamic = false;
495       if (fValidationEnabled) {
496          if (fDynamicDisabledByValidation) {
497             fDynamicValidation = true;
498             fDynamicDisabledByValidation = false;
499          }
500       } else if (fDynamicValidation) {
501          fDynamicValidation = false;
502          fDynamicDisabledByValidation = true;
503       }
504       fValidating = fValidationEnabled;
505       if (fValidating) {
506         initDataTypeValidators();
507       }
508     }
509
510    /** Returns true if validation is enabled. */
511    public boolean getValidationEnabled() {
512       return fValidationEnabled;
513    }
514
515    /** Sets whether Schema support is on/off. */
516    public void setSchemaValidationEnabled(boolean flag) {
517       fSchemaValidation = flag;
518    }
519
520    /** Returns true if Schema support is on. */
521    public boolean getSchemaValidationEnabled() {
522       return fSchemaValidation;
523    }
524
525    /** Sets whether full Schema error checking is on/off */
526    public void setSchemaFullCheckingEnabled(boolean flag) {
527       fSchemaValidationFullChecking = flag;
528    }
529
530    //Properties on the parser to allow the user to specify
531
//XML schemas externaly
532
//
533
public void setExternalSchemas(Object JavaDoc value){
534        fExternalSchemas = (String JavaDoc)value;
535    }
536    public void setExternalNoNamespaceSchema(Object JavaDoc value){
537        fExternalNoNamespaceSchema = (String JavaDoc)value;
538    }
539
540    public String JavaDoc getExternalSchemas(){
541        return fExternalSchemas;
542    }
543    public String JavaDoc getExternalNoNamespaceSchema(){
544        return fExternalNoNamespaceSchema;
545    }
546
547    /** Returns true if full Schema checking is on. */
548    public boolean getSchemaFullCheckingEnabled() {
549       return fSchemaValidationFullChecking;
550    }
551
552    /** Sets whether validation is dynamic. */
553    public void setDynamicValidationEnabled(boolean flag) throws Exception JavaDoc {
554       fDynamicValidation = flag;
555       fDynamicDisabledByValidation = false;
556       if (!fDynamicValidation) {
557          if (fValidationEnabledByDynamic) {
558             fValidationEnabled = false;
559             fValidationEnabledByDynamic = false;
560          }
561       } else if (!fValidationEnabled) {
562          fValidationEnabled = true;
563          fValidationEnabledByDynamic = true;
564       }
565       fValidating = fValidationEnabled;
566       if (fValidating) {
567         initDataTypeValidators();
568       }
569     }
570
571    /** Returns true if validation is dynamic. */
572    public boolean getDynamicValidationEnabled() {
573       return fDynamicValidation;
574    }
575
576    /** Sets fNormalizeAttributeValues **/
577    public void setNormalizeAttributeValues(boolean normalize){
578       fNormalizeAttributeValues = normalize;
579    }
580
581    /** Sets fLoadDTDGrammar when validation is off **/
582    public void setLoadDTDGrammar(boolean loadDG){
583       if (fValidating) {
584          fLoadDTDGrammar = true;
585       } else {
586          fLoadDTDGrammar = loadDG;
587       }
588    }
589
590    /** Returns fLoadDTDGrammar **/
591    public boolean getLoadDTDGrammar() {
592       return fLoadDTDGrammar;
593    }
594
595    /** Sets whether namespaces are enabled. */
596    public void setNamespacesEnabled(boolean flag) {
597       fNamespacesEnabled = flag;
598    }
599
600    /** Returns true if namespaces are enabled. */
601    public boolean getNamespacesEnabled() {
602       return fNamespacesEnabled;
603    }
604
605    /** Sets whether duplicate attribute definitions signal a warning. */
606    public void setWarningOnDuplicateAttDef(boolean flag) {
607       fWarningOnDuplicateAttDef = flag;
608    }
609
610    /** Returns true if duplicate attribute definitions signal a warning. */
611    public boolean getWarningOnDuplicateAttDef() {
612       return fWarningOnDuplicateAttDef;
613    }
614
615    /** Sets whether undeclared elements signal a warning. */
616    public void setWarningOnUndeclaredElements(boolean flag) {
617       fWarningOnUndeclaredElements = flag;
618    }
619
620    /** Returns true if undeclared elements signal a warning. */
621    public boolean getWarningOnUndeclaredElements() {
622       return fWarningOnUndeclaredElements;
623    }
624
625    /** Sets fNormalizeContents **/
626    public void setNormalizeContents(boolean normalize){
627       fNormalizeContents = normalize;
628    }
629    public boolean getNormalizeConents() {
630       return fNormalizeContents;
631    }
632
633     //
634
// FieldActivator methods
635
//
636

637    /**
638     * Start the value scope for the specified identity constraint. This
639     * method is called when the selector matches in order to initialize
640     * the value store.
641     *
642     * @param identityConstraint The identity constraint.
643     */

644    public void startValueScopeFor(IdentityConstraint identityConstraint)
645         throws Exception JavaDoc {
646
647         for(int i=0; i<identityConstraint.getFieldCount(); i++) {
648             Field field = identityConstraint.getFieldAt(i);
649             ValueStoreBase valueStore = fValueStoreCache.getValueStoreFor(field);
650             valueStore.startValueScope();
651         }
652
653     } // startValueScopeFor(IdentityConstraint identityConstraint)
654

655     /**
656      * Request to activate the specified field. This method returns the
657      * matcher for the field.
658      *
659      * @param field The field to activate.
660      */

661     public XPathMatcher activateField(Field field) throws Exception JavaDoc {
662         if (DEBUG_IDENTITY_CONSTRAINTS) {
663             System.out.println("<IC>: activateField(\""+field+"\")");
664         }
665         ValueStore valueStore = fValueStoreCache.getValueStoreFor(field);
666         field.setMayMatch(true);
667         XPathMatcher matcher = field.createMatcher(valueStore);
668         fMatcherStack.addMatcher(matcher);
669         matcher.startDocumentFragment(fStringPool);
670         return matcher;
671     } // activateField(Field):XPathMatcher
672

673     /**
674      * Ends the value scope for the specified identity constraint.
675      *
676      * @param identityConstraint The identity constraint.
677      */

678     public void endValueScopeFor(IdentityConstraint identityConstraint)
679         throws Exception JavaDoc {
680
681         ValueStoreBase valueStore = fValueStoreCache.getValueStoreFor(identityConstraint);
682         valueStore.endValueScope();
683
684     } // endValueScopeFor(IdentityConstraint)
685

686    //
687
// DefaultEntityHandler.EventHandler methods
688
//
689

690    /** Start entity reference. */
691    public void startEntityReference(int entityName, int entityType, int entityContext) throws Exception JavaDoc {
692       fDocumentHandler.startEntityReference(entityName, entityType, entityContext);
693    }
694
695    /** End entity reference. */
696    public void endEntityReference(int entityName, int entityType, int entityContext) throws Exception JavaDoc {
697       fDocumentHandler.endEntityReference(entityName, entityType, entityContext);
698    }
699
700    /** Send end of input notification. */
701    public void sendEndOfInputNotifications(int entityName, boolean moreToFollow) throws Exception JavaDoc {
702       fDocumentScanner.endOfInput(entityName, moreToFollow);
703       /***
704       if (fScanningDTD) {
705           fDTDImporter.sendEndOfInputNotifications(entityName, moreToFollow);
706       }
707       /***/

708    }
709
710    /** Send reader change notifications. */
711    public void sendReaderChangeNotifications(XMLEntityHandler.EntityReader reader, int readerId) throws Exception JavaDoc {
712       fDocumentScanner.readerChange(reader, readerId);
713       /***
714       if (fScanningDTD) {
715           fDTDImporter.sendReaderChangeNotifications(reader, readerId);
716       }
717       /***/

718    }
719
720    /** External entity standalone check. */
721    public boolean externalEntityStandaloneCheck() {
722       return(fStandaloneReader != -1 && fValidating);
723    }
724
725    /** Return true if validating. */
726    public boolean getValidating() {
727       return fValidating;
728    }
729
730    //
731
// XMLEntityHandler.CharDataHandler methods
732
//
733

734    private String JavaDoc normalizeValue (String JavaDoc unNormalizedValue){
735        fUnnormalizedStr.setLength(0);
736        fUnnormalizedStr.append(unNormalizedValue);
737        normalizeWhitespace(fUnnormalizedStr, (fWhiteSpace == DatatypeValidator.COLLAPSE));
738        return fNormalizedStr.toString();
739    }
740
741     /**
742      * Normalize whitespace in an XMLString according to the rules of attribute
743      * value normalization - converting all whitespace characters to space
744      * characters.
745      * In addition for attributes of type other than CDATA: trim leading and
746      * trailing spaces and collapse spaces (0x20 only).
747      *
748      * @param value The string to normalize.
749      * @returns 0 if no triming is done or if there is neither leading nor
750      * trailing whitespace,
751      * 1 if there is only leading whitespace,
752      * 2 if there is only trailing whitespace,
753      * 3 if there is both leading and trailing whitespace.
754      */

755
756     private int normalizeWhitespace( StringBuffer JavaDoc chars, boolean collapse) {
757         int length = fUnnormalizedStr.length();
758         fNormalizedStr.setLength(0);
759         boolean skipSpace = collapse;
760         boolean sawNonWS = false;
761         int leading = 0;
762         int trailing = 0;
763         int c;
764         for (int i = 0; i < length; i++) {
765             c = chars.charAt(i);
766             if (c == 0x20 || c == 0x0D || c == 0x0A || c == 0x09) {
767                 if (!skipSpace) {
768                     // take the first whitespace as a space and skip the others
769
fNormalizedStr.append(' ');
770                     skipSpace = collapse;
771                 }
772                 if (!sawNonWS) {
773                     // this is a leading whitespace, record it
774
leading = 1;
775                 }
776             }
777             else {
778                 fNormalizedStr.append((char)c);
779                 skipSpace = false;
780                 sawNonWS = true;
781             }
782         }
783         if (skipSpace) {
784             c = fNormalizedStr.length();
785             if ( c != 0) {
786                 // if we finished on a space trim it but also record it
787
fNormalizedStr.setLength (--c);
788                 trailing = 2;
789             }
790             else if (leading != 0 && !sawNonWS) {
791                 // if all we had was whitespace we skipped record it as
792
// trailing whitespace as well
793
trailing = 2;
794             }
795         }
796         //value.setValues(fNormalizedStr);
797
return collapse ? leading + trailing : 0;
798     }
799
800    /** Process characters. Schema Normalization*/
801    public void processCharacters(char[] chars, int offset, int length) throws Exception JavaDoc {
802        if (DEBUG_NORMALIZATION) {
803            System.out.println("==>processCharacters(char[] chars, int offset, int length");
804        }
805        if (fValidating) {
806            if (fInElementContent || fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
807                if (DEBUG_NORMALIZATION) {
808                    System.out.println("==>charDataInContent()");
809                }
810             charDataInContent();
811            }
812         if (fBufferDatatype) {
813             if (fFirstChunk && fGrammar!=null) {
814                 fGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
815                 fCurrentDV = fTempElementDecl.datatypeValidator;
816                 if ( fXsiTypeValidator != null ) {
817                    fCurrentDV = fXsiTypeValidator;
818                    fXsiTypeValidator = null;
819                 }
820                 if (fCurrentDV !=null) {
821                     fWhiteSpace = fCurrentDV.getWSFacet();
822                 }
823             }
824             if (DEBUG_NORMALIZATION) {
825                 System.out.println("Start schema datatype normalization <whiteSpace value=" +fWhiteSpace+">");
826             }
827             if (!fNormalizeContents || fWhiteSpace == DatatypeValidator.PRESERVE) { //do not normalize
828
fDatatypeBuffer.append(chars, offset, length);
829             }
830             else {
831                 fUnnormalizedStr.setLength(0);
832                 fUnnormalizedStr.append(chars, offset, length);
833                 int spaces = normalizeWhitespace(fUnnormalizedStr, (fWhiteSpace==DatatypeValidator.COLLAPSE));
834                 int nLength = fNormalizedStr.length();
835                 if (nLength > 0) {
836                     if (!fFirstChunk && (fWhiteSpace==DatatypeValidator.COLLAPSE) && fTrailing) {
837                          fNormalizedStr.insert(0, ' ');
838                          nLength++;
839                     }
840                     if ((length-offset)!=nLength) {
841                         char[] newChars = new char[nLength];
842                         fNormalizedStr.getChars(0, nLength , newChars, 0);
843                         chars = newChars;
844                         offset = 0;
845                         length = nLength;
846                     }
847                     else {
848                        fNormalizedStr.getChars(0, nLength , chars, 0);
849                     }
850                     fDatatypeBuffer.append(chars, offset, length);
851
852                     // call all active identity constraints
853
int count = fMatcherStack.getMatcherCount();
854                     for (int i = 0; i < count; i++) {
855                         XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
856                         if (DEBUG_IDENTITY_CONSTRAINTS) {
857                             String JavaDoc text = new String JavaDoc(chars, offset, length);
858                             System.out.println("<IC>: "+matcher.toString()+"#characters("+text+")");
859                         }
860                         matcher.characters(chars, offset, length);
861                     }
862
863                     fDocumentHandler.characters(chars, offset, length);
864                 }
865                 fTrailing = (spaces > 1)?true:false;
866                 fFirstChunk = false;
867                 return;
868             }
869         }
870     }
871
872        fFirstChunk = false;
873
874        // call all active identity constraints
875
int count = fMatcherStack.getMatcherCount();
876        for (int i = 0; i < count; i++) {
877            XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
878            if (DEBUG_IDENTITY_CONSTRAINTS) {
879                String JavaDoc text = new String JavaDoc(chars, offset, length);
880                System.out.println("<IC>: "+matcher.toString()+"#characters("+text+")");
881            }
882            matcher.characters(chars, offset, length);
883        }
884
885        fDocumentHandler.characters(chars, offset, length);
886    }
887
888    /** Process characters. */
889    public void processCharacters(int data) throws Exception JavaDoc {
890       if (fValidating) {
891         if (fInElementContent || fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
892             charDataInContent();
893         }
894         if (fBufferDatatype) {
895             fGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
896             //REVISIT: add normalization according to datatypes
897
fCurrentDV = fTempElementDecl.datatypeValidator;
898             if ( fXsiTypeValidator != null ) {
899                fCurrentDV = fXsiTypeValidator;
900                fXsiTypeValidator = null;
901             }
902             if (fCurrentDV !=null) {
903                 fWhiteSpace = fCurrentDV.getWSFacet();
904             }
905             if (!fNormalizeContents || fWhiteSpace == DatatypeValidator.PRESERVE) { //no normalization done
906
fDatatypeBuffer.append(fStringPool.toString(data));
907             }
908             else {
909                 String JavaDoc str = fStringPool.toString(data);
910                 int length = str.length();
911                 fUnnormalizedStr.setLength(0);
912                 fUnnormalizedStr.append(str);
913                 int spaces = normalizeWhitespace(fUnnormalizedStr, (fWhiteSpace == DatatypeValidator.COLLAPSE));
914                 if (fWhiteSpace != DatatypeValidator.PRESERVE) {
915                     //normalization was done.
916
fStringPool.releaseString(data);
917                     data = fStringPool.addString(fNormalizedStr.toString());
918                 }
919                 fDatatypeBuffer.append(fNormalizedStr.toString());
920             }
921         }
922       }
923
924       // call all active identity constraints
925
int count = fMatcherStack.getMatcherCount();
926       if (count > 0) {
927           String JavaDoc text = fStringPool.toString(data);
928           char[] chars = new char[text.length()];
929           int offset = 0;
930           int length = chars.length;
931           text.getChars(offset, length, chars, offset);
932           for (int i = 0; i < count; i++) {
933               XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
934               if (DEBUG_IDENTITY_CONSTRAINTS) {
935                   System.out.println("<IC>: "+matcher.toString()+"#characters("+text+")");
936               }
937               matcher.characters(chars, offset, length);
938           }
939       }
940
941       fDocumentHandler.characters(data);
942    }
943
944    /** Process whitespace. */
945    public void processWhitespace(char[] chars, int offset, int length)
946    throws Exception JavaDoc {
947
948       if (fInElementContent) {
949          if (fStandaloneReader != -1 && fValidating && getElementDeclIsExternal(fCurrentElementIndex)) {
950             reportRecoverableXMLError(XMLMessages.MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE,
951                                       XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION);
952          }
953          fDocumentHandler.ignorableWhitespace(chars, offset, length);
954       } else {
955          if (fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
956             charDataInContent();
957          }
958
959          // call all active identity constraints
960
int count = fMatcherStack.getMatcherCount();
961          for (int i = 0; i < count; i++) {
962              XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
963              if (DEBUG_IDENTITY_CONSTRAINTS) {
964                  String JavaDoc text = new String JavaDoc(chars, offset, length);
965                  System.out.println("<IC>: "+matcher.toString()+"#characters("+text+")");
966              }
967              matcher.characters(chars, offset, length);
968          }
969          if (fGrammar != null && fValidating) {
970
971              fGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
972              fCurrentDV = fTempElementDecl.datatypeValidator;
973              if ( fXsiTypeValidator != null ) {
974                 fCurrentDV = fXsiTypeValidator;
975                 fXsiTypeValidator = null;
976              }
977              if (fCurrentDV !=null) {
978                 fWhiteSpace = fCurrentDV.getWSFacet();
979              }
980
981
982             if (fWhiteSpace == DatatypeValidator.PRESERVE) { //do not normalize
983
fDatatypeBuffer.append(chars, offset, length);
984             }
985
986          }
987
988          fDocumentHandler.characters(chars, offset, length);
989       }
990
991    } // processWhitespace(char[],int,int)
992

993    /** Process whitespace. */
994    public void processWhitespace(int data) throws Exception JavaDoc {
995
996       if (fInElementContent) {
997          if (fStandaloneReader != -1 && fValidating && getElementDeclIsExternal(fCurrentElementIndex)) {
998             reportRecoverableXMLError(XMLMessages.MSG_WHITE_SPACE_IN_ELEMENT_CONTENT_WHEN_STANDALONE,
999                                       XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION);
1000         }
1001         fDocumentHandler.ignorableWhitespace(data);
1002      } else {
1003         if (fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY) {
1004            charDataInContent();
1005         }
1006
1007         // call all active identity constraints
1008
int count = fMatcherStack.getMatcherCount();
1009         if (count > 0) {
1010             String JavaDoc text = fStringPool.toString(data);
1011             char[] chars = new char[text.length()];
1012             int offset = 0;
1013             int length = chars.length;
1014             text.getChars(length, length, chars, offset);
1015             for (int i = 0; i < count; i++) {
1016                 XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
1017                 if (DEBUG_IDENTITY_CONSTRAINTS) {
1018                     System.out.println("<IC>: "+matcher.toString()+"#characters("+text+")");
1019                 }
1020                 matcher.characters(chars, offset, length);
1021             }
1022         }
1023
1024         if (fGrammar != null && fValidating) {
1025            fGrammar.getElementDecl(fCurrentElementIndex, fTempElementDecl);
1026            fCurrentDV = fTempElementDecl.datatypeValidator;
1027            if ( fXsiTypeValidator != null ) {
1028               fCurrentDV = fXsiTypeValidator;
1029               fXsiTypeValidator = null;
1030            }
1031            if (fCurrentDV !=null) {
1032                fWhiteSpace = fCurrentDV.getWSFacet();
1033            }
1034            if (fWhiteSpace == DatatypeValidator.PRESERVE) { //no normalization done
1035
fDatatypeBuffer.append(fStringPool.toString(data));
1036            }
1037
1038         }
1039         fDocumentHandler.characters(data);
1040      }
1041
1042   } // processWhitespace(int)
1043

1044   //
1045
// XMLDocumentScanner.EventHandler methods
1046
//
1047

1048   /** Scans element type. */
1049   public void scanElementType(XMLEntityHandler.EntityReader entityReader,
1050                               char fastchar, QName element) throws Exception JavaDoc {
1051
1052      if (!fNamespacesEnabled) {
1053         element.clear();
1054         element.localpart = entityReader.scanName(fastchar);
1055         element.rawname = element.localpart;
1056      } else {
1057         entityReader.scanQName(fastchar, element);
1058         if (entityReader.lookingAtChar(':', false)) {
1059            fErrorReporter.reportError(fErrorReporter.getLocator(),
1060                                       XMLMessages.XML_DOMAIN,
1061                                       XMLMessages.MSG_TWO_COLONS_IN_QNAME,
1062                                       XMLMessages.P5_INVALID_CHARACTER,
1063                                       null,
1064                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
1065            entityReader.skipPastNmtoken(' ');
1066         }
1067      }
1068
1069   } // scanElementType(XMLEntityHandler.EntityReader,char,QName)
1070

1071   /** Scans expected element type. */
1072   public boolean scanExpectedElementType(XMLEntityHandler.EntityReader entityReader,
1073                                          char fastchar, QName element)
1074   throws Exception JavaDoc {
1075
1076      if (fCurrentElementCharArrayRange == null) {
1077         fCurrentElementCharArrayRange = fStringPool.createCharArrayRange();
1078      }
1079      fStringPool.getCharArrayRange(fCurrentElement.rawname, fCurrentElementCharArrayRange);
1080      return entityReader.scanExpectedName(fastchar, fCurrentElementCharArrayRange);
1081
1082   } // scanExpectedElementType(XMLEntityHandler.EntityReader,char,QName)
1083

1084   /** Scans attribute name. */
1085   public void scanAttributeName(XMLEntityHandler.EntityReader entityReader,
1086                                 QName element, QName attribute)
1087   throws Exception JavaDoc {
1088
1089      if (!fSeenRootElement) {
1090         fSeenRootElement = true;
1091         rootElementSpecified(element);
1092         fStringPool.resetShuffleCount();
1093      }
1094
1095      if (!fNamespacesEnabled) {
1096         attribute.clear();
1097         attribute.localpart = entityReader.scanName('=');
1098         attribute.rawname = attribute.localpart;
1099      } else {
1100         entityReader.scanQName('=', attribute);
1101         if (entityReader.lookingAtChar(':', false)) {
1102            fErrorReporter.reportError(fErrorReporter.getLocator(),
1103                                       XMLMessages.XML_DOMAIN,
1104                                       XMLMessages.MSG_TWO_COLONS_IN_QNAME,
1105                                       XMLMessages.P5_INVALID_CHARACTER,
1106                                       null,
1107                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
1108            entityReader.skipPastNmtoken(' ');
1109         }
1110      }
1111
1112   } // scanAttributeName(XMLEntityHandler.EntityReader,QName,QName)
1113

1114   /** Call start document. */
1115   public void callStartDocument() throws Exception JavaDoc {
1116
1117      if (!fCalledStartDocument) {
1118         fDocumentHandler.startDocument();
1119         fCalledStartDocument = true;
1120         if (fValidating) {
1121             fValueStoreCache.startDocument();
1122         }
1123      }
1124   }
1125
1126   /** Call end document. */
1127   public void callEndDocument() throws Exception JavaDoc {
1128
1129      if (fCalledStartDocument) {
1130          if (fValidating) {
1131                if (DEBUG_IDENTITY_CONSTRAINTS) {
1132                    System.out.println("<IC>: ValueStoreCache#endDocument()");
1133                }
1134              fValueStoreCache.endDocument();
1135          }
1136         fDocumentHandler.endDocument();
1137      }
1138   }
1139
1140   /** Call XML declaration. */
1141   public void callXMLDecl(int version, int encoding, int standalone) throws Exception JavaDoc {
1142      fDocumentHandler.xmlDecl(version, encoding, standalone);
1143   }
1144   public void callStandaloneIsYes() throws Exception JavaDoc {
1145      // standalone = "yes". said XMLDocumentScanner.
1146
fStandaloneReader = fEntityHandler.getReaderId() ;
1147
1148   }
1149
1150
1151
1152   /** Call text declaration. */
1153   public void callTextDecl(int version, int encoding) throws Exception JavaDoc {
1154      fDocumentHandler.textDecl(version, encoding);
1155   }
1156
1157   /**
1158    * Signal the scanning of an element name in a start element tag.
1159    *
1160    * @param element Element name scanned.
1161    */

1162   public void element(QName element) throws Exception JavaDoc {
1163      fAttrListHandle = -1;
1164   }
1165   /**
1166    * Signal the scanning of an attribute associated to the previous
1167    * start element tag.
1168    *
1169    * @param element Element name scanned.
1170    * @param attrName Attribute name scanned.
1171    * @param attrValue The string pool index of the attribute value.
1172    */

1173   public boolean attribute(QName element, QName attrName, int attrValue) throws Exception JavaDoc {
1174      if (fAttrListHandle == -1) {
1175         fAttrListHandle = fAttrList.startAttrList();
1176      }
1177
1178      // if fAttrList.addAttr returns -1, indicates duplicate att in start tag of an element.
1179
// specified: true, search : true
1180
return fAttrList.addAttr(attrName, attrValue, fCDATASymbol, true, true) == -1;
1181   }
1182
1183   /** Call start element. */
1184   public void callStartElement(QName element) throws Exception JavaDoc {
1185
1186      if ( DEBUG_SCHEMA_VALIDATION )
1187         System.out.println("\n=======StartElement : " + fStringPool.toString(element.localpart));
1188
1189
1190      //
1191
// Check after all specified attrs are scanned
1192
// (1) report error for REQUIRED attrs that are missing (V_TAGc)
1193
// (2) report error for PROHIBITED attrs that are present (V_TAGc)
1194
// (3) add default attrs (FIXED and NOT_FIXED)
1195
//
1196

1197      if (!fSeenRootElement) {
1198         rootElementSpecified(element);
1199         fStringPool.resetShuffleCount();
1200      }
1201
1202      if (fGrammar != null && fGrammarIsDTDGrammar) {
1203         fAttrListHandle = addDTDDefaultAttributes(element, fAttrList, fAttrListHandle, fValidating, fStandaloneReader != -1);
1204      }
1205
1206      fCheckedForSchema = true;
1207      if (fNamespacesEnabled) {
1208         bindNamespacesToElementAndAttributes(element, fAttrList);
1209      }
1210
1211      if (fDynamicValidation && fGrammar==null) {
1212         fValidating = false;
1213      }
1214
1215      if (!fSeenRootElement) {
1216          fSeenRootElement = true;
1217      }
1218
1219      validateElementAndAttributes(element, fAttrList);
1220      if (fAttrListHandle != -1) {
1221         //fAttrList.endAttrList();
1222
int dupAttrs[];
1223         if ((dupAttrs = fAttrList.endAttrList()) != null) {
1224            Object JavaDoc[] args = {fStringPool.toString(element.rawname), null};
1225            for (int i = 0; i < dupAttrs.length; i++) {
1226                args[1] = fStringPool.toString(dupAttrs[i]);
1227                fErrorReporter.reportError(fErrorReporter.getLocator(),
1228                                           XMLMessages.XMLNS_DOMAIN,
1229                                           XMLMessages.MSG_ATTRIBUTE_NOT_UNIQUE,
1230                                           XMLMessages.WFC_UNIQUE_ATT_SPEC,
1231                                           args,
1232                                           XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1233            }
1234         }
1235      }
1236
1237      // activate identity constraints
1238
if (fValidating && fGrammar != null && fGrammarIsSchemaGrammar) {
1239          if (DEBUG_IDENTITY_CONSTRAINTS) {
1240              System.out.println("<IC>: pushing context - element: "+fStringPool.toString(element.rawname));
1241          }
1242          fValueStoreCache.startElement();
1243          fMatcherStack.pushContext();
1244          int eindex = fGrammar.getElementDeclIndex(element, -1);
1245          if (eindex != -1) {
1246              fGrammar.getElementDecl(eindex, fTempElementDecl);
1247              fValueStoreCache.initValueStoresFor(fTempElementDecl);
1248              int uCount = fTempElementDecl.unique.size();
1249              for (int i = 0; i < uCount; i++) {
1250                  activateSelectorFor((IdentityConstraint)fTempElementDecl.unique.elementAt(i));
1251              }
1252              int kCount = fTempElementDecl.key.size();
1253              for (int i = 0; i < kCount; i++) {
1254                  activateSelectorFor((IdentityConstraint)fTempElementDecl.key.elementAt(i));
1255              }
1256              int krCount = fTempElementDecl.keyRef.size();
1257              for (int i = 0; i < krCount; i++) {
1258                  activateSelectorFor((IdentityConstraint)fTempElementDecl.keyRef.elementAt(i));
1259              }
1260          }
1261
1262          // call all active identity constraints
1263
int count = fMatcherStack.getMatcherCount();
1264          for (int i = 0; i < count; i++) {
1265              XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
1266              if (DEBUG_IDENTITY_CONSTRAINTS) {
1267                  System.out.println("<IC>: "+matcher.toString()+"#startElement("+fStringPool.toString(element.rawname)+")");
1268              }
1269              matcher.startElement(element, fAttrList, fAttrListHandle, fCurrentElementIndex, (SchemaGrammar)fGrammar);
1270          }
1271      }
1272
1273      // call handler
1274
fDocumentHandler.startElement(element, fAttrList, fAttrListHandle);
1275      fElementDepth++;
1276      fAttrListHandle = -1;
1277
1278      //if (fElementDepth >= 0) {
1279
// REVISIT: Why are doing anything if the grammar is null? -Ac
1280
if (fValidating) {
1281         // push current length onto stack
1282
if (fElementChildrenOffsetStack.length <= fElementDepth) {
1283            int newarray[] = new int[fElementChildrenOffsetStack.length * 2];
1284            System.arraycopy(fElementChildrenOffsetStack, 0, newarray, 0, fElementChildrenOffsetStack.length);
1285            fElementChildrenOffsetStack = newarray;
1286         }
1287         fElementChildrenOffsetStack[fElementDepth] = fElementChildrenLength;
1288
1289         // add this element to children
1290
if (fElementChildren.length <= fElementChildrenLength) {
1291            QName[] newarray = new QName[fElementChildrenLength * 2];
1292            System.arraycopy(fElementChildren, 0, newarray, 0, fElementChildren.length);
1293            fElementChildren = newarray;
1294         }
1295         QName qname = fElementChildren[fElementChildrenLength];
1296         if (qname == null) {
1297            for (int i = fElementChildrenLength; i < fElementChildren.length; i++) {
1298               fElementChildren[i] = new QName();
1299            }
1300            qname = fElementChildren[fElementChildrenLength];
1301         }
1302         qname.setValues(element);
1303         fElementChildrenLength++;
1304
1305         if (DEBUG_ELEMENT_CHILDREN) {
1306            printChildren();
1307            printStack();
1308         }
1309
1310      }
1311
1312      ensureStackCapacity(fElementDepth);
1313      fCurrentElement.setValues(element);
1314      fCurrentElementEntity = fEntityHandler.getReaderId();
1315
1316      fElementQNamePartsStack[fElementDepth].setValues(fCurrentElement);
1317
1318      fElementEntityStack[fElementDepth] = fCurrentElementEntity;
1319      fElementIndexStack[fElementDepth] = fCurrentElementIndex;
1320      fContentSpecTypeStack[fElementDepth] = fCurrentContentSpecType;
1321
1322      if (fNeedValidationOff) {
1323         fValidating = false;
1324         fNeedValidationOff = false;
1325      }
1326
1327      if (fValidating && fGrammarIsSchemaGrammar) {
1328         pushContentLeafStack();
1329      } else {
1330        fContentModelStateStack[fElementDepth] = -2;
1331      }
1332
1333      fValidationFlagStack[fElementDepth] = fValidating ? 0 : -1;
1334
1335      fScopeStack[fElementDepth] = fCurrentScope;
1336      fGrammarNameSpaceIndexStack[fElementDepth] = fGrammarNameSpaceIndex;
1337
1338    } // callStartElement(QName)
1339

1340    private void activateSelectorFor(IdentityConstraint ic) throws Exception JavaDoc {
1341        Selector selector = ic.getSelector();
1342        if (DEBUG_IDENTITY_CONSTRAINTS) {
1343            System.out.println("<IC>: XMLValidator#activateSelectorFor("+selector+')');
1344        }
1345        FieldActivator activator = this;
1346        if(selector == null)
1347            return;
1348        XPathMatcher matcher = selector.createMatcher(activator);
1349        fMatcherStack.addMatcher(matcher);
1350        if (DEBUG_IDENTITY_CONSTRAINTS) {
1351            System.out.println("<IC>: "+matcher+"#startDocumentFragment()");
1352        }
1353        matcher.startDocumentFragment(fStringPool);
1354    }
1355
1356   private void pushContentLeafStack() throws Exception JavaDoc {
1357      int contentType = getContentSpecType(fCurrentElementIndex);
1358      if ( contentType == XMLElementDecl.TYPE_CHILDREN ||
1359           contentType == XMLElementDecl.TYPE_MIXED_COMPLEX) {
1360         XMLContentModel cm = getElementContentModel(fCurrentElementIndex);
1361         ContentLeafNameTypeVector cv = cm.getContentLeafNameTypeVector();
1362         if (cm != null) {
1363            fContentLeafStack[fElementDepth] = cv;
1364            //OTWI: on-the-way-in
1365
fContentModelStack[fElementDepth] = cm;
1366            // for DFA with wildcard, we validate on-the-way-in
1367
// for other content models, we do it on-the-way-out
1368
if (cm instanceof DFAContentModel && cv != null)
1369                fContentModelStateStack[fElementDepth] = 0;
1370            else
1371                fContentModelStateStack[fElementDepth] = -2;
1372            fContentModelEleCount[fElementDepth] = 0;
1373         }
1374      } else {
1375        fContentModelStateStack[fElementDepth] = -2;
1376      }
1377   }
1378
1379   private void ensureStackCapacity ( int newElementDepth) {
1380
1381      if (newElementDepth == fElementQNamePartsStack.length ) {
1382         int[] newStack = new int[newElementDepth * 2];
1383         System.arraycopy(fScopeStack, 0, newStack, 0, newElementDepth);
1384         fScopeStack = newStack;
1385
1386         newStack = new int[newElementDepth * 2];
1387         System.arraycopy(fGrammarNameSpaceIndexStack, 0, newStack, 0, newElementDepth);
1388         fGrammarNameSpaceIndexStack = newStack;
1389
1390         QName[] newStackOfQueue = new QName[newElementDepth * 2];
1391         System.arraycopy(this.fElementQNamePartsStack, 0, newStackOfQueue, 0, newElementDepth );
1392         fElementQNamePartsStack = newStackOfQueue;
1393
1394         QName qname = fElementQNamePartsStack[newElementDepth];
1395         if (qname == null) {
1396            for (int i = newElementDepth; i < fElementQNamePartsStack.length; i++) {
1397               fElementQNamePartsStack[i] = new QName();
1398            }
1399         }
1400
1401         newStack = new int[newElementDepth * 2];
1402         System.arraycopy(fElementEntityStack, 0, newStack, 0, newElementDepth);
1403         fElementEntityStack = newStack;
1404
1405         newStack = new int[newElementDepth * 2];
1406         System.arraycopy(fElementIndexStack, 0, newStack, 0, newElementDepth);
1407         fElementIndexStack = newStack;
1408
1409         newStack = new int[newElementDepth * 2];
1410         System.arraycopy(fContentSpecTypeStack, 0, newStack, 0, newElementDepth);
1411         fContentSpecTypeStack = newStack;
1412
1413         newStack = new int[newElementDepth * 2];
1414         System.arraycopy(fValidationFlagStack, 0, newStack, 0, newElementDepth);
1415         fValidationFlagStack = newStack;
1416
1417         ContentLeafNameTypeVector[] newStackV = new ContentLeafNameTypeVector[newElementDepth * 2];
1418         System.arraycopy(fContentLeafStack, 0, newStackV, 0, newElementDepth);
1419         fContentLeafStack = newStackV;
1420
1421         //OTWI: on-the-way-in
1422
XMLContentModel[] newStackCM = new XMLContentModel[newElementDepth * 2];
1423         System.arraycopy(fContentModelStack, 0, newStackCM, 0, newElementDepth);
1424         fContentModelStack = newStackCM;
1425         newStack = new int[newElementDepth * 2];
1426         System.arraycopy(fContentModelStateStack, 0, newStack, 0, newElementDepth);
1427         fContentModelStateStack = newStack;
1428         newStack = new int[newElementDepth * 2];
1429         System.arraycopy(fContentModelEleCount, 0, newStack, 0, newElementDepth);
1430         fContentModelEleCount = newStack;
1431      }
1432   }
1433
1434   /** Call end element. */
1435   public void callEndElement(int readerId) throws Exception JavaDoc {
1436      if ( DEBUG_SCHEMA_VALIDATION )
1437         System.out.println("=======EndElement : " + fStringPool.toString(fCurrentElement.localpart)+"\n");
1438
1439      int prefixIndex = fCurrentElement.prefix;
1440      int elementType = fCurrentElement.rawname;
1441
1442      if (fCurrentElementEntity != readerId) {
1443         fErrorReporter.reportError(fErrorReporter.getLocator(),
1444                                    XMLMessages.XML_DOMAIN,
1445                                    XMLMessages.MSG_ELEMENT_ENTITY_MISMATCH,
1446                                    XMLMessages.P78_NOT_WELLFORMED,
1447                                    new Object JavaDoc[] { fStringPool.toString(elementType)},
1448                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
1449      }
1450
1451      fElementDepth--;
1452      if (fValidating) {
1453         int elementIndex = fCurrentElementIndex;
1454         if (elementIndex != -1 && fCurrentContentSpecType != -1) {
1455            QName children[] = fElementChildren;
1456            int childrenOffset = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
1457            int childrenLength = fElementChildrenLength - childrenOffset;
1458            if (DEBUG_ELEMENT_CHILDREN) {
1459               System.out.println("endElement("+fStringPool.toString(fCurrentElement.rawname)+')');
1460               System.out.println("fCurrentContentSpecType : " + fCurrentContentSpecType );
1461               System.out.print("offset: ");
1462               System.out.print(childrenOffset);
1463               System.out.print(", length: ");
1464               System.out.print(childrenLength);
1465               System.out.println();
1466               printChildren();
1467               printStack();
1468            }
1469            int result = checkContent(elementIndex,
1470                                      children, childrenOffset, childrenLength);
1471            fCurrentDV = null;
1472
1473            if ( DEBUG_SCHEMA_VALIDATION )
1474               System.out.println("!!!!!!!!In XMLValidator, the return value from checkContent : " + result);
1475
1476            if (result != -1) {
1477               int majorCode = result != childrenLength ? XMLMessages.MSG_CONTENT_INVALID : XMLMessages.MSG_CONTENT_INCOMPLETE;
1478               fGrammar.getElementDecl(elementIndex, fTempElementDecl);
1479               if (fTempElementDecl.type == XMLElementDecl.TYPE_EMPTY) {
1480                  reportRecoverableXMLError(majorCode,
1481                                            0,
1482                                            fStringPool.toString(elementType),
1483                                            "EMPTY");
1484               } else
1485                  reportRecoverableXMLError(majorCode,
1486                                            0,
1487                                            fStringPool.toString(elementType),
1488                                            XMLContentSpec.toString(fGrammar, fStringPool, fTempElementDecl.contentSpecIndex));
1489            }
1490         }
1491         fElementChildrenLength = fElementChildrenOffsetStack[fElementDepth + 1] + 1;
1492
1493         // call matchers and de-activate context
1494
if(fGrammarIsSchemaGrammar) {
1495            int oldCount = fMatcherStack.getMatcherCount();
1496            for (int i = oldCount - 1; i >= 0; i--) {
1497                XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
1498                if (DEBUG_IDENTITY_CONSTRAINTS) {
1499                    System.out.println("<IC>: "+matcher+"#endElement("+fStringPool.toString(fCurrentElement.rawname)+")");
1500                }
1501                matcher.endElement(fCurrentElement, fCurrentElementIndex, (SchemaGrammar)fGrammar);
1502            }
1503            if (DEBUG_IDENTITY_CONSTRAINTS) {
1504                System.out.println("<IC>: popping context - element: "+fStringPool.toString(fCurrentElement.rawname));
1505            }
1506            if (fMatcherStack.size() > 0) {
1507                fMatcherStack.popContext();
1508            }
1509            int newCount = fMatcherStack.getMatcherCount();
1510            // handle everything *but* keyref's.
1511
for (int i = oldCount - 1; i >= newCount; i--) {
1512                XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
1513                IdentityConstraint id;
1514                if((id = matcher.getIDConstraint()) != null && id.getType() != IdentityConstraint.KEYREF) {
1515                    if (DEBUG_IDENTITY_CONSTRAINTS) {
1516                        System.out.println("<IC>: "+matcher+"#endDocumentFragment()");
1517                    }
1518                    matcher.endDocumentFragment();
1519                    fValueStoreCache.transplant(id);
1520                } else if (id == null)
1521                    matcher.endDocumentFragment();
1522            }
1523            // now handle keyref's/...
1524
for (int i = oldCount - 1; i >= newCount; i--) {
1525                XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
1526                IdentityConstraint id;
1527                if((id = matcher.getIDConstraint()) != null && id.getType() == IdentityConstraint.KEYREF) {
1528                    if (DEBUG_IDENTITY_CONSTRAINTS) {
1529                        System.out.println("<IC>: "+matcher+"#endDocumentFragment()");
1530                    }
1531                    ValueStoreBase values = fValueStoreCache.getValueStoreFor(id);
1532                    if(values != null) // nothing to do if nothing matched!
1533
values.endDocumentFragment();
1534                    matcher.endDocumentFragment();
1535                }
1536            }
1537            fValueStoreCache.endElement();
1538        }
1539      }
1540      fDocumentHandler.endElement(fCurrentElement);
1541      if (fNamespacesEnabled) {
1542         fNamespacesScope.decreaseDepth();
1543      }
1544
1545      // now pop this element off the top of the element stack
1546
//if (fElementDepth-- < 0) {
1547
if (fElementDepth < -1) {
1548         throw new RuntimeException JavaDoc("FWK008 Element stack underflow");
1549      }
1550      if (fElementDepth < 0) {
1551         fCurrentElement.clear();
1552         fCurrentElementEntity = -1;
1553         fCurrentElementIndex = -1;
1554         fCurrentContentSpecType = -1;
1555         fInElementContent = false;
1556         //
1557
// Check after document is fully parsed
1558
// (1) check that there was an element with a matching id for every
1559
// IDREF and IDREFS attr (V_IDREF0)
1560
//
1561
if (fValidating ) {
1562            try {
1563                this.fValIDRef.validate( null, this.fCheckIDRef ); //Do final IDREF validation round
1564
this.fIdDefs.clear();
1565                this.fIdREFDefs.clear();
1566            } catch ( InvalidDatatypeValueException ex ) {
1567               reportRecoverableXMLError( ex.getMajorCode(), ex.getMinorCode(),
1568                                          ex.getMessage() );
1569            }
1570         }
1571         return;
1572      }
1573
1574
1575      //restore enclosing element to all the "current" variables
1576
// REVISIT: Validation. This information needs to be stored.
1577
fCurrentElement.prefix = -1;
1578
1579
1580      if (fNamespacesEnabled) { //If Namespace enable then localName != rawName
1581
fCurrentElement.localpart = fElementQNamePartsStack[fElementDepth].localpart;
1582      } else {//REVISIT - jeffreyr - This is so we still do old behavior when namespace is off
1583
fCurrentElement.localpart = fElementQNamePartsStack[fElementDepth].rawname;
1584      }
1585      fCurrentElement.rawname = fElementQNamePartsStack[fElementDepth].rawname;
1586      fCurrentElement.uri = fElementQNamePartsStack[fElementDepth].uri;
1587      fCurrentElement.prefix = fElementQNamePartsStack[fElementDepth].prefix;
1588
1589
1590      fCurrentElementEntity = fElementEntityStack[fElementDepth];
1591      fCurrentElementIndex = fElementIndexStack[fElementDepth];
1592      fCurrentContentSpecType = fContentSpecTypeStack[fElementDepth];
1593
1594      fValidating = fValidationFlagStack[fElementDepth] == 0 ? true : false;
1595
1596      fCurrentScope = fScopeStack[fElementDepth];
1597
1598      if ( DEBUG_SCHEMA_VALIDATION ) {
1599
1600        System.out.println("+++++ currentElement : " + fStringPool.toString(elementType)+
1601                   "\n fCurrentElementIndex : " + fCurrentElementIndex +
1602                   "\n fCurrentScope : " + fCurrentScope +
1603                   "\n fCurrentContentSpecType : " + fCurrentContentSpecType +
1604                   "\n++++++++++++++++++++++++++++++++++++++++++++++++" );
1605      }
1606
1607      // if enclosing element's Schema is different, need to switch "context"
1608
if ( fGrammarNameSpaceIndex != fGrammarNameSpaceIndexStack[fElementDepth] ) {
1609
1610         fGrammarNameSpaceIndex = fGrammarNameSpaceIndexStack[fElementDepth];
1611         if ( fValidating && fGrammarIsSchemaGrammar )
1612             if (fGrammarNameSpaceIndex < StringPool.EMPTY_STRING) {
1613                 fGrammar = null;
1614                 fGrammarIsSchemaGrammar = false;
1615                 fGrammarIsDTDGrammar = false;
1616                } else if (!switchGrammar(fGrammarNameSpaceIndex)) {
1617                     reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR, XMLMessages.SCHEMA_GENERIC_ERROR,
1618                                               "Grammar with uri: " + fStringPool.toString(fGrammarNameSpaceIndex)
1619                                               + " , can not be found; possible mismatch between instance document's namespace and that of schema");
1620             }
1621      }
1622
1623      if (fValidating) {
1624         fBufferDatatype = false;
1625      }
1626      fInElementContent = (fCurrentContentSpecType == XMLElementDecl.TYPE_CHILDREN);
1627
1628   } // callEndElement(int)
1629

1630   /** Call start CDATA section. */
1631   public void callStartCDATA() throws Exception JavaDoc {
1632      if (fValidating && fInElementContent) {
1633         charDataInContent();
1634      }
1635      fDocumentHandler.startCDATA();
1636   }
1637
1638   /** Call end CDATA section. */
1639   public void callEndCDATA() throws Exception JavaDoc {
1640      fDocumentHandler.endCDATA();
1641   }
1642
1643   /** Call characters. */
1644   public void callCharacters(int ch) throws Exception JavaDoc {
1645
1646      if (fCharRefData == null) {
1647         fCharRefData = new char[2];
1648      }
1649      int count = (ch < 0x10000) ? 1 : 2;
1650      if (count == 1) {
1651         fCharRefData[0] = (char)ch;
1652      } else {
1653         fCharRefData[0] = (char)(((ch-0x00010000)>>10)+0xd800);
1654         fCharRefData[1] = (char)(((ch-0x00010000)&0x3ff)+0xdc00);
1655      }
1656      if (fValidating && (fInElementContent || fCurrentContentSpecType == XMLElementDecl.TYPE_EMPTY)) {
1657         charDataInContent();
1658      }
1659      if (fValidating) {
1660         if (fBufferDatatype) {
1661            fDatatypeBuffer.append(fCharRefData,0,1);
1662         }
1663      }
1664
1665      // call all active identity constraints
1666
int matcherCount = fMatcherStack.getMatcherCount();
1667      for (int i = 0; i < matcherCount; i++) {
1668          XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
1669          if (DEBUG_IDENTITY_CONSTRAINTS) {
1670              String JavaDoc text = new String JavaDoc(fCharRefData, 0, count);
1671              System.out.println("<IC>: "+matcher.toString()+"#characters("+text+")");
1672          }
1673          matcher.characters(fCharRefData, 0, count);
1674      }
1675
1676      if (fSendCharDataAsCharArray) {
1677         fDocumentHandler.characters(fCharRefData, 0, count);
1678      } else {
1679         int index = fStringPool.addString(new String JavaDoc(fCharRefData, 0, count));
1680         fDocumentHandler.characters(index);
1681      }
1682   } // callCharacters(int)
1683

1684   /** Call processing instruction. */
1685   public void callProcessingInstruction(int target, int data) throws Exception JavaDoc {
1686      fDocumentHandler.processingInstruction(target, data);
1687   }
1688
1689   /** Call comment. */
1690   public void callComment(int comment) throws Exception JavaDoc {
1691      fDocumentHandler.comment(comment);
1692   }
1693
1694   //
1695
// NamespacesScope.NamespacesHandler methods
1696
//
1697

1698   /** Start a new namespace declaration scope. */
1699   public void startNamespaceDeclScope(int prefix, int uri) throws Exception JavaDoc {
1700      fDocumentHandler.startNamespaceDeclScope(prefix, uri);
1701   }
1702
1703   /** End a namespace declaration scope. */
1704   public void endNamespaceDeclScope(int prefix) throws Exception JavaDoc {
1705      fDocumentHandler.endNamespaceDeclScope(prefix);
1706   }
1707
1708   // attributes
1709

1710
1711   // other
1712

1713   /** Sets the root element. */
1714   public void setRootElementType(QName rootElement) {
1715      fRootElement.setValues(rootElement);
1716   }
1717
1718   /**
1719    * Returns true if the element declaration is external.
1720    * <p>
1721    * <strong>Note:</strong> This method is primarilly useful for
1722    * DTDs with internal and external subsets.
1723    */

1724   private boolean getElementDeclIsExternal(int elementIndex) {
1725      /*if (elementIndex < 0 || elementIndex >= fElementCount) {
1726          return false;
1727      }
1728      int chunk = elementIndex >> CHUNK_SHIFT;
1729      int index = elementIndex & CHUNK_MASK;
1730      return (fElementDeclIsExternal[chunk][index] != 0);
1731      */

1732
1733      if (fGrammarIsDTDGrammar ) {
1734         return((DTDGrammar) fGrammar).getElementDeclIsExternal(elementIndex);
1735      }
1736      return false;
1737   }
1738
1739   /** Returns the content spec type for an element index. */
1740   public int getContentSpecType(int elementIndex) {
1741
1742      int contentSpecType = -1;
1743      if ( elementIndex > -1) {
1744         if ( fGrammar.getElementDecl(elementIndex,fTempElementDecl) ) {
1745            contentSpecType = fTempElementDecl.type;
1746         }
1747      }
1748      return contentSpecType;
1749   }
1750
1751   /** Returns the content spec handle for an element index. */
1752   public int getContentSpecHandle(int elementIndex) {
1753      int contentSpecHandle = -1;
1754      if ( elementIndex > -1) {
1755         if ( fGrammar.getElementDecl(elementIndex,fTempElementDecl) ) {
1756            contentSpecHandle = fTempElementDecl.contentSpecIndex;
1757         }
1758      }
1759      return contentSpecHandle;
1760   }
1761
1762   //
1763
// Protected methods
1764
//
1765

1766   // error reporting
1767

1768   /** Report a recoverable schema error. */
1769   private void reportSchemaError(int code, Object JavaDoc[] args) throws Exception JavaDoc {
1770       fErrorReporter.reportError(fErrorReporter.getLocator(),
1771                                  SchemaMessageProvider.SCHEMA_DOMAIN,
1772                                  code,
1773                                  SchemaMessageProvider.MSG_NONE,
1774                                  args,
1775                                  XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1776   } // reportSchemaError(int,Object)
1777

1778   /** Report a recoverable xml error. */
1779   protected void reportRecoverableXMLError(int majorCode, int minorCode)
1780   throws Exception JavaDoc {
1781
1782      fErrorReporter.reportError(fErrorReporter.getLocator(),
1783                                 XMLMessages.XML_DOMAIN,
1784                                 majorCode,
1785                                 minorCode,
1786                                 null,
1787                                 XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1788
1789   } // reportRecoverableXMLError(int,int)
1790

1791   /** Report a recoverable xml error. */
1792   protected void reportRecoverableXMLError(int majorCode, int minorCode,
1793                                            int stringIndex1)
1794   throws Exception JavaDoc {
1795
1796      Object JavaDoc[] args = { fStringPool.toString(stringIndex1)};
1797      fErrorReporter.reportError(fErrorReporter.getLocator(),
1798                                 XMLMessages.XML_DOMAIN,
1799                                 majorCode,
1800                                 minorCode,
1801                                 args,
1802                                 XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1803
1804   } // reportRecoverableXMLError(int,int,int)
1805

1806   /** Report a recoverable xml error. */
1807   protected void reportRecoverableXMLError(int majorCode, int minorCode,
1808                                            String JavaDoc string1) throws Exception JavaDoc {
1809
1810      Object JavaDoc[] args = { string1};
1811      fErrorReporter.reportError(fErrorReporter.getLocator(),
1812                                 XMLMessages.XML_DOMAIN,
1813                                 majorCode,
1814                                 minorCode,
1815                                 args,
1816                                 XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1817
1818   } // reportRecoverableXMLError(int,int,String)
1819

1820   /** Report a recoverable xml error. */
1821   protected void reportRecoverableXMLError(int majorCode, int minorCode,
1822                                            int stringIndex1, int stringIndex2)
1823   throws Exception JavaDoc {
1824
1825      Object JavaDoc[] args = { fStringPool.toString(stringIndex1), fStringPool.toString(stringIndex2)};
1826      fErrorReporter.reportError(fErrorReporter.getLocator(),
1827                                 XMLMessages.XML_DOMAIN,
1828                                 majorCode,
1829                                 minorCode,
1830                                 args,
1831                                 XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1832
1833   } // reportRecoverableXMLError(int,int,int,int)
1834

1835   /** Report a recoverable xml error. */
1836   protected void reportRecoverableXMLError(int majorCode, int minorCode,
1837                                            String JavaDoc string1, String JavaDoc string2)
1838   throws Exception JavaDoc {
1839
1840      Object JavaDoc[] args = { string1, string2};
1841      fErrorReporter.reportError(fErrorReporter.getLocator(),
1842                                 XMLMessages.XML_DOMAIN,
1843                                 majorCode,
1844                                 minorCode,
1845                                 args,
1846                                 XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1847
1848   } // reportRecoverableXMLError(int,int,String,String)
1849

1850   /** Report a recoverable xml error. */
1851   protected void reportRecoverableXMLError(int majorCode, int minorCode,
1852                                            String JavaDoc string1, String JavaDoc string2,
1853                                            String JavaDoc string3) throws Exception JavaDoc {
1854
1855      Object JavaDoc[] args = { string1, string2, string3};
1856      fErrorReporter.reportError(fErrorReporter.getLocator(),
1857                                 XMLMessages.XML_DOMAIN,
1858                                 majorCode,
1859                                 minorCode,
1860                                 args,
1861                                 XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
1862
1863   } // reportRecoverableXMLError(int,int,String,String,String)
1864

1865   // content spec
1866

1867   /**
1868    * Returns information about which elements can be placed at a particular point
1869    * in the passed element's content model.
1870    * <p>
1871    * Note that the incoming content model to test must be valid at least up to
1872    * the insertion point. If not, then -1 will be returned and the info object
1873    * will not have been filled in.
1874    * <p>
1875    * If, on return, the info.isValidEOC flag is set, then the 'insert after'
1876    * elemement is a valid end of content, i.e. nothing needs to be inserted
1877    * after it to make the parent element's content model valid.
1878    *
1879    * @param elementIndex The index within the <code>ElementDeclPool</code> of the
1880    * element which is being querying.
1881    * @param fullyValid Only return elements that can be inserted and still
1882    * maintain the validity of subsequent elements past the
1883    * insertion point (if any). If the insertion point is at
1884    * the end, and this is true, then only elements that can
1885    * be legal final states will be returned.
1886    * @param info An object that contains the required input data for the method,
1887    * and which will contain the output information if successful.
1888    *
1889    * @return The value -1 if fully valid, else the 0 based index of the child
1890    * that first failed before the insertion point. If the value
1891    * returned is equal to the number of children, then the specified
1892    * children are valid but additional content is required to reach a
1893    * valid ending state.
1894    *
1895    * @exception Exception Thrown on error.
1896    *
1897    * @see InsertableElementsInfo
1898    */

1899   protected int whatCanGoHere(int elementIndex, boolean fullyValid,
1900                               InsertableElementsInfo info) throws Exception JavaDoc {
1901
1902      //
1903
// Do some basic sanity checking on the info packet. First, make sure
1904
// that insertAt is not greater than the child count. It can be equal,
1905
// which means to get appendable elements, but not greater. Or, if
1906
// the current children array is null, that's bad too.
1907
//
1908
// Since the current children array must have a blank spot for where
1909
// the insert is going to be, the child count must always be at least
1910
// one.
1911
//
1912
// Make sure that the child count is not larger than the current children
1913
// array. It can be equal, which means get appendable elements, but not
1914
// greater.
1915
//
1916
if (info.insertAt > info.childCount || info.curChildren == null ||
1917          info.childCount < 1 || info.childCount > info.curChildren.length) {
1918         fErrorReporter.reportError(fErrorReporter.getLocator(),
1919                                    ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
1920                                    ImplementationMessages.VAL_WCGHI,
1921                                    0,
1922                                    null,
1923                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
1924      }
1925
1926      int retVal = 0;
1927      try {
1928         // Get the content model for this element
1929
final XMLContentModel cmElem = getElementContentModel(elementIndex);
1930
1931         // And delegate this call to it
1932
retVal = cmElem.whatCanGoHere(fullyValid, info);
1933      } catch (CMException excToCatch) {
1934         // REVISIT - Translate caught error to the protected error handler interface
1935
int majorCode = excToCatch.getErrorCode();
1936         fErrorReporter.reportError(fErrorReporter.getLocator(),
1937                                    ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
1938                                    majorCode,
1939                                    0,
1940                                    null,
1941                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
1942         throw excToCatch;
1943      }
1944      return retVal;
1945
1946   } // whatCanGoHere(int,boolean,InsertableElementsInfo):int
1947

1948   // attribute information
1949

1950   /** Protected for use by AttributeValidator classes. */
1951   protected boolean getAttDefIsExternal(QName element, QName attribute) {
1952      int attDefIndex = getAttDef(element, attribute);
1953      if (fGrammarIsDTDGrammar ) {
1954         return((DTDGrammar) fGrammar).getAttributeDeclIsExternal(attDefIndex);
1955      }
1956      return false;
1957   }
1958
1959
1960
1961   //
1962
// Private methods
1963
//
1964

1965   // other
1966

1967   /** Returns true if using a standalone reader. */
1968   private boolean usingStandaloneReader() {
1969      return fStandaloneReader == -1 || fEntityHandler.getReaderId() == fStandaloneReader;
1970   }
1971
1972   /** Returns a locator implementation. */
1973   private LocatorImpl JavaDoc getLocatorImpl(LocatorImpl JavaDoc fillin) {
1974
1975      Locator JavaDoc here = fErrorReporter.getLocator();
1976      if (fillin == null)
1977         return new LocatorImpl JavaDoc(here);
1978      fillin.setPublicId(here.getPublicId());
1979      fillin.setSystemId(here.getSystemId());
1980      fillin.setLineNumber(here.getLineNumber());
1981      fillin.setColumnNumber(here.getColumnNumber());
1982      return fillin;
1983
1984   } // getLocatorImpl(LocatorImpl):LocatorImpl
1985

1986
1987   // initialization
1988

1989   /** Reset pool. */
1990   private void poolReset() {
1991        if (fValidating) { // - el
1992
this.fIdDefs.clear();
1993            this.fIdREFDefs.clear();
1994        }
1995   } // poolReset()
1996

1997   /** Reset common. */
1998   private void resetCommon(StringPool stringPool) throws Exception JavaDoc {
1999
2000      fStringPool = stringPool;
2001      fValidateEntity.setDatatypeObject(new Object JavaDoc[]{fEntityHandler, stringPool});
2002      fValidating = fValidationEnabled;
2003      fValidationEnabledByDynamic = false;
2004      fDynamicDisabledByValidation = false;
2005      fNormalizeContents = false;
2006      poolReset();
2007      fCalledStartDocument = false;
2008      fStandaloneReader = -1;
2009      fElementChildrenLength = 0;
2010      fElementDepth = -1;
2011      fSeenRootElement = false;
2012      fSeenDoctypeDecl = false;
2013      fNamespacesScope = null;
2014      fNamespacesPrefix = -1;
2015      fRootElement.clear();
2016      fAttrListHandle = -1;
2017      fCheckedForSchema = false;
2018
2019      fCurrentScope = TOP_LEVEL_SCOPE;
2020      fCurrentSchemaURI = StringPool.EMPTY_STRING;
2021      fEmptyURI = StringPool.EMPTY_STRING;
2022      fXsiPrefix = - 1;
2023      fXsiTypeValidator = null;
2024
2025      // xsi:nill
2026
fNil = false;
2027
2028      fGrammar = null;
2029      fGrammarNameSpaceIndex = StringPool.EMPTY_STRING;
2030
2031      // we reset fGrammarResolver in XMLParser before passing it to Validator
2032
fSGComparator = null;
2033      fGrammarIsDTDGrammar = false;
2034      fGrammarIsSchemaGrammar = false;
2035
2036      //Normalization
2037
fCurrentDV = null;
2038      fFirstChunk = true;
2039      fTrailing = false;
2040      fWhiteSpace = DatatypeValidator.COLLAPSE;
2041
2042      fMatcherStack.clear();
2043
2044      UPACheckedGrammarURIs.clear();
2045      //REVISIT: fExternalSchemas/fExternalNoNamespaceSchema is not reset 'cause we don't have grammar cashing in Xerces-J
2046
// reconsider implementation when we have grammar chashing
2047
//
2048
init();
2049
2050   } // resetCommon(StringPool)
2051

2052   /** Initialize. */
2053   private void init() {
2054
2055      fEmptyURI = fStringPool.addSymbol("");
2056      fXsiURI = fStringPool.addSymbol(SchemaSymbols.URI_XSI);
2057
2058      fEMPTYSymbol = fStringPool.addSymbol("EMPTY");
2059      fANYSymbol = fStringPool.addSymbol("ANY");
2060      fMIXEDSymbol = fStringPool.addSymbol("MIXED");
2061      fCHILDRENSymbol = fStringPool.addSymbol("CHILDREN");
2062
2063      fCDATASymbol = fStringPool.addSymbol("CDATA");
2064      fIDSymbol = fStringPool.addSymbol("ID");
2065      fIDREFSymbol = fStringPool.addSymbol("IDREF");
2066      fIDREFSSymbol = fStringPool.addSymbol("IDREFS");
2067      fENTITYSymbol = fStringPool.addSymbol("ENTITY");
2068      fENTITIESSymbol = fStringPool.addSymbol("ENTITIES");
2069      fNMTOKENSymbol = fStringPool.addSymbol("NMTOKEN");
2070      fNMTOKENSSymbol = fStringPool.addSymbol("NMTOKENS");
2071      fNOTATIONSymbol = fStringPool.addSymbol("NOTATION");
2072      fENUMERATIONSymbol = fStringPool.addSymbol("ENUMERATION");
2073      fREQUIREDSymbol = fStringPool.addSymbol("#REQUIRED");
2074      fFIXEDSymbol = fStringPool.addSymbol("#FIXED");
2075      fDATATYPESymbol = fStringPool.addSymbol("<<datatype>>");
2076      fEpsilonIndex = fStringPool.addSymbol("<<CMNODE_EPSILON>>");
2077      fXMLLang = fStringPool.addSymbol("xml:lang");
2078
2079   } // init()
2080

2081    /**
2082    * This method should only be invoked when validation
2083    * is turn on.
2084    * fDataTypeReg object of type DatatypeValidatorFactoryImpl
2085    * needs to be initialized.
2086    * In the XMLValidator the table will be by default
2087    * first initialized to 9 validators used by DTD
2088    * validation.
2089    * These Validators are known.
2090    * Later on if we ever find a Schema and need to do
2091    * Schema validation then we will expand this
2092    * registry table of fDataTypeReg.
2093    */

2094   private void initDataTypeValidators() {
2095
2096       if ( fGrammarResolver != null ) {
2097           fDataTypeReg = (DatatypeValidatorFactoryImpl) fGrammarResolver.getDatatypeRegistry();
2098           fDataTypeReg.initializeDTDRegistry();
2099        }
2100       if ( fDataTypeReg != null ) {
2101            fValID = fDataTypeReg.getDatatypeValidator("ID" );
2102            fValIDRef = fDataTypeReg.getDatatypeValidator("IDREF" );
2103            fValIDRefs = fDataTypeReg.getDatatypeValidator("IDREFS" );
2104            fValENTITY = fDataTypeReg.getDatatypeValidator("ENTITY" );
2105            fValENTITIES = fDataTypeReg.getDatatypeValidator("ENTITIES" );
2106            fValNMTOKEN = fDataTypeReg.getDatatypeValidator("NMTOKEN");
2107            fValNMTOKENS = fDataTypeReg.getDatatypeValidator("NMTOKENS");
2108            fValNOTATION = fDataTypeReg.getDatatypeValidator("NOTATION" );
2109       }
2110   }
2111
2112   // other
2113

2114   // default attribute
2115

2116   /** addDefaultAttributes. */
2117   private int addDefaultAttributes(int elementIndex, XMLAttrList attrList, int attrIndex, boolean validationEnabled, boolean standalone) throws Exception JavaDoc {
2118
2119      //System.out.println("XMLValidator#addDefaultAttributes");
2120
//System.out.print(" ");
2121
//fGrammar.printAttributes(elementIndex);
2122

2123      //
2124
// Check after all specified attrs are scanned
2125
// (1) report error for REQUIRED attrs that are missing (V_TAGc)
2126
// (2) report error for PROHIBITED attrs that are present (V_TAGc)
2127
// (3) check that FIXED attrs have matching value (V_TAGd)
2128
// (4) add default attrs (FIXED and NOT_FIXED)
2129
//
2130
fGrammar.getElementDecl(elementIndex,fTempElementDecl);
2131
2132      int elementNameIndex = fTempElementDecl.name.localpart;
2133      int attlistIndex = fGrammar.getFirstAttributeDeclIndex(elementIndex);
2134      int firstCheck = attrIndex;
2135      int lastCheck = -1;
2136      while (attlistIndex != -1) {
2137         fGrammar.getAttributeDecl(attlistIndex, fTempAttDecl);
2138
2139
2140         int attPrefix = fTempAttDecl.name.prefix;
2141         int attName = fTempAttDecl.name.localpart;
2142         int attType = attributeTypeName(fTempAttDecl);
2143         int attDefType =fTempAttDecl.defaultType;
2144         int attValue = -1 ;
2145         if (fTempAttDecl.defaultValue != null ) {
2146            attValue = fStringPool.addSymbol(fTempAttDecl.defaultValue);
2147         }
2148
2149         boolean specified = false;
2150         boolean required = (attDefType & XMLAttributeDecl.DEFAULT_TYPE_REQUIRED) > 0;
2151         boolean prohibited = (attDefType & XMLAttributeDecl.DEFAULT_TYPE_PROHIBITED) > 0;
2152         boolean fixed = (attDefType & XMLAttributeDecl.DEFAULT_TYPE_FIXED) > 0;
2153
2154         if (firstCheck != -1) {
2155            boolean cdata = attType == fCDATASymbol;
2156            if (!cdata || required || prohibited || attValue != -1) {
2157               int i = attrList.getFirstAttr(firstCheck);
2158               while (i != -1 && (lastCheck == -1 || i <= lastCheck)) {
2159
2160                  if ( (fGrammarIsDTDGrammar && (attrList.getAttrName(i) == fTempAttDecl.name.rawname)) ||
2161                       ( fStringPool.equalNames(attrList.getAttrLocalpart(i), attName)
2162                          && fStringPool.equalNames(attrList.getAttrURI(i), fTempAttDecl.name.uri) ) ) {
2163
2164                    if (prohibited && validationEnabled) {
2165                        Object JavaDoc[] args = { fStringPool.toString(elementNameIndex),
2166                            fStringPool.toString(attName)};
2167                        fErrorReporter.reportError(fErrorReporter.getLocator(),
2168                                SchemaMessageProvider.SCHEMA_DOMAIN,
2169                                SchemaMessageProvider.ProhibitedAttributePresent,
2170                                SchemaMessageProvider.MSG_NONE,
2171                                args,
2172                                XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2173                    }
2174                     specified = true;
2175                     break;
2176                  }
2177                  i = attrList.getNextAttr(i);
2178               }
2179            }
2180         }
2181
2182         if (!specified) {
2183            if (required) {
2184               if (validationEnabled) {
2185                  Object JavaDoc[] args = { fStringPool.toString(elementNameIndex),
2186                     fStringPool.toString(attName)};
2187                  fErrorReporter.reportError(fErrorReporter.getLocator(),
2188                                             XMLMessages.XML_DOMAIN,
2189                                             XMLMessages.MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED,
2190                                             XMLMessages.VC_REQUIRED_ATTRIBUTE,
2191                                             args,
2192                                             XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2193               }
2194            } else if (attValue != -1) {
2195               if (validationEnabled && standalone ) {
2196                  if ( fGrammarIsDTDGrammar
2197                       && ((DTDGrammar) fGrammar).getAttributeDeclIsExternal(attlistIndex) ) {
2198
2199                     Object JavaDoc[] args = { fStringPool.toString(elementNameIndex),
2200                        fStringPool.toString(attName)};
2201                     fErrorReporter.reportError(fErrorReporter.getLocator(),
2202                                                XMLMessages.XML_DOMAIN,
2203                                                XMLMessages.MSG_DEFAULTED_ATTRIBUTE_NOT_SPECIFIED,
2204                                                XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
2205                                                args,
2206                                                XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2207                  }
2208               }
2209               if (validationEnabled) {
2210                   // default value should have been already normalized
2211
validateUsingDV (fTempAttDecl.datatypeValidator,
2212                                    fStringPool.toString(attValue), true);
2213               }
2214               if (attrIndex == -1) {
2215                  attrIndex = attrList.startAttrList();
2216               }
2217               // REVISIT: Validation. What should the prefix be?
2218
fTempQName.setValues(attPrefix, attName, attName, fTempAttDecl.name.uri);
2219               int newAttr = attrList.addAttr(fTempQName,
2220                                              attValue, attType,
2221                                              false, false);
2222               if (lastCheck == -1) {
2223                  lastCheck = newAttr;
2224               }
2225            }
2226         }
2227         attlistIndex = fGrammar.getNextAttributeDeclIndex(attlistIndex);
2228      }
2229      return attrIndex;
2230
2231   } // addDefaultAttributes(int,XMLAttrList,int,boolean,boolean):int
2232

2233   /** addDTDDefaultAttributes. */
2234   private int addDTDDefaultAttributes(QName element, XMLAttrList attrList, int attrIndex, boolean validationEnabled, boolean standalone) throws Exception JavaDoc {
2235
2236
2237      //
2238
// Check after all specified attrs are scanned
2239
// (1) report error for REQUIRED attrs that are missing (V_TAGc)
2240
// (2) check that FIXED attrs have matching value (V_TAGd)
2241
// (3) add default attrs (FIXED and NOT_FIXED)
2242
//
2243

2244      int elementIndex = fGrammar.getElementDeclIndex(element, -1);
2245
2246      if (elementIndex == -1) {
2247         return attrIndex;
2248      }
2249
2250      fGrammar.getElementDecl(elementIndex,fTempElementDecl);
2251
2252
2253      int elementNameIndex = fTempElementDecl.name.rawname;
2254      int attlistIndex = fGrammar.getFirstAttributeDeclIndex(elementIndex);
2255      int firstCheck = attrIndex;
2256      int lastCheck = -1;
2257      while (attlistIndex != -1) {
2258
2259         fGrammar.getAttributeDecl(attlistIndex, fTempAttDecl);
2260
2261         // TO DO: For ericye Debug only
2262
/***
2263         if (fTempAttDecl != null) {
2264             XMLElementDecl element = new XMLElementDecl();
2265             fGrammar.getElementDecl(elementIndex, element);
2266             System.out.println("element: "+fStringPool.toString(element.name.localpart));
2267             System.out.println("attlistIndex " + attlistIndex + "\n"+
2268                 "attName : '"+fStringPool.toString(fTempAttDecl.name.localpart) + "'\n"
2269                                + "attType : "+fTempAttDecl.type + "\n"
2270                                + "attDefaultType : "+fTempAttDecl.defaultType + "\n"
2271                                + "attDefaultValue : '"+fTempAttDecl.defaultValue + "'\n"
2272                                + attrList.getLength() +"\n"
2273                                );
2274         }
2275         /***/

2276
2277         int attPrefix = fTempAttDecl.name.prefix;
2278         int attName = fTempAttDecl.name.rawname;
2279         int attLocalpart = fTempAttDecl.name.localpart;
2280         int attType = attributeTypeName(fTempAttDecl);
2281         int attDefType =fTempAttDecl.defaultType;
2282         int attValue = -1 ;
2283         if (fTempAttDecl.defaultValue != null ) {
2284            attValue = fStringPool.addSymbol(fTempAttDecl.defaultValue);
2285         }
2286         boolean specified = false;
2287         boolean required = (attDefType & XMLAttributeDecl.DEFAULT_TYPE_REQUIRED)>0;
2288
2289
2290         /****
2291         if (fValidating && fGrammar != null && fGrammarIsDTDGrammar && attValue != -1) {
2292             normalizeAttValue(null, fTempAttDecl.name,
2293                               attValue,attType,fTempAttDecl.list,
2294                               fTempAttDecl.enumeration);
2295         }
2296         /****/

2297
2298         if (firstCheck != -1) {
2299            boolean cdata = attType == fCDATASymbol;
2300            if (!cdata || required || attValue != -1) {
2301               int i = attrList.getFirstAttr(firstCheck);
2302               while (i != -1 && (lastCheck == -1 || i <= lastCheck)) {
2303
2304                  if ( attrList.getAttrName(i) == fTempAttDecl.name.rawname ) {
2305
2306                     if (validationEnabled && (attDefType & XMLAttributeDecl.DEFAULT_TYPE_FIXED) > 0) {
2307                        int alistValue = attrList.getAttValue(i);
2308                        if (alistValue != attValue &&
2309                            !fStringPool.toString(alistValue).equals(fStringPool.toString(attValue))) {
2310                           Object JavaDoc[] args = { fStringPool.toString(elementNameIndex),
2311                              fStringPool.toString(attName),
2312                              fStringPool.toString(alistValue),
2313                              fStringPool.toString(attValue)};
2314                           fErrorReporter.reportError(fErrorReporter.getLocator(),
2315                                                      XMLMessages.XML_DOMAIN,
2316                                                      XMLMessages.MSG_FIXED_ATTVALUE_INVALID,
2317                                                      XMLMessages.VC_FIXED_ATTRIBUTE_DEFAULT,
2318                                                      args,
2319                                                      XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2320                        }
2321                     }
2322                     specified = true;
2323                     break;
2324                  }
2325                  i = attrList.getNextAttr(i);
2326               }
2327            }
2328         }
2329
2330         if (!specified) {
2331            if (required) {
2332               if (validationEnabled) {
2333                  Object JavaDoc[] args = { fStringPool.toString(elementNameIndex),
2334                     fStringPool.toString(attName)};
2335                  fErrorReporter.reportError(fErrorReporter.getLocator(),
2336                                             XMLMessages.XML_DOMAIN,
2337                                             XMLMessages.MSG_REQUIRED_ATTRIBUTE_NOT_SPECIFIED,
2338                                             XMLMessages.VC_REQUIRED_ATTRIBUTE,
2339                                             args,
2340                                             XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2341               }
2342            } else if (attValue != -1) {
2343               if (validationEnabled && standalone ){
2344                  if ( fGrammarIsDTDGrammar
2345                       && ((DTDGrammar) fGrammar).getAttributeDeclIsExternal(attlistIndex) ) {
2346
2347                     Object JavaDoc[] args = { fStringPool.toString(elementNameIndex),
2348                        fStringPool.toString(attName)};
2349                     fErrorReporter.reportError(fErrorReporter.getLocator(),
2350                                                XMLMessages.XML_DOMAIN,
2351                                                XMLMessages.MSG_DEFAULTED_ATTRIBUTE_NOT_SPECIFIED,
2352                                                XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
2353                                                args,
2354                                                XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2355                  }
2356               }
2357               if (validationEnabled) {
2358                    validateUsingDV (fTempAttDecl.datatypeValidator,
2359                                     fStringPool.toString(attValue), true);
2360               }
2361               if (attrIndex == -1) {
2362                  attrIndex = attrList.startAttrList();
2363               }
2364
2365               fTempQName.setValues(attPrefix, attLocalpart, attName, fTempAttDecl.name.uri);
2366               int newAttr = attrList.addAttr(fTempQName,
2367                                              attValue, attType,
2368                                              false, false);
2369               if (lastCheck == -1) {
2370                  lastCheck = newAttr;
2371               }
2372            }
2373         }
2374         attlistIndex = fGrammar.getNextAttributeDeclIndex(attlistIndex);
2375      }
2376      return attrIndex;
2377
2378   } // addDTDDefaultAttributes(int,XMLAttrList,int,boolean,boolean):int
2379

2380   // content models
2381

2382   /** Queries the content model for the specified element index. */
2383   private XMLContentModel getElementContentModel(int elementIndex) throws Exception JavaDoc {
2384      XMLContentModel contentModel = null;
2385      if ( elementIndex > -1) {
2386         if ( fGrammar.getElementDecl(elementIndex,fTempElementDecl) ) {
2387             if (fSGComparator == null) {
2388                 fSGComparator = new SubstitutionGroupComparator(fGrammarResolver, fStringPool, fErrorReporter);
2389             }
2390            contentModel = fGrammar.getElementContentModel(elementIndex, fSGComparator);
2391         }
2392      }
2393      //return fGrammar.getElementContentModel(elementIndex);
2394
return contentModel;
2395   }
2396
2397
2398
2399   // query attribute information
2400

2401   /** Returns an attribute definition for an element type. */
2402   // this is only used by DTD validation.
2403
private int getAttDef(QName element, QName attribute) {
2404      if (fGrammar != null) {
2405         int scope = fCurrentScope;
2406         if (element.uri > -1) {
2407            scope = TOP_LEVEL_SCOPE;
2408         }
2409         int elementIndex = fGrammar.getElementDeclIndex(element,scope);
2410         if (elementIndex == -1) {
2411            return -1;
2412         }
2413         int attDefIndex = fGrammar.getFirstAttributeDeclIndex(elementIndex);
2414         while (attDefIndex != -1) {
2415            fGrammar.getAttributeDecl(attDefIndex, fTempAttributeDecl);
2416            if (fTempAttributeDecl.name.localpart == attribute.localpart &&
2417                fTempAttributeDecl.name.uri == attribute.uri ) {
2418               return attDefIndex;
2419            }
2420            attDefIndex = fGrammar.getNextAttributeDeclIndex(attDefIndex);
2421         }
2422      }
2423      return -1;
2424
2425   } // getAttDef(QName,QName)
2426

2427   /** Returns an attribute definition for an element type. */
2428   private int getAttDefByElementIndex(int elementIndex, QName attribute) {
2429      if (fGrammar != null && elementIndex > -1) {
2430         if (elementIndex == -1) {
2431            return -1;
2432         }
2433         int attDefIndex = fGrammar.getFirstAttributeDeclIndex(elementIndex);
2434         while (attDefIndex != -1) {
2435            fGrammar.getAttributeDecl(attDefIndex, fTempAttDecl);
2436
2437            if (fGrammarIsDTDGrammar) {
2438               if (fTempAttDecl.name.rawname == attribute.rawname )
2439                  return attDefIndex;
2440            } else
2441               if (fTempAttDecl.name.localpart == attribute.localpart &&
2442                   fTempAttDecl.name.uri == attribute.uri ) {
2443               return attDefIndex;
2444            }
2445
2446            if (fGrammarIsSchemaGrammar) {
2447               if (fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_ANY) {
2448                  return attDefIndex;
2449               } else if (fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_OTHER) {
2450                  if (attribute.uri != fTempAttDecl.name.uri) {
2451                     return attDefIndex;
2452                  }
2453               } else if (fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_LIST) {
2454                  if (fStringPool.stringInList(fTempAttDecl.enumeration, attribute.uri)) {
2455                     return attDefIndex;
2456                  }
2457               }
2458            }
2459
2460            attDefIndex = fGrammar.getNextAttributeDeclIndex(attDefIndex);
2461         }
2462      }
2463      return -1;
2464
2465   } // getAttDef(QName,QName)
2466

2467   // validation
2468

2469   /** Root element specified. */
2470   private void rootElementSpecified(QName rootElement) throws Exception JavaDoc {
2471
2472      if ( fLoadDTDGrammar )
2473         // initialize the grammar to be the default one,
2474
// it definitely should be a DTD Grammar at this case;
2475
if (fGrammar == null) {
2476
2477            fGrammar = fGrammarResolver.getGrammar("");
2478
2479            if (fGrammar != null) {
2480               if (fGrammar instanceof DTDGrammar) {
2481                  fGrammarIsDTDGrammar = true;
2482                  fGrammarIsSchemaGrammar = false;
2483               } else if ( fGrammar instanceof SchemaGrammar ) {
2484                  fGrammarIsSchemaGrammar = true;
2485                  fGrammarIsDTDGrammar = false;
2486               }
2487
2488               fGrammarNameSpaceIndex = fEmptyURI;
2489            }
2490         }
2491
2492      if (fValidating) {
2493         if ( fGrammarIsDTDGrammar &&
2494              ((DTDGrammar) fGrammar).getRootElementQName(fRootElement) ) {
2495
2496            String JavaDoc root1 = fStringPool.toString(fRootElement.rawname);
2497            String JavaDoc root2 = fStringPool.toString(rootElement.rawname);
2498            if (!root1.equals(root2)) {
2499               reportRecoverableXMLError(XMLMessages.MSG_ROOT_ELEMENT_TYPE,
2500                                         XMLMessages.VC_ROOT_ELEMENT_TYPE,
2501                                         fRootElement.rawname,
2502                                         rootElement.rawname);
2503            }
2504         }
2505      }
2506
2507      if (fNamespacesEnabled) {
2508         if (fNamespacesScope == null) {
2509            fNamespacesScope = new NamespacesScope(this);
2510            fNamespacesPrefix = fStringPool.addSymbol("xmlns");
2511            //fNamespacesScope.setNamespaceForPrefix(fNamespacesPrefix, StringPool.EMPTY_STRING);
2512
// xxxxx
2513
fNamespacesScope.setNamespaceForPrefix(fNamespacesPrefix, -1);
2514            int xmlSymbol = fStringPool.addSymbol("xml");
2515            int xmlNamespace = fStringPool.addSymbol("http://www.w3.org/XML/1998/namespace");
2516            fNamespacesScope.setNamespaceForPrefix(xmlSymbol, xmlNamespace);
2517         }
2518      }
2519
2520   } // rootElementSpecified(QName)
2521

2522   /** Switchs to correct validating symbol tables when Schema changes.*/
2523
2524   private boolean switchGrammar(int newGrammarNameSpaceIndex) throws Exception JavaDoc {
2525      Grammar tempGrammar = fGrammarResolver.getGrammar(fStringPool.toString(newGrammarNameSpaceIndex));
2526      if (tempGrammar == null) {
2527         // This is a case where namespaces is on with a DTD grammar.
2528
tempGrammar = fGrammarResolver.getGrammar("");
2529      }
2530      if (tempGrammar == null) {
2531         return false;
2532      } else {
2533         fGrammar = tempGrammar;
2534         if (fGrammar instanceof DTDGrammar) {
2535            fGrammarIsDTDGrammar = true;
2536            fGrammarIsSchemaGrammar = false;
2537         } else if ( fGrammar instanceof SchemaGrammar ) {
2538            fGrammarIsSchemaGrammar = true;
2539            fGrammarIsDTDGrammar = false;
2540         }
2541
2542         return true;
2543      }
2544   }
2545
2546   /** Binds namespaces to the element and attributes. */
2547   private void bindNamespacesToElementAndAttributes(QName element,
2548                                                     XMLAttrList attrList)
2549   throws Exception JavaDoc {
2550
2551      fNamespacesScope.increaseDepth();
2552
2553
2554      if (fAttrListHandle != -1 || !fSeenRootElement) {
2555         int index = attrList.getFirstAttr(fAttrListHandle);
2556         while (index != -1) {
2557            int attName = attrList.getAttrName(index);
2558            int attPrefix = attrList.getAttrPrefix(index);
2559            if (fStringPool.equalNames(attName, fXMLLang)) {
2560               /* No check: http://www.w3.org/XML/xml-19980210-errata#E73 and bug 2793 */
2561            } else if (fStringPool.equalNames(attName, fNamespacesPrefix)) {
2562               int uri = fStringPool.addSymbol(attrList.getAttValue(index));
2563               fNamespacesScope.setNamespaceForPrefix(StringPool.EMPTY_STRING, uri);
2564            } else {
2565               if (attPrefix == fNamespacesPrefix) {
2566                  int nsPrefix = attrList.getAttrLocalpart(index);
2567                  int uri = fStringPool.addSymbol(attrList.getAttValue(index));
2568                  if(uri == StringPool.EMPTY_STRING) {
2569                      Object JavaDoc[] args = { fStringPool.toString(nsPrefix) };
2570                      fErrorReporter.reportError(fErrorReporter.getLocator(),
2571                                                 XMLMessages.XMLNS_DOMAIN,
2572                                                 XMLMessages.MSG_NAMESPACE_NAME_EMPTY,
2573                                                 XMLMessages.NC_NAMESPACE_NAME_EMPTY,
2574                                                 args, XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2575                   }
2576                  fNamespacesScope.setNamespaceForPrefix(nsPrefix, uri);
2577
2578                  if (fValidating && fSchemaValidation) {
2579                     boolean seeXsi = false;
2580                     String JavaDoc attrValue = fStringPool.toString(attrList.getAttValue(index));
2581
2582                     if (attrValue.equals(SchemaSymbols.URI_XSI)) {
2583                        fXsiPrefix = nsPrefix;
2584                        seeXsi = true;
2585                     }
2586                  }
2587               }
2588            }
2589            index = attrList.getNextAttr(index);
2590         }
2591
2592         String JavaDoc location = null;
2593         String JavaDoc uri = null;
2594
2595         // if validating, walk through the list again to deal with "xsi:...."
2596
if (fValidating && fSchemaValidation) {
2597
2598             fLocationUriPairs.clear();
2599             if (!fSeenRootElement) {
2600                 // we are at the root element
2601
// and user set property on the parser to include external schemas
2602
//
2603
if (fExternalSchemas != null && fExternalSchemas.length()!=0) {
2604
2605                     parseSchemaLocation(fExternalSchemas);
2606                 }
2607                 if (fExternalNoNamespaceSchema!=null && fExternalNoNamespaceSchema.length() !=0 ) {
2608
2609                     fLocationUriPairs.put(fExternalNoNamespaceSchema, "");
2610
2611                     //REVISIT: wrong solution (see AndyC note below)
2612
if (fNamespacesScope != null) {
2613                      //bind prefix "" to URI "" in this case
2614
fNamespacesScope.setNamespaceForPrefix( fStringPool.addSymbol(""),
2615                                                              fStringPool.addSymbol(""));
2616                   }
2617                 }
2618                 parseSchemas();
2619                 fLocationUriPairs.clear();
2620             }
2621
2622            fXsiTypeAttValue = -1;
2623            fNil = false;
2624            index = attrList.getFirstAttr(fAttrListHandle);
2625            int attName;
2626            int attPrefix;
2627            while (index != -1) {
2628
2629               attName = attrList.getAttrName(index);
2630               attPrefix = attrList.getAttrPrefix(index);
2631
2632               if (fStringPool.equalNames(attName, fNamespacesPrefix)) {
2633                  // REVISIT
2634
} else {
2635                  if ( DEBUG_SCHEMA_VALIDATION ) {
2636                     System.out.println("deal with XSI");
2637                     System.out.println("before find XSI: "+fStringPool.toString(attPrefix)
2638                                        +","+fStringPool.toString(fXsiPrefix) );
2639                  }
2640                  if ( fXsiPrefix != -1 && attPrefix == fXsiPrefix ) {
2641
2642                     if (DEBUG_SCHEMA_VALIDATION) {
2643                        System.out.println("find XSI: "+fStringPool.toString(attPrefix)
2644                                           +","+fStringPool.toString(attName) );
2645                     }
2646
2647                     int localpart = attrList.getAttrLocalpart(index);
2648                     if (localpart == fStringPool.addSymbol(SchemaSymbols.XSI_SCHEMALOCACTION)) {
2649                        parseSchemaLocation(fStringPool.toString(attrList.getAttValue(index)));
2650                     } else if (localpart == fStringPool.addSymbol(SchemaSymbols.XSI_NONAMESPACESCHEMALOCACTION)) {
2651                        fLocationUriPairs.put(fStringPool.toString(attrList.getAttValue(index)), "");
2652
2653                        /***/
2654                        // NOTE: This is the *wrong* solution to the problem
2655
// of finding the grammar associated to elements
2656
// when the grammar does *not* have a target
2657
// namespace!!! -Ac
2658
if (fNamespacesScope != null) {
2659                           //bind prefix "" to URI "" in this case
2660
fNamespacesScope.setNamespaceForPrefix( fStringPool.addSymbol(""),
2661                                                                   fStringPool.addSymbol(""));
2662                        }
2663                        /***/
2664                        }
2665                        else if ( localpart == fStringPool.addSymbol(SchemaSymbols.XSI_TYPE) ) {
2666                            fXsiTypeAttValue = attrList.getAttValue(index);
2667                        }
2668                        else if ( localpart == fStringPool.addSymbol(SchemaSymbols.ATT_NIL) ) {
2669                            fNil = (fStringPool.toString(attrList.getAttValue(index)).equals("true")) ? true: false;
2670
2671                        }
2672                     // REVISIT: should we break here?
2673
//break;
2674
}
2675               }
2676               index = attrList.getNextAttr(index);
2677            }
2678            parseSchemas ();
2679         }
2680
2681      }
2682
2683      // bind element to URI
2684
int prefix = element.prefix != -1 ? element.prefix : 0;
2685      int uri = fNamespacesScope.getNamespaceForPrefix(prefix);
2686      if (element.prefix != -1 || uri != StringPool.EMPTY_STRING) {
2687         element.uri = uri;
2688         if (element.uri == StringPool.EMPTY_STRING) {
2689            Object JavaDoc[] args = { fStringPool.toString(element.prefix)};
2690            fErrorReporter.reportError(fErrorReporter.getLocator(),
2691                                       XMLMessages.XMLNS_DOMAIN,
2692                                       XMLMessages.MSG_PREFIX_DECLARED,
2693                                       XMLMessages.NC_PREFIX_DECLARED,
2694                                       args,
2695                                       XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2696         }
2697      }
2698
2699
2700      if (fAttrListHandle != -1) {
2701         int index = attrList.getFirstAttr(fAttrListHandle);
2702         while (index != -1) {
2703            int attName = attrList.getAttrName(index);
2704            if (!fStringPool.equalNames(attName, fNamespacesPrefix)) {
2705               int attPrefix = attrList.getAttrPrefix(index);
2706               if (attPrefix != fNamespacesPrefix) {
2707                  if (attPrefix != -1 ) {
2708                     int attrUri = fNamespacesScope.getNamespaceForPrefix(attPrefix);
2709                     if (attrUri == -1) {
2710                        Object JavaDoc[] args = { fStringPool.toString(attPrefix)};
2711                        fErrorReporter.reportError(fErrorReporter.getLocator(),
2712                                                   XMLMessages.XMLNS_DOMAIN,
2713                                                   XMLMessages.MSG_PREFIX_DECLARED,
2714                                                   XMLMessages.NC_PREFIX_DECLARED,
2715                                                   args,
2716                                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2717                     }
2718                     attrList.setAttrURI(index, attrUri);
2719                  }
2720               }
2721            }
2722            index = attrList.getNextAttr(index);
2723         }
2724      }
2725
2726   } // bindNamespacesToElementAndAttributes(QName,XMLAttrList)
2727

2728   private void parseSchemas () throws Exception JavaDoc{
2729
2730       // try to resolve all the grammars here
2731
Enumeration JavaDoc locations = fLocationUriPairs.keys();
2732       String JavaDoc location = null;
2733       String JavaDoc uri = null;
2734       while (locations.hasMoreElements()) {
2735           location = (String JavaDoc) locations.nextElement();
2736           uri = (String JavaDoc) fLocationUriPairs.get(location);
2737           resolveSchemaGrammar( location, uri);
2738       }
2739   }
2740
2741   private void parseSchemaLocation(String JavaDoc schemaLocationStr) throws Exception JavaDoc{
2742         StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(schemaLocationStr, " \n\t\r", false);
2743         int tokenTotal = tokenizer.countTokens();
2744         if (tokenTotal % 2 != 0 ) {
2745             fErrorReporter.reportError(fErrorReporter.getLocator(),
2746                     SchemaMessageProvider.SCHEMA_DOMAIN,
2747                     SchemaMessageProvider.SchemaLocation,
2748                     SchemaMessageProvider.MSG_NONE,
2749                     new Object JavaDoc[]{schemaLocationStr},
2750                     XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
2751
2752         } else {
2753             String JavaDoc uri = null;
2754             String JavaDoc location = null;
2755             while (tokenizer.hasMoreTokens()) {
2756               uri = tokenizer.nextToken();
2757               location = tokenizer.nextToken();
2758               fLocationUriPairs.put(location, uri);
2759            }
2760         }
2761
2762   }// parseSchemaLocation(String, Hashtable)
2763

2764
2765   private void resolveSchemaGrammar( String JavaDoc loc, String JavaDoc uri) throws Exception JavaDoc {
2766       Grammar grammar = null;
2767       if (uri!=null) {
2768           if (fGrammarIsDTDGrammar && uri.length()==0) {
2769               fErrorReporter.reportError(fErrorReporter.getLocator(),
2770                                          XMLMessages.XML_DOMAIN,
2771                                          XMLMessages.MSG_DTD_SCHEMA_ERROR,
2772                                          XMLMessages.MSG_DTD_SCHEMA_ERROR,
2773                                          null,
2774                                          XMLErrorReporter.ERRORTYPE_WARNING);
2775           } else {
2776                grammar = fGrammarResolver.getGrammar(uri);
2777           }
2778       }
2779
2780       if (grammar == null) {
2781
2782          if (fSchemaGrammarParser == null) {
2783              //
2784
// creating a parser for schema only once per parser instance
2785
// leads to less objects, but increases time we spend in reset()
2786
//
2787
fSchemaGrammarParser = new DOMParser();
2788              fSchemaGrammarParser.setEntityResolver( new Resolver JavaDoc(fEntityHandler) );
2789              fSchemaGrammarParser.setErrorHandler( new ErrorHandler() );
2790
2791              try {
2792                fSchemaGrammarParser.setFeature("http://xml.org/sax/features/validation", false);
2793                fSchemaGrammarParser.setFeature("http://xml.org/sax/features/namespaces", true);
2794                fSchemaGrammarParser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
2795              } catch ( org.xml.sax.SAXNotRecognizedException JavaDoc e ) {
2796                e.printStackTrace();
2797              } catch ( org.xml.sax.SAXNotSupportedException JavaDoc e ) {
2798                e.printStackTrace();
2799              }
2800          }
2801         // expand it before passing it to the parser
2802
InputSource JavaDoc source = null;
2803         EntityResolver JavaDoc currentER = fSchemaGrammarParser.getEntityResolver();
2804         if (currentER != null) {
2805            source = currentER.resolveEntity("", loc);
2806         }
2807         if (source == null) {
2808            loc = fEntityHandler.expandSystemId(loc);
2809            source = new InputSource JavaDoc(loc);
2810         }
2811
2812         try {
2813            fSchemaGrammarParser.parse( source );
2814         } catch ( IOException JavaDoc e ) {
2815            e.printStackTrace();
2816         } catch ( SAXException JavaDoc e ) {
2817            reportRecoverableXMLError( XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
2818                                       XMLMessages.SCHEMA_GENERIC_ERROR, e.getMessage() );
2819         }
2820
2821         Document JavaDoc document = fSchemaGrammarParser.getDocument(); //Our Grammar
2822

2823         TraverseSchema tst = null;
2824         if (DEBUG_SCHEMA_VALIDATION) {
2825            System.out.println("I am geting the Schema Document");
2826         }
2827
2828         Element JavaDoc root = null;
2829         if (document != null) {
2830             root = document.getDocumentElement();// This is what we pass to TraverserSchema
2831
}
2832         if (root == null) {
2833            reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR, XMLMessages.SCHEMA_GENERIC_ERROR, "Can't get back Schema document's root element :" + loc);
2834         } else {
2835            if (uri!=null && !uri.equals(root.getAttribute(SchemaSymbols.ATT_TARGETNAMESPACE)) ) {
2836               reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR, XMLMessages.SCHEMA_GENERIC_ERROR, "Schema in " + loc + " has a different target namespace " +
2837                                         "from the one specified in the instance document :" + uri);
2838            }
2839
2840            grammar = new SchemaGrammar();
2841            grammar.setGrammarDocument(document);
2842
2843            // Since we've just constructed a schema grammar, we should make sure we know what we've done.
2844
fGrammarIsSchemaGrammar = true;
2845            fGrammarIsDTDGrammar = false;
2846
2847            //At this point we should expand the registry table.
2848
// pass parser's entity resolver (local Resolver), which also has reference to user's
2849
// entity resolver, and also can fall-back to entityhandler's expandSystemId()
2850
GeneralAttrCheck generalAttrCheck = new GeneralAttrCheck(fErrorReporter, fDataTypeReg);
2851            tst = new TraverseSchema( root, fStringPool, (SchemaGrammar)grammar, fGrammarResolver, fErrorReporter, source.getSystemId(), currentER, getSchemaFullCheckingEnabled(), generalAttrCheck, fExternalSchemas, fExternalNoNamespaceSchema);
2852            generalAttrCheck.checkNonSchemaAttributes(fGrammarResolver);
2853
2854            //allowing xsi:schemaLocation to appear on any element
2855

2856            String JavaDoc targetNS = root.getAttribute("targetNamespace");
2857            fGrammarNameSpaceIndex = fStringPool.addSymbol(targetNS);
2858            fGrammarResolver.putGrammar(targetNS, grammar);
2859            fGrammar = (SchemaGrammar)grammar;
2860
2861            // when in full checking, we need to do UPA stuff here
2862
// by constructing all content models
2863
if (fSchemaValidationFullChecking) {
2864               try {
2865                 // get all grammar URIs
2866
Enumeration JavaDoc grammarURIs = fGrammarResolver.nameSpaceKeys();
2867                 String JavaDoc grammarURI;
2868                 Grammar gGrammar;
2869                 SchemaGrammar sGrammar;
2870                 // for each grammar
2871
while (grammarURIs.hasMoreElements()) {
2872                     grammarURI = (String JavaDoc)grammarURIs.nextElement();
2873                     // if we checked UPA on this grammar, just skip
2874
if (UPACheckedGrammarURIs.get(grammarURI) != null)
2875                        continue;
2876                     // otherwise, mark this one as checked
2877
UPACheckedGrammarURIs.put(grammarURI, fgNullObject);
2878                     gGrammar = fGrammarResolver.getGrammar(grammarURI);
2879                     if (!(gGrammar instanceof SchemaGrammar))
2880                        continue;
2881                     sGrammar = (SchemaGrammar)gGrammar;
2882
2883                     // get all registered complex type in this grammar
2884
Hashtable JavaDoc complexTypeRegistry = sGrammar.getComplexTypeRegistry();
2885                     int count = complexTypeRegistry.size();
2886                     Enumeration JavaDoc enumer = complexTypeRegistry.elements();
2887
2888                     TraverseSchema.ComplexTypeInfo typeInfo;
2889                     if (fSGComparator == null) {
2890                         fSGComparator = new SubstitutionGroupComparator(fGrammarResolver, fStringPool, fErrorReporter);
2891                     }
2892                     while (enumer.hasMoreElements ()) {
2893                         typeInfo = (TraverseSchema.ComplexTypeInfo)enumer.nextElement();
2894                         // for each type, we construct a corresponding content model
2895
sGrammar.getContentModel(typeInfo.contentSpecHandle,
2896                                                  typeInfo.contentType,
2897                                                  fSGComparator);
2898                     }
2899                 }
2900               } catch (CMException excToCatch) {
2901                  // REVISIT - Translate caught error to the protected error handler interface
2902
int majorCode = excToCatch.getErrorCode();
2903                  fErrorReporter.reportError(fErrorReporter.getLocator(),
2904                                             ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
2905                                             majorCode,
2906                                             0,
2907                                             null,
2908                                             XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
2909               }
2910            }
2911         }
2912      }
2913
2914   }
2915
2916
2917   /*
2918    * for <notation> must resolve values "b:myNotation"
2919    *
2920    * @param value string value of element or attribute
2921    * @return
2922    * @exception Exception
2923    */

2924   private String JavaDoc bindNotationURI (String JavaDoc value) throws Exception JavaDoc{
2925       int colonP = value.indexOf(":");
2926       String JavaDoc prefix = "";
2927       String JavaDoc localpart = value;
2928       if (colonP > -1) {
2929           prefix = value.substring(0,colonP);
2930           localpart = value.substring(colonP+1);
2931       }
2932
2933       String JavaDoc uri = "";
2934       int uriIndex = StringPool.EMPTY_STRING;
2935       if (fNamespacesScope != null) {
2936           //if prefix.equals("") it would bing to xmlns URI
2937
uriIndex = fNamespacesScope.getNamespaceForPrefix(fStringPool.addSymbol(prefix));
2938           if (uriIndex > 0) {
2939               return fStringPool.toString(uriIndex)+":"+localpart;
2940           } else if (fGrammarNameSpaceIndex!=-1){
2941               // REVISIT: try binding to current namespace
2942
// trying to solve the case:
2943
// <v01:root xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"
2944
// xmlns:my ="http://www.schemaTest.org/my"
2945
// might not work in all cases (need clarification from schema?)
2946
return fStringPool.toString( fGrammarNameSpaceIndex)+":"+localpart;
2947           }
2948
2949
2950       }
2951       return value;
2952   }
2953
2954   static class Resolver implements EntityResolver JavaDoc {
2955
2956      //
2957
// Constants
2958
//
2959

2960      private static final String JavaDoc SYSTEM[] = {
2961         "http://www.w3.org/2001/XMLSchema.dtd",
2962         "http://www.w3.org/XMLSchema/datatypes.dtd",
2963         "http://www.w3.org/XMLSchema/versionInfo.ent",
2964      };
2965      private static final String JavaDoc PATH[] = {
2966         "structures.dtd",
2967         "datatypes.dtd",
2968         "versionInfo.ent",
2969      };
2970
2971      //
2972
// Data
2973
//
2974

2975      private DefaultEntityHandler fEntityHandler;
2976
2977      //
2978
// Constructors
2979
//
2980

2981      public Resolver(DefaultEntityHandler handler) {
2982         fEntityHandler = handler;
2983      }
2984
2985      //
2986
// EntityResolver methods
2987
//
2988

2989      public InputSource JavaDoc resolveEntity(String JavaDoc publicId, String JavaDoc systemId)
2990      throws IOException JavaDoc, SAXException JavaDoc {
2991
2992         // looking for the schema DTDs?
2993
for (int i = 0; i < SYSTEM.length; i++) {
2994            if (systemId.equals(SYSTEM[i])) {
2995               InputSource JavaDoc source = new InputSource JavaDoc(getClass().getResourceAsStream(PATH[i]));
2996               source.setPublicId(publicId);
2997               source.setSystemId(systemId);
2998               return source;
2999            }
3000         }
3001
3002         // first try to resolve using user's entity resolver
3003
EntityResolver JavaDoc resolver = fEntityHandler.getEntityResolver();
3004         if (resolver != null) {
3005            InputSource JavaDoc source = resolver.resolveEntity(publicId, systemId);
3006            if (source != null) {
3007               return source;
3008            }
3009         }
3010
3011         // use default resolution
3012
return new InputSource JavaDoc(fEntityHandler.expandSystemId(systemId));
3013
3014      } // resolveEntity(String,String):InputSource
3015

3016   } // class Resolver
3017

3018   static class ErrorHandler implements org.xml.sax.ErrorHandler JavaDoc {
3019
3020      /** Warning. */
3021      public void warning(SAXParseException JavaDoc ex) {
3022         System.err.println("[Warning] "+
3023                            getLocationString(ex)+": "+
3024                            ex.getMessage());
3025      }
3026
3027      /** Error. */
3028      public void error(SAXParseException JavaDoc ex) {
3029         System.err.println("[Error] "+
3030                            getLocationString(ex)+": "+
3031                            ex.getMessage());
3032      }
3033
3034      /** Fatal error. */
3035      public void fatalError(SAXParseException JavaDoc ex) {
3036         System.err.println("[Fatal Error] "+
3037                            getLocationString(ex)+": "+
3038                            ex.getMessage());
3039         //throw ex;
3040
}
3041
3042      //
3043
// Private methods
3044
//
3045

3046      /** Returns a string of the location. */
3047      private String JavaDoc getLocationString(SAXParseException JavaDoc ex) {
3048         StringBuffer JavaDoc str = new StringBuffer JavaDoc();
3049
3050         String JavaDoc systemId_ = ex.getSystemId();
3051         if (systemId_ != null) {
3052            int index = systemId_.lastIndexOf('/');
3053            if (index != -1)
3054               systemId_ = systemId_.substring(index + 1);
3055            str.append(systemId_);
3056         }
3057         str.append(':');
3058         str.append(ex.getLineNumber());
3059         str.append(':');
3060         str.append(ex.getColumnNumber());
3061
3062         return str.toString();
3063
3064      } // getLocationString(SAXParseException):String
3065
}
3066
3067   private int attributeTypeName(XMLAttributeDecl attrDecl) {
3068      switch (attrDecl.type) {
3069      case XMLAttributeDecl.TYPE_ENTITY: {
3070            return attrDecl.list ? fENTITIESSymbol : fENTITYSymbol;
3071         }
3072      case XMLAttributeDecl.TYPE_ENUMERATION: {
3073            String JavaDoc enumeration = fStringPool.stringListAsString(attrDecl.enumeration);
3074            return fStringPool.addSymbol(enumeration);
3075         }
3076      case XMLAttributeDecl.TYPE_ID: {
3077            return fIDSymbol;
3078         }
3079      case XMLAttributeDecl.TYPE_IDREF: {
3080            return attrDecl.list ? fIDREFSSymbol : fIDREFSymbol;
3081         }
3082      case XMLAttributeDecl.TYPE_NMTOKEN: {
3083            return attrDecl.list ? fNMTOKENSSymbol : fNMTOKENSymbol;
3084         }
3085      case XMLAttributeDecl.TYPE_NOTATION: {
3086            return fNOTATIONSymbol;
3087         }
3088      }
3089      return fCDATASymbol;
3090   }
3091
3092   /** Validates element and attributes. */
3093   private void validateElementAndAttributes(QName element,
3094                                             XMLAttrList attrList)
3095   throws Exception JavaDoc {
3096
3097      if ((fGrammarIsSchemaGrammar && fElementDepth >= 0 && fValidationFlagStack[fElementDepth] != 0 )||
3098          (fGrammar == null && !fValidating && !fNamespacesEnabled) ) {
3099         fCurrentElementIndex = -1;
3100         fCurrentContentSpecType = -1;
3101         fInElementContent = false;
3102         if (fAttrListHandle != -1) {
3103            //fAttrList.endAttrList();
3104
int dupAttrs[];
3105            if ((dupAttrs = fAttrList.endAttrList()) != null) {
3106               Object JavaDoc[] args = {fStringPool.toString(element.rawname), null};
3107               for (int i = 0; i < dupAttrs.length; i++) {
3108                   args[1] = fStringPool.toString(dupAttrs[i]);
3109                   fErrorReporter.reportError(fErrorReporter.getLocator(),
3110                                              XMLMessages.XMLNS_DOMAIN,
3111                                              XMLMessages.MSG_ATTRIBUTE_NOT_UNIQUE,
3112                                              XMLMessages.WFC_UNIQUE_ATT_SPEC,
3113                                              args,
3114                                              XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
3115               }
3116            }
3117         }
3118         return;
3119      }
3120
3121      int elementIndex = -1;
3122      int contentSpecType = -1;
3123
3124      boolean skipThisOne = false;
3125      boolean laxThisOne = false;
3126
3127      if ( fGrammarIsSchemaGrammar && fElementDepth > -1 && fContentLeafStack[fElementDepth] != null ) {
3128         ContentLeafNameTypeVector cv = fContentLeafStack[fElementDepth];
3129
3130         //OTWI: on-the-way-in
3131
if (fContentModelStateStack[fElementDepth] >= 0) {
3132            // get the position of the current element in the content model
3133
int pos = ((DFAContentModel)fContentModelStack[fElementDepth]).
3134                      oneTransition(element, fContentModelStateStack, fElementDepth);
3135            // if it's a valid child, increase succeful count
3136
// and check whether we need to lax or skip this one
3137
if (pos >= 0) {
3138                fContentModelEleCount[fElementDepth]++;
3139                switch (cv.leafTypes[pos]) {
3140                case XMLContentSpec.CONTENTSPECNODE_ANY_SKIP:
3141                case XMLContentSpec.CONTENTSPECNODE_ANY_NS_SKIP:
3142                case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER_SKIP:
3143                      skipThisOne = true;
3144                      break;
3145                case XMLContentSpec.CONTENTSPECNODE_ANY_LAX:
3146                case XMLContentSpec.CONTENTSPECNODE_ANY_NS_LAX:
3147                case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER_LAX:
3148                      laxThisOne = true;
3149                      break;
3150                }
3151            }
3152         }
3153/*
3154         QName[] fElemMap = cv.leafNames;
3155         for (int i=0; i<cv.leafCount; i++) {
3156            int type = cv.leafTypes[i] ;
3157            //System.out.println("******* see a ANY_OTHER_SKIP, "+type+","+element+","+fElemMap[i]+"\n*******");
3158
3159            if (type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
3160               if (fElemMap[i].uri==element.uri
3161                   && fElemMap[i].localpart == element.localpart)
3162                  break;
3163            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY) {
3164                  break;
3165            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_NS) {
3166               if (element.uri == fElemMap[i].uri) {
3167                  break;
3168               }
3169            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
3170               if (fElemMap[i].uri != element.uri) {
3171                  break;
3172               }
3173            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_SKIP) {
3174                  skipThisOne = true;
3175                  break;
3176            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_NS_SKIP) {
3177               if (element.uri == fElemMap[i].uri) {
3178                  skipThisOne = true;
3179                  break;
3180               }
3181            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER_SKIP) {
3182               if (fElemMap[i].uri != element.uri) {
3183                  skipThisOne = true;
3184                  break;
3185               }
3186            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_LAX) {
3187                  laxThisOne = true;
3188                  break;
3189            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_NS_LAX) {
3190               if (element.uri == fElemMap[i].uri) {
3191                  laxThisOne = true;
3192                  break;
3193               }
3194            } else if (type == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER_LAX) {
3195               if (fElemMap[i].uri != element.uri) {
3196                  laxThisOne = true;
3197                  break;
3198               }
3199            }
3200
3201         }
3202*/

3203      }
3204
3205      if (skipThisOne) {
3206         fNeedValidationOff = true;
3207      } else {
3208         //REVISIT: is this the right place to check on if the Schema has changed?
3209
TraverseSchema.ComplexTypeInfo baseTypeInfo = null;
3210        if (fGrammarIsSchemaGrammar && fCurrentElementIndex != -1)
3211            baseTypeInfo = ((SchemaGrammar)fGrammar).getElementComplexTypeInfo(fCurrentElementIndex);
3212
3213
3214         if ( fNamespacesEnabled && fValidating &&
3215              element.uri != fGrammarNameSpaceIndex &&
3216              element.uri != StringPool.EMPTY_STRING) {
3217            fGrammarNameSpaceIndex = element.uri;
3218
3219            boolean success = switchGrammar(fGrammarNameSpaceIndex);
3220
3221            if (!success && !laxThisOne) {
3222               reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR, XMLMessages.SCHEMA_GENERIC_ERROR,
3223                                         "Grammar with uri: " + fStringPool.toString(fGrammarNameSpaceIndex)
3224                                         + " , can not be found; schema namespace may be wrong: Xerces supports schemas from the \"http://www.w3.org/2001/XMLSchema\" namespace"
3225                                         + " or the instance document's namespace may not match the targetNamespace of the schema");
3226            }
3227         }
3228
3229         if ( fGrammar != null ) {
3230            if (DEBUG_SCHEMA_VALIDATION) {
3231               System.out.println("*******Lookup element: uri: " + fStringPool.toString(element.uri)+
3232                                  " localpart: '" + fStringPool.toString(element.localpart)
3233                                  +"' and scope : " + fCurrentScope+"\n");
3234            }
3235
3236            elementIndex = fGrammar.getElementDeclIndex(element,fCurrentScope);
3237
3238            if (elementIndex == -1 ) {
3239               elementIndex = fGrammar.getElementDeclIndex(element, TOP_LEVEL_SCOPE);
3240            }
3241
3242            if (elementIndex == -1) {
3243               // if validating based on a Schema, try to resolve the element again by searching in its type's ancestor types
3244
if (fGrammarIsSchemaGrammar && fCurrentElementIndex != -1) {
3245                  int aGrammarNSIndex = fGrammarNameSpaceIndex;
3246                  while (baseTypeInfo != null) {
3247                    String JavaDoc baseTName = baseTypeInfo.typeName;
3248                    if (!baseTName.startsWith("#")) {
3249                       int comma = baseTName.indexOf(',');
3250                       aGrammarNSIndex = fStringPool.addSymbol(baseTName.substring(0,comma).trim());
3251                       if (aGrammarNSIndex != fGrammarNameSpaceIndex) {
3252                          if ( !switchGrammar(aGrammarNSIndex) ) {
3253                             break; //exit the loop in this case
3254
}
3255                          fGrammarNameSpaceIndex = aGrammarNSIndex;
3256                       }
3257                    }
3258                     elementIndex = fGrammar.getElementDeclIndex(element, baseTypeInfo.scopeDefined);
3259                     if (elementIndex > -1 ) {
3260                        //System.out.println("found element index for " + fStringPool.toString(element.localpart));
3261
// update the current Grammar NS index if resolving element succeed.
3262
break;
3263                     }
3264                     baseTypeInfo = baseTypeInfo.baseComplexTypeInfo;
3265                  }
3266                  // if *still* can't find it, try a grammar with no targetNamespace
3267
if(elementIndex == -1 && element.uri == StringPool.EMPTY_STRING) {
3268                    boolean success = switchGrammar(element.uri);
3269                    if(success) {
3270                        fGrammarNameSpaceIndex = element.uri;
3271                        elementIndex = fGrammar.getElementDeclIndex(element.localpart, TOP_LEVEL_SCOPE);
3272                    }
3273                  }
3274               }
3275               //if still can't resolve it, try TOP_LEVEL_SCOPE AGAIN
3276
/****/
3277               if ( element.uri == StringPool.EMPTY_STRING && elementIndex == -1
3278               && fNamespacesScope != null ) {
3279               elementIndex = fGrammar.getElementDeclIndex(element.localpart, TOP_LEVEL_SCOPE);
3280               // REVISIT:
3281
// this is a hack to handle the situation where namespace prefix "" is bound to nothing, and there
3282
// is a "noNamespaceSchemaLocation" specified, and element
3283
element.uri = StringPool.EMPTY_STRING;
3284               }
3285               /****/
3286
3287               /****/
3288               if (elementIndex == -1) {
3289                  if (laxThisOne) {
3290                     fNeedValidationOff = true;
3291                  } else
3292                     if (DEBUG_SCHEMA_VALIDATION)
3293                     System.out.println("!!! can not find elementDecl in the grammar, " +
3294                                        " the element localpart: " + element.localpart +
3295                                        "["+fStringPool.toString(element.localpart) +"]" +
3296                                        " the element uri: " + element.uri +
3297                                        "["+fStringPool.toString(element.uri) +"]" +
3298                                        " and the current enclosing scope: " + fCurrentScope );
3299               }
3300               /****/
3301            }
3302
3303            if (DEBUG_SCHEMA_VALIDATION) {
3304               fGrammar.getElementDecl(elementIndex, fTempElementDecl);
3305               System.out.println("elementIndex: " + elementIndex+" \n and itsName : '"
3306                                  + fStringPool.toString(fTempElementDecl.name.localpart)
3307                                  +"' \n its ContentType:" + fTempElementDecl.type
3308                                  +"\n its ContentSpecIndex : " + fTempElementDecl.contentSpecIndex +"\n"+
3309                                  " and the current enclosing scope: " + fCurrentScope);
3310            }
3311         }
3312
3313         final int oldElementIndex = elementIndex;
3314
3315         contentSpecType = getContentSpecType(elementIndex);
3316         int elementNameLocalPart = StringPool.NULL_STRING;
3317         DatatypeValidator elementDatatypeValidator = null;
3318
3319         if (elementIndex != -1) {
3320             fGrammar.getElementDecl(elementIndex, fTempElementDecl);
3321             elementNameLocalPart = fTempElementDecl.name.localpart;
3322             elementDatatypeValidator = fTempElementDecl.datatypeValidator;
3323         }
3324
3325         if (fGrammarIsSchemaGrammar) {
3326
3327            // handle "xsi:type" right here
3328
if (fXsiTypeAttValue > -1) {
3329               String JavaDoc xsiType = fStringPool.toString(fXsiTypeAttValue);
3330               int colonP = xsiType.indexOf(":");
3331               String JavaDoc prefix = "";
3332               String JavaDoc localpart = xsiType;
3333               if (colonP > -1) {
3334                  prefix = xsiType.substring(0,colonP);
3335                  localpart = xsiType.substring(colonP+1);
3336               }
3337
3338               String JavaDoc uri = "";
3339               int uriIndex = StringPool.EMPTY_STRING;
3340               if (fNamespacesScope != null) {
3341                  uriIndex = fNamespacesScope.getNamespaceForPrefix(fStringPool.addSymbol(prefix));
3342                  if (uriIndex > 0) {
3343                     uri = fStringPool.toString(uriIndex);
3344                     if (uriIndex != fGrammarNameSpaceIndex) {
3345                        fGrammarNameSpaceIndex = fCurrentSchemaURI = uriIndex;
3346                        boolean success = switchGrammar(fCurrentSchemaURI);
3347                        if (!success && !fNeedValidationOff) {
3348                           // only report an error if the new namespace is not
3349
// the schema namespace
3350
if (!uri.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA))
3351                               reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3352                                                         XMLMessages.SCHEMA_GENERIC_ERROR,
3353                                                         "Grammar with uri: "
3354                                                         + fStringPool.toString(fCurrentSchemaURI)
3355                                                         + " , can not be found");
3356                        }
3357                     }
3358                  }
3359               }
3360
3361
3362               Hashtable JavaDoc complexRegistry = ((SchemaGrammar)fGrammar).getComplexTypeRegistry();
3363               DatatypeValidatorFactoryImpl dataTypeReg = ((SchemaGrammar)fGrammar).getDatatypeRegistry();
3364               if (complexRegistry==null || dataTypeReg == null) {
3365                  reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3366                                            XMLMessages.SCHEMA_GENERIC_ERROR,
3367                                            fErrorReporter.getLocator().getSystemId()
3368                                            +" line"+fErrorReporter.getLocator().getLineNumber()
3369                                            +", canot resolve xsi:type = " + xsiType+" ---2");
3370               } else {
3371                  TraverseSchema.ComplexTypeInfo typeInfo =
3372                  (TraverseSchema.ComplexTypeInfo) complexRegistry.get(uri+","+localpart);
3373
3374                  if (typeInfo==null) {
3375                     if (uri.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA) ) {
3376                        fXsiTypeValidator = dataTypeReg.getDatatypeValidator(localpart);
3377                     } else
3378                        fXsiTypeValidator = dataTypeReg.getDatatypeValidator(uri+","+localpart);
3379                     if ( fXsiTypeValidator == null )
3380                        reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3381                                                  XMLMessages.SCHEMA_GENERIC_ERROR,
3382                                                  "unresolved type : "+uri+","+localpart
3383                                                  +" found in xsi:type handling");
3384                     else if (elementIndex != -1) {
3385                        // make sure the new type is related to the
3386
// type of the expected element
3387
DatatypeValidator ancestorValidator = elementDatatypeValidator;
3388                        DatatypeValidator tempVal = fXsiTypeValidator;
3389                        for(; tempVal != null; tempVal = tempVal.getBaseValidator())
3390                            // WARNING!!! Comparison by reference.
3391
if(tempVal == ancestorValidator) break;
3392                        if(tempVal == null) {
3393                            // now if ancestorValidator is a union, then we must
3394
// look through its members to see whether we derive from any of them.
3395
if(ancestorValidator instanceof UnionDatatypeValidator) {
3396                                // fXsiTypeValidator must derive from one of its members...
3397
Vector JavaDoc subUnionMemberDV = ((UnionDatatypeValidator)ancestorValidator).getBaseValidators();
3398                                int subUnionSize = subUnionMemberDV.size();
3399                                boolean found = false;
3400                                for (int i=0; i<subUnionSize && !found; i++) {
3401                                    DatatypeValidator dTempSub = (DatatypeValidator)subUnionMemberDV.elementAt(i);
3402                                    DatatypeValidator dTemp = fXsiTypeValidator;
3403                                    for(; dTemp != null; dTemp = dTemp.getBaseValidator()) {
3404                                        // WARNING!!! This uses comparison by reference andTemp is thus inherently suspect!
3405
if(dTempSub == dTemp) {
3406                                            found = true;
3407                                            break;
3408                                        }
3409                                    }
3410                                    if (!found) {
3411                                        // if dTempSub is anySimpleType,
3412
// then the derivation is ok.
3413
if (dTempSub instanceof AnySimpleType) {
3414                                            found = true;
3415                                        }
3416                                    }
3417                                }
3418                                if(!found) {
3419                                    reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3420                                        XMLMessages.SCHEMA_GENERIC_ERROR,
3421                                        "Type : "+uri+","+localpart
3422                                        +" does not derive from the type of element " + fStringPool.toString(elementNameLocalPart));
3423                                }
3424                            } else
3425                            if ((ancestorValidator == null &&
3426                                 ((SchemaGrammar)fGrammar).getElementComplexTypeInfo(elementIndex) == null) ||
3427                                (ancestorValidator instanceof AnySimpleType)) {
3428                                // if ancestorValidator is anyType or anySimpleType,
3429
// then the derivation is ok.
3430
} else {
3431                                reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3432                                    XMLMessages.SCHEMA_GENERIC_ERROR,
3433                                    "Type : "+uri+","+localpart
3434                                    +" does not derive from the type of element " + fStringPool.toString(elementNameLocalPart));
3435                            }
3436                        } else {
3437                            // if we have an attribute but xsi:type's type is simple, we have a problem...
3438
if (tempVal != null && fXsiTypeValidator != null &&
3439                                    (fGrammar.getFirstAttributeDeclIndex(elementIndex) != -1)) {
3440                                reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3441                                    XMLMessages.SCHEMA_GENERIC_ERROR,
3442                                    "Type : "+uri+","+localpart
3443                                    +" does not derive from the type of element " + fStringPool.toString(elementNameLocalPart));
3444                            }
3445                            // check if element has block set
3446
if((((SchemaGrammar)fGrammar).getElementDeclBlockSet(elementIndex) & SchemaSymbols.RESTRICTION) != 0) {
3447                                reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3448                                    XMLMessages.SCHEMA_GENERIC_ERROR,
3449                                    "Element " + fStringPool.toString(elementNameLocalPart)
3450                                    + "does not permit substitution by a type such as "+uri+","+localpart);
3451                            }
3452                        }
3453                     }
3454                  } else {
3455
3456                     //
3457
// The type must not be abstract
3458
//
3459
if (typeInfo.isAbstractType()) {
3460                        reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3461                               XMLMessages.SCHEMA_GENERIC_ERROR,
3462                               "Abstract type " + xsiType + " should not be used in xsi:type");
3463                     }
3464                     if (elementIndex != -1) {
3465                         // now we look at whether there is a type
3466
// relation and whether the type (and element) allow themselves to be substituted for.
3467

3468                         TraverseSchema.ComplexTypeInfo tempType = typeInfo;
3469                         TraverseSchema.ComplexTypeInfo destType = ((SchemaGrammar)fGrammar).getElementComplexTypeInfo(elementIndex);
3470                         for(; tempType != null && destType != null; tempType = tempType.baseComplexTypeInfo) {
3471                            if(tempType.typeName.equals(destType.typeName))
3472                                break;
3473                         }
3474                         if(tempType == null) {
3475                            reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3476                                   XMLMessages.SCHEMA_GENERIC_ERROR,
3477                                    "Type : "+uri+","+localpart
3478                                    +" does not derive from the type " + destType.typeName);
3479                         } else if (destType == null && elementDatatypeValidator != null) {
3480                            // if the original type is a simple type, check derivation ok.
3481
DatatypeValidator ancestorValidator = elementDatatypeValidator;
3482                            DatatypeValidator tempVal = fXsiTypeValidator;
3483                            for(; tempVal != null; tempVal = tempVal.getBaseValidator())
3484                                // WARNING!!! Comparison by reference.
3485
if(tempVal == ancestorValidator) break;
3486                            if (tempVal == null) {
3487                                // if ancestorValidator is anyType or anySimpleType,
3488
// then the derivation is ok.
3489
if (ancestorValidator instanceof AnySimpleType) {
3490                                    tempVal = fXsiTypeValidator;
3491                                }
3492                            }
3493                            if(tempVal == null) {
3494                                // now if ancestorValidator is a union, then we must
3495
// look through its members to see whether we derive from any of them.
3496
if(ancestorValidator instanceof UnionDatatypeValidator) {
3497                                    // fXsiTypeValidator must derive from one of its members...
3498
Vector JavaDoc subUnionMemberDV = ((UnionDatatypeValidator)ancestorValidator).getBaseValidators();
3499                                    int subUnionSize = subUnionMemberDV.size();
3500                                    boolean found = false;
3501                                    for (int i=0; i<subUnionSize && !found; i++) {
3502                                        DatatypeValidator dTempSub = (DatatypeValidator)subUnionMemberDV.elementAt(i);
3503                                        DatatypeValidator dTemp = fXsiTypeValidator;
3504                                        for(; dTemp != null; dTemp = dTemp.getBaseValidator()) {
3505                                            // WARNING!!! This uses comparison by reference andTemp is thus inherently suspect!
3506
if(dTempSub == dTemp) {
3507                                                found = true;
3508                                                break;
3509                                            }
3510                                        }
3511                                        if (!found) {
3512                                            // if dTempSub is anySimpleType,
3513
// then the derivation is ok.
3514
if (dTempSub instanceof AnySimpleType) {
3515                                                found = true;
3516                                            }
3517                                        }
3518                                    }
3519                                    if(!found) {
3520                                        reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3521                                            XMLMessages.SCHEMA_GENERIC_ERROR,
3522                                            "Type : "+uri+","+localpart
3523                                            +" does not derive from the type of element " + fStringPool.toString(elementNameLocalPart));
3524                                    }
3525                                } else {
3526                                    reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3527                                        XMLMessages.SCHEMA_GENERIC_ERROR,
3528                                        "Type : "+uri+","+localpart
3529                                        +" does not derive from the type of element " + fStringPool.toString(elementNameLocalPart));
3530                                }
3531                            }
3532                         } else if (typeInfo != destType) { // now check whether the element or typeInfo's baseType blocks us.
3533
int derivationMethod = typeInfo.derivedBy;
3534                            if((((SchemaGrammar)fGrammar).getElementDeclBlockSet(elementIndex) & derivationMethod) != 0) {
3535                                reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3536                                   XMLMessages.SCHEMA_GENERIC_ERROR,
3537                                    "Element " + fStringPool.toString(elementNameLocalPart) +
3538                                    " does not permit xsi:type substitution in the manner required by type "+uri+","+localpart);
3539                            } else if (typeInfo.baseComplexTypeInfo != null &&
3540                                       (typeInfo.baseComplexTypeInfo.blockSet & derivationMethod) != 0) {
3541                                reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3542                                   XMLMessages.SCHEMA_GENERIC_ERROR,
3543                                    "Type " + typeInfo.baseComplexTypeInfo.typeName + " does not permit other types, such as "
3544                                    +uri+","+localpart + " to be substituted for itself using xsi:type");
3545                            }
3546                         }
3547                     }
3548                     elementIndex = typeInfo.templateElementIndex;
3549                  }
3550               }
3551
3552               fXsiTypeAttValue = -1;
3553            }
3554
3555            else if (elementIndex != -1) {
3556               //
3557
// xsi:type was not specified...
3558
// If the corresponding type is abstract, detect an error
3559
//
3560
TraverseSchema.ComplexTypeInfo typeInfo =
3561                 ((SchemaGrammar) fGrammar).getElementComplexTypeInfo(elementIndex);
3562
3563               if (typeInfo != null &&
3564                   typeInfo.isAbstractType()) {
3565                  reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3566                   XMLMessages.SCHEMA_GENERIC_ERROR,
3567                   "Element " + fStringPool.toString(element.rawname) + " is declared with a type that is abstract. Use xsi:type to specify a non-abstract type");
3568               }
3569            }
3570
3571            if (elementIndex != -1) {
3572                //
3573
// Check whether this element is abstract. If so, an error
3574
//
3575
int miscFlags = ((SchemaGrammar) fGrammar).getElementDeclMiscFlags(elementIndex);
3576                if ((miscFlags & SchemaSymbols.ABSTRACT) != 0) {
3577                  reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3578                    XMLMessages.SCHEMA_GENERIC_ERROR,
3579                    "A member of abstract element " + fStringPool.toString(element.rawname) + "'s substitution group must be specified");
3580                }
3581                if (fNil && (miscFlags & SchemaSymbols.NILLABLE) == 0 ) {
3582                    fNil = false;
3583                    reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3584                    XMLMessages.SCHEMA_GENERIC_ERROR,
3585                    "xsi:nil must not be specified for the element "+ fStringPool.toString(element.rawname)+
3586                                              " with {nillable} equals 'false'");
3587                }
3588                //Change the current scope to be the one defined by this element.
3589
fCurrentScope = ((SchemaGrammar) fGrammar).getElementDefinedScope(elementIndex);
3590
3591                // here need to check if we need to switch Grammar by asking SchemaGrammar whether
3592
// this element actually is of a type in another Schema.
3593
String JavaDoc anotherSchemaURI = ((SchemaGrammar)fGrammar).getElementFromAnotherSchemaURI(elementIndex);
3594                if (anotherSchemaURI != null) {
3595                   //before switch Grammar, set the elementIndex to be the template elementIndex of its type
3596
if (contentSpecType != -1) {
3597                      TraverseSchema.ComplexTypeInfo typeInfo = ((SchemaGrammar) fGrammar).getElementComplexTypeInfo(elementIndex);
3598                      if (typeInfo != null) {
3599                         elementIndex = typeInfo.templateElementIndex;
3600                      }
3601
3602                      // now switch the grammar
3603
fGrammarNameSpaceIndex = fCurrentSchemaURI = fStringPool.addSymbol(anotherSchemaURI);
3604                      boolean success = switchGrammar(fCurrentSchemaURI);
3605                      if (!success && !fNeedValidationOff) {
3606                         reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
3607                                                   XMLMessages.SCHEMA_GENERIC_ERROR,
3608                                                   "Grammar with uri: "
3609                                                   + fStringPool.toString(fCurrentSchemaURI)
3610                                                   + " , can not be found");
3611                      }
3612                    }
3613                }
3614
3615             }
3616         }
3617         // If the elementIndex changed since last time
3618
// we queried the content type, query it again.
3619
if (elementIndex != oldElementIndex)
3620             contentSpecType = getContentSpecType(elementIndex);
3621
3622         if (contentSpecType == -1 && fValidating && !fNeedValidationOff ) {
3623            reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_NOT_DECLARED,
3624                                      XMLMessages.VC_ELEMENT_VALID,
3625                                      element.rawname);
3626         }
3627         if (fGrammar != null && fGrammarIsSchemaGrammar && elementIndex != -1) {
3628            fAttrListHandle = addDefaultAttributes(elementIndex, attrList, fAttrListHandle, fValidating, fStandaloneReader != -1);
3629         }
3630         if (fAttrListHandle != -1) {
3631            //fAttrList.endAttrList();
3632
int dupAttrs[];
3633            if ((dupAttrs = fAttrList.endAttrList()) != null) {
3634               Object JavaDoc[] args = {fStringPool.toString(element.rawname), null};
3635               for (int i = 0; i < dupAttrs.length; i++) {
3636                   args[1] = fStringPool.toString(dupAttrs[i]);
3637                   fErrorReporter.reportError(fErrorReporter.getLocator(),
3638                                              XMLMessages.XMLNS_DOMAIN,
3639                                              XMLMessages.MSG_ATTRIBUTE_NOT_UNIQUE,
3640                                              XMLMessages.WFC_UNIQUE_ATT_SPEC,
3641                                              args,
3642                                              XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
3643               }
3644            }
3645         }
3646
3647         if (DEBUG_PRINT_ATTRIBUTES) {
3648            String JavaDoc elementStr = fStringPool.toString(element.rawname);
3649            System.out.print("startElement: <" + elementStr);
3650            if (fAttrListHandle != -1) {
3651               int index = attrList.getFirstAttr(fAttrListHandle);
3652               while (index != -1) {
3653                  System.out.print(" " + fStringPool.toString(attrList.getAttrName(index)) + "=\"" +
3654                                   fStringPool.toString(attrList.getAttValue(index)) + "\"");
3655                  index = attrList.getNextAttr(index);
3656               }
3657            }
3658            System.out.println(">");
3659         }
3660         if (fAttrListHandle != -1 && !fNeedValidationOff ) {
3661            int index = fAttrList.getFirstAttr(fAttrListHandle);
3662            while (index != -1) {
3663               int attrNameIndex = attrList.getAttrName(index);
3664
3665               // here, we validate every "user-defined" attributes
3666
int _xmlns = fStringPool.addSymbol("xmlns");
3667
3668               if (attrNameIndex != _xmlns && attrList.getAttrPrefix(index) != _xmlns)
3669                  if (fGrammar != null) {
3670                     fTempQName.setValues(attrList.getAttrPrefix(index),
3671                                          attrList.getAttrLocalpart(index),
3672                                          attrList.getAttrName(index),
3673                                          attrList.getAttrURI(index) );
3674                     int attDefIndex = getAttDefByElementIndex(elementIndex, fTempQName);
3675
3676                     if (fTempQName.uri != fXsiURI)
3677                        if (attDefIndex == -1 ) {
3678                           if (fValidating) {
3679                              // REVISIT - cache the elem/attr tuple so that we only give
3680
// this error once for each unique occurrence
3681
Object JavaDoc[] args = { fStringPool.toString(element.rawname),
3682                                 fStringPool.toString(attrList.getAttrName(index))};
3683
3684                              /*****/
3685                              fAttrNameLocator = getLocatorImpl(fAttrNameLocator);
3686
3687                              fErrorReporter.reportError(fAttrNameLocator,
3688                                                         XMLMessages.XML_DOMAIN,
3689                                                         XMLMessages.MSG_ATTRIBUTE_NOT_DECLARED,
3690                                                         XMLMessages.VC_ATTRIBUTE_VALUE_TYPE,
3691                                                         args,
3692                                                         XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
3693                              /******/
3694                           }
3695                        } else {
3696
3697                           fGrammar.getAttributeDecl(attDefIndex, fTempAttDecl);
3698
3699                           int attributeType = attributeTypeName(fTempAttDecl);
3700                           attrList.setAttType(index, attributeType);
3701
3702
3703                            if (fGrammarIsDTDGrammar) {
3704                                  int normalizedValue = validateDTDattribute(element, attrList.getAttValue(index), fTempAttDecl);
3705                                  attrList.setAttValue(index, normalizedValue);
3706
3707                            }
3708                            if (fValidating) {
3709                              // check to see if this attribute matched an attribute wildcard
3710
if (fGrammarIsDTDGrammar) {
3711                                  //do nothing
3712
}
3713                              else if ( fGrammarIsSchemaGrammar &&
3714                                        (fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_ANY
3715                                         ||fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_LIST
3716                                         ||fTempAttDecl.type == XMLAttributeDecl.TYPE_ANY_OTHER) ) {
3717
3718                                 if ((fTempAttDecl.defaultType & XMLAttributeDecl.PROCESSCONTENTS_SKIP) > 0) {
3719                                    // attribute should just be bypassed,
3720
} else if ( (fTempAttDecl.defaultType & XMLAttributeDecl.PROCESSCONTENTS_STRICT) > 0
3721                                             || (fTempAttDecl.defaultType & XMLAttributeDecl.PROCESSCONTENTS_LAX) > 0) {
3722
3723                                    boolean reportError = false;
3724                                    boolean processContentStrict =
3725                                    (fTempAttDecl.defaultType & XMLAttributeDecl.PROCESSCONTENTS_STRICT) > 0;
3726
3727                                    // ??? REVISIT: can't tell whether it's a local attribute
3728
// or a global one with empty namespace
3729
//if (fTempQName.uri == StringPool.EMPTY_STRING) {
3730
// if (processContentStrict) {
3731
// reportError = true;
3732
// }
3733
//} else {
3734
{
3735                                       Grammar aGrammar =
3736                                       fGrammarResolver.getGrammar(fStringPool.toString(fTempQName.uri));
3737
3738                                       if (aGrammar == null || !(aGrammar instanceof SchemaGrammar) ) {
3739                                          if (processContentStrict) {
3740                                             reportError = true;
3741                                          }
3742                                       } else {
3743                                          SchemaGrammar sGrammar = (SchemaGrammar) aGrammar;
3744                                          Hashtable JavaDoc attRegistry = sGrammar.getAttributeDeclRegistry();
3745                                          if (attRegistry == null) {
3746                                             if (processContentStrict) {
3747                                                reportError = true;
3748                                             }
3749                                          } else {
3750                                             XMLAttributeDecl attDecl = (XMLAttributeDecl) attRegistry.get(fStringPool.toString(fTempQName.localpart));
3751                                             if (attDecl == null) {
3752                                                if (processContentStrict) {
3753                                                   reportError = true;
3754                                                }
3755                                             } else {
3756                                                DatatypeValidator attDV = attDecl.datatypeValidator;
3757                                                if (attDV == null) {
3758                                                   if (processContentStrict) {
3759                                                      reportError = true;
3760                                                   }
3761                                                } else {
3762                                                   try {
3763                                                      String JavaDoc value = fStringPool.toString(attrList.getAttValue(index));
3764                                                      fWhiteSpace = attDV.getWSFacet();
3765                                                      if (fWhiteSpace != DatatypeValidator.PRESERVE) {
3766                                                            value = normalizeValue(value);
3767                                                      }
3768                                                       validateUsingDV(attDV, value, false);
3769                                                       if (fNormalizeContents) {
3770                                                            int normalizedValue = fStringPool.addString(value);
3771                                                            attrList.setAttValue(index,normalizedValue);
3772                                                       }
3773                                                   } catch (InvalidDatatypeValueException idve) {
3774                                                      fErrorReporter.reportError(fErrorReporter.getLocator(),
3775                                                                                 SchemaMessageProvider.SCHEMA_DOMAIN,
3776                                                                                 SchemaMessageProvider.DatatypeError,
3777                                                                                 SchemaMessageProvider.MSG_NONE,
3778                                                                                 new Object JavaDoc [] { idve.getMessage()},
3779                                                                                 XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
3780                                                   }
3781                                                }
3782                                             }
3783                                          }
3784                                       }
3785                                    }
3786                                    if (reportError) {
3787                                       Object JavaDoc[] args = { fStringPool.toString(element.rawname),
3788                                          "ANY---"+fStringPool.toString(attrList.getAttrName(index))};
3789
3790                                       fAttrNameLocator = getLocatorImpl(fAttrNameLocator);
3791
3792                                       fErrorReporter.reportError(fAttrNameLocator,
3793                                                                  XMLMessages.XML_DOMAIN,
3794                                                                  XMLMessages.MSG_ATTRIBUTE_NOT_DECLARED,
3795                                                                  XMLMessages.VC_ATTRIBUTE_VALUE_TYPE,
3796                                                                  args,
3797                                                                  XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
3798
3799                                    }
3800                                 }
3801                              } else if (fTempAttDecl.datatypeValidator == null) {
3802                                 Object JavaDoc[] args = { fStringPool.toString(element.rawname),
3803                                    fStringPool.toString(attrList.getAttrName(index))};
3804
3805                                 System.out.println("[Error] Datatypevalidator for attribute " + fStringPool.toString(attrList.getAttrName(index))
3806                                                    + " not found in element type " + fStringPool.toString(element.rawname));
3807                                 /****/
3808                                 fAttrNameLocator = getLocatorImpl(fAttrNameLocator);
3809
3810                                 fErrorReporter.reportError(fAttrNameLocator,
3811                                                            XMLMessages.XML_DOMAIN,
3812                                                            XMLMessages.MSG_ATTRIBUTE_NOT_DECLARED,
3813                                                            XMLMessages.VC_ATTRIBUTE_VALUE_TYPE,
3814                                                            args,
3815                                                            XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
3816                                 /****/
3817                              } else {
3818                                 try {
3819                                    String JavaDoc value = fStringPool.toString(attrList.getAttValue(index));
3820                                    DatatypeValidator tempDV = fTempAttDecl.datatypeValidator;
3821                                    fWhiteSpace = tempDV.getWSFacet();
3822                                    if (fWhiteSpace != DatatypeValidator.PRESERVE) {
3823                                        value = normalizeValue(value);
3824                                    }
3825                                    // if "fixed" is specified, then get the fixed string,
3826
// and compare over value space
3827
if ((fTempAttDecl.defaultType & XMLAttributeDecl.DEFAULT_TYPE_FIXED) > 0 &&
3828                                        tempDV.compare(value, fTempAttDecl.defaultValue) != 0) {
3829                                        Object JavaDoc[] args = { fStringPool.toString(element.rawname),
3830                                                          fStringPool.toString(attrList.getAttrName(index)),
3831                                                          value,
3832                                                          fTempAttDecl.defaultValue};
3833                                        fErrorReporter.reportError( fErrorReporter.getLocator(),
3834                                                                    XMLMessages.XML_DOMAIN,
3835                                                                    XMLMessages.MSG_FIXED_ATTVALUE_INVALID,
3836                                                                    XMLMessages.VC_FIXED_ATTRIBUTE_DEFAULT,
3837                                                                    args,
3838                                                                    XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
3839                                    }
3840                                    validateUsingDV(tempDV, value, false);
3841                                    if (fNormalizeContents) {
3842                                        int normalizedValue = fStringPool.addString(value);
3843                                        attrList.setAttValue(index,normalizedValue );
3844                                    }
3845                                 } catch (InvalidDatatypeValueException idve) {
3846                                    fErrorReporter.reportError(fErrorReporter.getLocator(),
3847                                                               SchemaMessageProvider.SCHEMA_DOMAIN,
3848                                                               SchemaMessageProvider.DatatypeError,
3849                                                               SchemaMessageProvider.MSG_NONE,
3850                                                               new Object JavaDoc [] { idve.getMessage()},
3851                                                               XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
3852                                 }
3853                              }
3854                           } // end of if (fValidating)
3855

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

3859                  }// end of if (fGrammar != null)
3860
index = fAttrList.getNextAttr(index);
3861            }
3862         }
3863      }
3864      if (fAttrListHandle != -1) {
3865         int index = attrList.getFirstAttr(fAttrListHandle);
3866         while (index != -1) {
3867            int attName = attrList.getAttrName(index);
3868            if (!fStringPool.equalNames(attName, fNamespacesPrefix)) {
3869               int attPrefix = attrList.getAttrPrefix(index);
3870               if (attPrefix != fNamespacesPrefix) {
3871                  if (attPrefix != -1) {
3872                     int uri = fNamespacesScope.getNamespaceForPrefix(attPrefix);
3873                     if (uri == StringPool.EMPTY_STRING) {
3874                        Object JavaDoc[] args = { fStringPool.toString(attPrefix)};
3875                        fErrorReporter.reportError(fErrorReporter.getLocator(),
3876                                                   XMLMessages.XMLNS_DOMAIN,
3877                                                   XMLMessages.MSG_PREFIX_DECLARED,
3878                                                   XMLMessages.NC_PREFIX_DECLARED,
3879                                                   args,
3880                                                   XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
3881                     }
3882                     attrList.setAttrURI(index, uri);
3883                  }
3884               }
3885            }
3886            index = attrList.getNextAttr(index);
3887         }
3888      }
3889
3890      fCurrentElementIndex = elementIndex;
3891      fCurrentContentSpecType = contentSpecType;
3892
3893      if (fValidating && contentSpecType == XMLElementDecl.TYPE_SIMPLE) {
3894         fBufferDatatype = true;
3895         fDatatypeBuffer.setLength(0);
3896      }
3897
3898      fInElementContent = (contentSpecType == XMLElementDecl.TYPE_CHILDREN);
3899
3900   } // validateElementAndAttributes(QName,XMLAttrList)
3901

3902
3903   /**
3904    * Validate attributes in DTD fashion.
3905    * Validation is separated from attribute value normalization (which is required
3906    * for non-validating parsers)
3907    * @return normalized attribute value
3908    */

3909   private int validateDTDattribute(QName element, int attValue,
3910                                     XMLAttributeDecl attributeDecl) throws Exception JavaDoc{
3911      AttributeValidator av = null;
3912      switch (attributeDecl.type) {
3913      case XMLAttributeDecl.TYPE_ENTITY:
3914         {
3915            boolean isAlistAttribute = attributeDecl.list;//Caveat - Save this information because invalidStandaloneAttDef
3916
String JavaDoc unTrimValue = fStringPool.toString(attValue);
3917            String JavaDoc value = unTrimValue.trim();
3918            if ( fValidationEnabled ) {
3919                if ( value != unTrimValue ) {
3920                    if ( invalidStandaloneAttDef(element, attributeDecl.name) ) {
3921                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
3922                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
3923                                                  fStringPool.toString(attributeDecl.name.rawname), unTrimValue, value);
3924                    }
3925                }
3926                try {
3927                    if ( isAlistAttribute ) {
3928                        fValENTITIES.validate( value, fValidateEntity );
3929                    }
3930                    else {
3931                        fValENTITY.validate( value, fValidateEntity );
3932                    }
3933                }
3934                catch ( InvalidDatatypeValueException ex ) {
3935                    if ( ex.getMajorCode() != 1 && ex.getMinorCode() != -1 ) {
3936                        reportRecoverableXMLError(ex.getMajorCode(),
3937                                                  ex.getMinorCode(),
3938                                                  fStringPool.toString( attributeDecl.name.rawname), value );
3939                    }
3940                    else {
3941                        reportRecoverableXMLError(XMLMessages.MSG_ENTITY_INVALID,
3942                                                  XMLMessages.VC_ENTITY_NAME,
3943                                                  fStringPool.toString( attributeDecl.name.rawname), value );
3944                    }
3945                }
3946            }
3947            if (fNormalizeAttributeValues) {
3948                if (attributeDecl.list) {
3949                    attValue = normalizeListAttribute(value, attValue, unTrimValue);
3950                } else {
3951                    if (value != unTrimValue) {
3952                        attValue = fStringPool.addSymbol(value);
3953                    }
3954                }
3955            }
3956         }
3957         break;
3958      case XMLAttributeDecl.TYPE_ENUMERATION:
3959         av = fAttValidatorENUMERATION;
3960         break;
3961      case XMLAttributeDecl.TYPE_ID:
3962         {
3963            String JavaDoc unTrimValue = fStringPool.toString(attValue);
3964            String JavaDoc value = unTrimValue.trim();
3965            if ( fValidationEnabled ) {
3966                if ( value != unTrimValue ) {
3967                    if ( invalidStandaloneAttDef(element, attributeDecl.name) ) {
3968                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
3969                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
3970                                                  fStringPool.toString(attributeDecl.name.rawname), unTrimValue, value);
3971                    }
3972                }
3973
3974                try {
3975                    fValID.validate( value, fIdDefs );
3976                    fValIDRef.validate( value, this.fValidateIDRef ); //just in case we called id after IDREF
3977
}
3978                catch ( InvalidDatatypeValueException ex ) {
3979                    int major = ex.getMajorCode(), minor = ex.getMinorCode();
3980                    if ( major == -1 ) {
3981                        major = XMLMessages.MSG_ID_INVALID;
3982                        minor = XMLMessages.VC_ID;
3983                    }
3984                    reportRecoverableXMLError(major, minor,
3985                                              fStringPool.toString( attributeDecl.name.rawname),
3986                                              value );
3987                }
3988            }
3989
3990            if (fNormalizeAttributeValues && value != unTrimValue) {
3991                attValue = fStringPool.addSymbol(value);
3992            }
3993         }
3994         break;
3995      case XMLAttributeDecl.TYPE_IDREF:
3996         {
3997            String JavaDoc unTrimValue = fStringPool.toString(attValue);
3998            String JavaDoc value = unTrimValue.trim();
3999            boolean isAlistAttribute = attributeDecl.list;//Caveat - Save this information because invalidStandaloneAttDef
4000
//changes fTempAttDef
4001
if ( fValidationEnabled ) {
4002                if ( value != unTrimValue ) {
4003                    if ( invalidStandaloneAttDef(element, attributeDecl.name) ) {
4004                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
4005                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
4006                                                  fStringPool.toString(attributeDecl.name.rawname), unTrimValue, value);
4007                    }
4008                }
4009
4010                if ( attributeDecl.list && value.length() == 0 ) {
4011                    reportRecoverableXMLError(XMLMessages.MSG_IDREFS_INVALID, XMLMessages.VC_IDREF,
4012                                              fStringPool.toString(attributeDecl.name.rawname) ) ;
4013                }
4014
4015                try {
4016                    if ( isAlistAttribute ) {
4017                        fValIDRefs.validate( value, this.fValidateIDRef );
4018                    }
4019                    else {
4020                        fValIDRef.validate( value, this.fValidateIDRef );
4021                    }
4022                }
4023                catch ( InvalidDatatypeValueException ex ) {
4024                    if ( ex.getMajorCode() != 1 && ex.getMinorCode() != -1 ) {
4025                        reportRecoverableXMLError(ex.getMajorCode(),
4026                                                  ex.getMinorCode(),
4027                                                  fStringPool.toString( attributeDecl.name.rawname), value );
4028                    }
4029                    else {
4030                        reportRecoverableXMLError(XMLMessages.MSG_IDREFS_INVALID,
4031                                                  XMLMessages.VC_IDREF,
4032                                                  fStringPool.toString( attributeDecl.name.rawname), value );
4033                    }
4034                }
4035            }
4036            if (fNormalizeAttributeValues) {
4037                if (attributeDecl.list) {
4038                    attValue = normalizeListAttribute(value, attValue, unTrimValue);
4039                } else {
4040                    if (value != unTrimValue) {
4041                        attValue = fStringPool.addSymbol(value);
4042                    }
4043                }
4044            }
4045         }
4046         break;
4047      case XMLAttributeDecl.TYPE_NOTATION:
4048         {
4049            /* WIP
4050            String unTrimValue = fStringPool.toString(attValue);
4051         String value = unTrimValue.trim();
4052         if (fValidationEnabled) {
4053             if (value != unTrimValue) {
4054                 if (invalidStandaloneAttDef(element, attributeDecl.name)) {
4055                     reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
4056                                               XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
4057                                               fStringPool.toString(attributeDecl.name.rawname), unTrimValue, value);
4058                 }
4059             }
4060         }
4061      }
4062        */

4063            av = fAttValidatorNOTATION;
4064         }
4065         break;
4066      case XMLAttributeDecl.TYPE_NMTOKEN:
4067         {
4068            String JavaDoc unTrimValue = fStringPool.toString(attValue);
4069            String JavaDoc value = unTrimValue.trim();
4070            boolean isAlistAttribute = attributeDecl.list;//Caveat - Save this information because invalidStandaloneAttDef
4071
//changes fTempAttDef
4072
if ( fValidationEnabled ) {
4073                if ( value != unTrimValue ) {
4074                    if ( invalidStandaloneAttDef(element, attributeDecl.name) ) {
4075                        reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
4076                                                  XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
4077                                                  fStringPool.toString(attributeDecl.name.rawname), unTrimValue, value);
4078                    }
4079                }
4080                if ( attributeDecl.list && value.length() == 0 ) {
4081                    reportRecoverableXMLError(XMLMessages.MSG_NMTOKENS_INVALID, XMLMessages.VC_NAME_TOKEN,
4082                                              fStringPool.toString(attributeDecl.name.rawname) ) ;
4083                }
4084
4085                try {
4086                    if ( isAlistAttribute ) {
4087                        fValNMTOKENS.validate( value, null );
4088                    }
4089                    else {
4090                        fValNMTOKEN.validate( value, null );
4091                    }
4092                }
4093                catch ( InvalidDatatypeValueException ex ) {
4094                    reportRecoverableXMLError(XMLMessages.MSG_NMTOKEN_INVALID,
4095                                              XMLMessages.VC_NAME_TOKEN,
4096                                              fStringPool.toString(attributeDecl.name.rawname), value);//TODO NMTOKENS messge
4097
}
4098            }
4099            if (fNormalizeAttributeValues) {
4100                if (attributeDecl.list) {
4101                    attValue = normalizeListAttribute(value, attValue, unTrimValue);
4102                } else {
4103                    if (value != unTrimValue) {
4104                        attValue = fStringPool.addSymbol(value);
4105                    }
4106                }
4107            }
4108         }
4109         break;
4110      }
4111      if ( av != null ) {
4112          int newValue = av.normalize(element, attributeDecl.name, attValue,
4113                                  attributeDecl.type, attributeDecl.enumeration);
4114          if (fNormalizeAttributeValues)
4115              attValue = newValue;
4116      }
4117      return attValue;
4118   }
4119
4120   /**
4121    * @param value This is already trimmed.
4122    */

4123   private int normalizeListAttribute(String JavaDoc value, int origIndex, String JavaDoc unTrimValue) {
4124
4125       //REVISIT: some code might be shared: see normalizeWhitespace()
4126
//
4127
fNormalizedStr.setLength(0);
4128       int length = value.length();
4129       boolean skipSpace = true;
4130       char c= 0;
4131
4132       for (int i = 0; i < length; i++) {
4133            c = value.charAt(i);
4134            if (c == 0x20) {
4135                if (!skipSpace) {
4136                    // take the first whitespace as a space and skip the others
4137
fNormalizedStr.append(' ');
4138                    skipSpace = true;
4139                }
4140            }
4141            else {
4142                fNormalizedStr.append((char)c);
4143                skipSpace = false;
4144            }
4145       }
4146       if (fNormalizedStr.length() == unTrimValue.length())
4147           return origIndex;
4148       return fStringPool.addSymbol(fNormalizedStr.toString());
4149   }
4150
4151   /** Character data in content. */
4152   private void charDataInContent() {
4153
4154      if (DEBUG_ELEMENT_CHILDREN) {
4155         System.out.println("charDataInContent()");
4156      }
4157      if (fElementChildren.length <= fElementChildrenLength) {
4158         QName[] newarray = new QName[fElementChildren.length * 2];
4159         System.arraycopy(fElementChildren, 0, newarray, 0, fElementChildren.length);
4160         fElementChildren = newarray;
4161      }
4162      QName qname = fElementChildren[fElementChildrenLength];
4163      if (qname == null) {
4164         for (int i = fElementChildrenLength; i < fElementChildren.length; i++) {
4165            fElementChildren[i] = new QName();
4166         }
4167         qname = fElementChildren[fElementChildrenLength];
4168      }
4169      qname.clear();
4170      fElementChildrenLength++;
4171
4172   } // charDataInCount()
4173

4174   /**
4175    * Check that the content of an element is valid.
4176    * <p>
4177    * This is the method of primary concern to the validator. This method is called
4178    * upon the scanner reaching the end tag of an element. At that time, the
4179    * element's children must be structurally validated, so it calls this method.
4180    * The index of the element being checked (in the decl pool), is provided as
4181    * well as an array of element name indexes of the children. The validator must
4182    * confirm that this element can have these children in this order.
4183    * <p>
4184    * This can also be called to do 'what if' testing of content models just to see
4185    * if they would be valid.
4186    * <p>
4187    * Note that the element index is an index into the element decl pool, whereas
4188    * the children indexes are name indexes, i.e. into the string pool.
4189    * <p>
4190    * A value of -1 in the children array indicates a PCDATA node. All other
4191    * indexes will be positive and represent child elements. The count can be
4192    * zero, since some elements have the EMPTY content model and that must be
4193    * confirmed.
4194    *
4195    * @param elementIndex The index within the <code>ElementDeclPool</code> of this
4196    * element.
4197    * @param childCount The number of entries in the <code>children</code> array.
4198    * @param children The children of this element. Each integer is an index within
4199    * the <code>StringPool</code> of the child element name. An index
4200    * of -1 is used to indicate an occurrence of non-whitespace character
4201    * data.
4202    *
4203    * @return The value -1 if fully valid, else the 0 based index of the child
4204    * that first failed. If the value returned is equal to the number
4205    * of children, then additional content is required to reach a valid
4206    * ending state.
4207    *
4208    * @exception Exception Thrown on error.
4209    */

4210   private int checkContent(int elementIndex,
4211                            QName[] children,
4212                            int childOffset,
4213                            int childCount) throws Exception JavaDoc {
4214
4215      // Get the element name index from the element
4216
// REVISIT: Validation
4217
final int elementType = fCurrentElement.rawname;
4218
4219      if (DEBUG_PRINT_CONTENT) {
4220         String JavaDoc strTmp = fStringPool.toString(elementType);
4221         System.out.println("Name: "+strTmp+", "+
4222                            "Count: "+childCount+", "+
4223                            "ContentSpecType: " +fCurrentContentSpecType); //+getContentSpecAsString(elementIndex));
4224
for (int index = childOffset; index < (childOffset+childCount) && index < 10; index++) {
4225            if (index == 0) {
4226               System.out.print(" (");
4227            }
4228            String JavaDoc childName = (children[index].localpart == -1) ? "#PCDATA" : fStringPool.toString(children[index].localpart);
4229            if (index + 1 == childCount) {
4230               System.out.println(childName + ")");
4231            } else if (index + 1 == 10) {
4232               System.out.println(childName + ",...)");
4233            } else {
4234               System.out.print(childName + ",");
4235            }
4236         }
4237      }
4238
4239      // Get out the content spec for this element
4240
final int contentType = fCurrentContentSpecType;
4241
4242      //
4243
// Deal with the possible types of content. We try to optimized here
4244
// by dealing specially with content models that don't require the
4245
// full DFA treatment.
4246
//
4247
if (contentType == XMLElementDecl.TYPE_EMPTY) {
4248         //
4249
// If the child count is greater than zero, then this is
4250
// an error right off the bat at index 0.
4251
//
4252
if (childCount != 0) {
4253            return 0;
4254         }
4255      } else if (contentType == XMLElementDecl.TYPE_ANY) {
4256         //
4257
// This one is open game so we don't pass any judgement on it
4258
// at all. Its assumed to fine since it can hold anything.
4259
//
4260
} else if (contentType == XMLElementDecl.TYPE_MIXED_SIMPLE ||
4261                 contentType == XMLElementDecl.TYPE_MIXED_COMPLEX ||
4262                 contentType == XMLElementDecl.TYPE_CHILDREN) {
4263
4264          // XML Schema REC: Validation Rule: Element Locally Valid (Element)
4265
// 3.2.1 The element information item must have no
4266
// character or element information item [children].
4267
//
4268
if (childCount == 0 && fNil) {
4269              fNil = false;
4270              //return success
4271
return -1;
4272          }
4273
4274          // Get the content model for this element, faulting it in if needed
4275
XMLContentModel cmElem = null;
4276         try {
4277            cmElem = getElementContentModel(elementIndex);
4278            int curState = fContentModelStateStack[fElementDepth+1];
4279            // if state!=-2, we have validate the children
4280
if (curState != -2) {
4281                // if state==-1, there is invalid child
4282
// if !finalState, then the content is not complete
4283
// both indicate an error, we return successful element count
4284
if (curState == -1 ||
4285                    !((DFAContentModel)cmElem).isFinalState(curState)) {
4286                    return fContentModelEleCount[fElementDepth+1];
4287                } else {
4288                    // otherwise -1: succeeded
4289
return -1;
4290                }
4291            }
4292            //otherwise, we need to validateContent
4293
int result = cmElem.validateContent(children, childOffset, childCount);
4294            if (result != -1 && fGrammarIsSchemaGrammar) {
4295               result = cmElem.validateContentSpecial(children, childOffset, childCount);
4296            }
4297            return result;
4298         } catch (CMException excToCatch) {
4299            // REVISIT - Translate the caught exception to the protected error API
4300
int majorCode = excToCatch.getErrorCode();
4301            fErrorReporter.reportError(fErrorReporter.getLocator(),
4302                                       ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
4303                                       majorCode,
4304                                       0,
4305                                       null,
4306                                       XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
4307         }
4308      } else if (contentType == -1) {
4309         reportRecoverableXMLError(XMLMessages.MSG_ELEMENT_NOT_DECLARED,
4310                                   XMLMessages.VC_ELEMENT_VALID,
4311                                   elementType);
4312      } else if (contentType == XMLElementDecl.TYPE_SIMPLE ) {
4313
4314         XMLContentModel cmElem = null;
4315         if (childCount > 0) {
4316            fErrorReporter.reportError(fErrorReporter.getLocator(),
4317                                       SchemaMessageProvider.SCHEMA_DOMAIN,
4318                                       SchemaMessageProvider.DatatypeError,
4319                                       SchemaMessageProvider.MSG_NONE,
4320                                       new Object JavaDoc [] { "In element '"+fStringPool.toString(elementType)+"' : "+
4321                                          "Can not have element children within a simple type content"},
4322                                       XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
4323         } else {
4324            try {
4325
4326                if (fCurrentDV == null ) { //no character data
4327
fGrammar.getElementDecl(elementIndex, fTempElementDecl);
4328                    fCurrentDV = fTempElementDecl.datatypeValidator;
4329                }
4330
4331                // If there is xsi:type validator, substitute it.
4332
if ( fXsiTypeValidator != null ) {
4333                  fCurrentDV = fXsiTypeValidator;
4334                  fXsiTypeValidator = null;
4335               }
4336               if (fCurrentDV == null) {
4337                  System.out.println("Internal Error: this element have a simpletype "+
4338                                     "but no datatypevalidator was found, element "+fTempElementDecl.name
4339                                     +",locapart: "+fStringPool.toString(fTempElementDecl.name.localpart));
4340               } else {
4341                   String JavaDoc value = fDatatypeBuffer.toString();
4342                   if (!fNormalizeContents && fWhiteSpace != DatatypeValidator.PRESERVE) {
4343                       // normalize data before validating it
4344
fUnnormalizedStr.setLength(0);
4345                       fUnnormalizedStr.append(value);
4346                       normalizeWhitespace(fUnnormalizedStr, (fWhiteSpace==DatatypeValidator.COLLAPSE));
4347                       value = fNormalizedStr.toString();
4348                   }
4349                   String JavaDoc currentElementDefault = ((SchemaGrammar)fGrammar).getElementDefaultValue(fCurrentElementIndex);
4350                   int hasFixed = (((SchemaGrammar)fGrammar).getElementDeclMiscFlags(fCurrentElementIndex) & SchemaSymbols.FIXED);
4351                   if (fNil) {
4352                       if (value.length() != 0) {
4353                         reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
4354                                                 XMLMessages.SCHEMA_GENERIC_ERROR,
4355                                                 "An element <" +fStringPool.toString(elementType)+"> with attribute xsi:nil=\"true\" must be empty");
4356                       }
4357                       if (hasFixed !=0) {
4358                           reportRecoverableXMLError(XMLMessages.MSG_GENERIC_SCHEMA_ERROR,
4359                             XMLMessages.SCHEMA_GENERIC_ERROR,
4360                             "An element <" +fStringPool.toString(elementType)+"> with attribute xsi:nil=\"true\" must not have fixed value constraint");
4361                       }
4362                       fNil = false;
4363                       return -1;
4364                   }
4365                   // check for fixed/default values of elements here.
4366
if( currentElementDefault == null || currentElementDefault.length() == 0) {
4367                            validateUsingDV(fCurrentDV, value, false);
4368                    }
4369                    else {
4370                        if (hasFixed !=0) {
4371                            if ( value.length() == 0 ) { // use fixed as default value
4372
// Note: this is inefficient where the DOMParser
4373
// is concerned. However, if we used the characters(int)
4374
// callback instead, this would be just as inefficient for SAX.
4375
fDocumentHandler.characters(currentElementDefault.toCharArray(), 0, currentElementDefault.length());
4376                                validateUsingDV(fCurrentDV, currentElementDefault, true);
4377                            }
4378                            else { // must check in valuespace!
4379
if ( fCurrentDV.compare(value, currentElementDefault) != 0 ) {
4380                                    fErrorReporter.reportError(fErrorReporter.getLocator(),
4381                                                               SchemaMessageProvider.SCHEMA_DOMAIN,
4382                                                               SchemaMessageProvider.FixedDiffersFromActual,
4383                                                               0, null,
4384                                                               XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
4385                                }
4386                                validateUsingDV(fCurrentDV, value, true);
4387                            }
4388                        }
4389                        else {
4390                            if ( value.length() == 0) { // use default value
4391
fDocumentHandler.characters(currentElementDefault.toCharArray(), 0, currentElementDefault.length());
4392                                validateUsingDV(fCurrentDV, currentElementDefault, true);
4393                            }
4394                            else {
4395                                validateUsingDV(fCurrentDV, value, false);
4396                            }
4397                        }
4398                    }
4399               }
4400            } catch (InvalidDatatypeValueException idve) {
4401               fErrorReporter.reportError(fErrorReporter.getLocator(),
4402                                          SchemaMessageProvider.SCHEMA_DOMAIN,
4403                                          SchemaMessageProvider.DatatypeError,
4404                                          SchemaMessageProvider.MSG_NONE,
4405                                          new Object JavaDoc [] { "In element '"+fStringPool.toString(elementType)+"' : "+idve.getMessage()},
4406                                          XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
4407            }
4408
4409            fCurrentDV = null;
4410            fFirstChunk= true;
4411            fTrailing=false;
4412         }
4413      } else {
4414         fErrorReporter.reportError(fErrorReporter.getLocator(),
4415                                    ImplementationMessages.XERCES_IMPLEMENTATION_DOMAIN,
4416                                    ImplementationMessages.VAL_CST,
4417                                    0,
4418                                    null,
4419                                    XMLErrorReporter.ERRORTYPE_FATAL_ERROR);
4420      }
4421
4422      // We succeeded
4423
return -1;
4424
4425   } // checkContent(int,int,int[]):int
4426

4427
4428   /**
4429    * Checks that all declared elements refer to declared elements
4430    * in their content models. This method calls out to the error
4431    * handler to indicate warnings.
4432    */

4433   /*private void checkDeclaredElements() throws Exception {
4434
4435               //****DEBUG****
4436               if (DEBUG) print("(???) XMLValidator.checkDeclaredElements\n");
4437               //****DEBUG****
4438
4439       for (int i = 0; i < fElementCount; i++) {
4440           int type = fGrammar.getContentSpecType(i);
4441           if (type == XMLElementDecl.TYPE_MIXED_SIMPLE ||
4442               type == XMLElementDecl.TYPE_MIXED_COMPLEX ||
4443               type == XMLElementDecl.TYPE_CHILDREN) {
4444               int chunk = i >> CHUNK_SHIFT;
4445               int index = i & CHUNK_MASK;
4446               int contentSpecIndex = fContentSpec[chunk][index];
4447               checkDeclaredElements(i, contentSpecIndex);
4448           }
4449       }
4450   }
4451   */

4452
4453   private void printChildren() {
4454      if (DEBUG_ELEMENT_CHILDREN) {
4455         System.out.print('[');
4456         for (int i = 0; i < fElementChildrenLength; i++) {
4457            System.out.print(' ');
4458            QName qname = fElementChildren[i];
4459            if (qname != null) {
4460               System.out.print(fStringPool.toString(qname.rawname));
4461            } else {
4462               System.out.print("null");
4463            }
4464            if (i < fElementChildrenLength - 1) {
4465               System.out.print(", ");
4466            }
4467            System.out.flush();
4468         }
4469         System.out.print(" ]");
4470         System.out.println();
4471      }
4472   }
4473
4474   private void printStack() {
4475      if (DEBUG_ELEMENT_CHILDREN) {
4476         System.out.print('{');
4477         for (int i = 0; i <= fElementDepth; i++) {
4478            System.out.print(' ');
4479            System.out.print(fElementChildrenOffsetStack[i]);
4480            if (i < fElementDepth) {
4481               System.out.print(", ");
4482            }
4483            System.out.flush();
4484         }
4485         System.out.print(" }");
4486         System.out.println();
4487      }
4488   }
4489
4490
4491   //
4492
// Interfaces
4493
//
4494

4495   /**
4496    * AttributeValidator.
4497    */

4498   public interface AttributeValidator {
4499
4500      //
4501
// AttributeValidator methods
4502
//
4503

4504      /** Normalize. */
4505      public int normalize(QName element, QName attribute,
4506                           int attValue, int attType, int enumHandle)
4507      throws Exception JavaDoc;
4508
4509   } // interface AttributeValidator
4510

4511
4512   /** Returns true if invalid standalone attribute definition. */
4513   boolean invalidStandaloneAttDef(QName element, QName attribute) {
4514      if (fStandaloneReader == -1) {
4515         return false;
4516      }
4517      // we are normalizing a default att value... this ok?
4518
if (element.rawname == -1) {
4519         return false;
4520      }
4521      return getAttDefIsExternal(element, attribute);
4522   }
4523
4524   void validateUsingDV (DatatypeValidator dv, String JavaDoc content, boolean onlyVal3Types)
4525       throws Exception JavaDoc, InvalidDatatypeValueException {
4526       if (dv instanceof IDDatatypeValidator) {
4527           dv.validate( content, fIdDefs );
4528       } else if (dv instanceof IDREFDatatypeValidator) {
4529           dv.validate( content, fValidateIDRef );
4530       } else if (dv instanceof ENTITYDatatypeValidator) {
4531           dv.validate( content, fValidateEntity);
4532       } else if (!onlyVal3Types) {
4533           if (dv instanceof NOTATIONDatatypeValidator && content != null) {
4534               content = bindNotationURI(content);
4535           }
4536           dv.validate( content, null);
4537       }
4538   }
4539
4540   //
4541
// Classes
4542
//
4543

4544
4545   /**
4546    * AttValidatorNOTATION.
4547    */

4548   final class AttValidatorNOTATION
4549   implements AttributeValidator {
4550
4551       //REVISIT: it looks like a redundant class
4552
//
4553

4554      //
4555
// AttributeValidator methods
4556
//
4557

4558      /** Normalize. */
4559      public int normalize(QName element, QName attribute,
4560                           int attValueHandle, int attType,
4561                           int enumHandle) throws Exception JavaDoc {
4562         //
4563
// Normalize attribute based upon attribute type...
4564
//
4565
String JavaDoc attValue = fStringPool.toString(attValueHandle);
4566         String JavaDoc newAttValue = attValue.trim();
4567         if (fValidating) {
4568            // REVISIT - can we release the old string?
4569
if (newAttValue != attValue) {
4570               if (invalidStandaloneAttDef(element, attribute)) {
4571                  reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
4572                                            XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
4573                                            fStringPool.toString(attribute.rawname), attValue, newAttValue);
4574               }
4575               attValueHandle = fStringPool.addSymbol(newAttValue);
4576            } else {
4577               attValueHandle = fStringPool.addSymbol(attValueHandle);
4578            }
4579            //
4580
// NOTATION - check that the value is in the AttDef enumeration (V_TAGo)
4581
//
4582
if (!fStringPool.stringInList(enumHandle, attValueHandle)) {
4583               reportRecoverableXMLError(XMLMessages.MSG_ATTRIBUTE_VALUE_NOT_IN_LIST,
4584                                         XMLMessages.VC_NOTATION_ATTRIBUTES,
4585                                         fStringPool.toString(attribute.rawname),
4586                                         newAttValue, fStringPool.stringListAsString(enumHandle));
4587            }
4588         } else if (newAttValue != attValue) {
4589            // REVISIT - can we release the old string?
4590
attValueHandle = fStringPool.addSymbol(newAttValue);
4591         }
4592         return attValueHandle;
4593
4594      } // normalize(QName,QName,int,int,int):int
4595

4596      //
4597
// Package methods
4598
//
4599

4600      /** Returns true if invalid standalone attribute definition. */
4601      boolean invalidStandaloneAttDef(QName element, QName attribute) {
4602         if (fStandaloneReader == -1) {
4603            return false;
4604         }
4605         // we are normalizing a default att value... this ok?
4606
if (element.rawname == -1) {
4607            return false;
4608         }
4609         return getAttDefIsExternal(element, attribute);
4610      }
4611
4612   } // class AttValidatorNOTATION
4613

4614   /**
4615    * AttValidatorENUMERATION.
4616    */

4617   final class AttValidatorENUMERATION
4618   implements AttributeValidator {
4619
4620       //REVISIT: it looks like a redundant class.
4621
// could be just a method. See also AttValidatorNOTATION
4622
//
4623
// AttributeValidator methods
4624
//
4625

4626      /** Normalize. */
4627      public int normalize(QName element, QName attribute,
4628                           int attValueHandle, int attType,
4629                           int enumHandle) throws Exception JavaDoc {
4630         //
4631
// Normalize attribute based upon attribute type...
4632
//
4633
String JavaDoc attValue = fStringPool.toString(attValueHandle);
4634         String JavaDoc newAttValue = attValue.trim();
4635         if (fValidating) {
4636            // REVISIT - can we release the old string?
4637
if (newAttValue != attValue) {
4638               if (invalidStandaloneAttDef(element, attribute)) {
4639                  reportRecoverableXMLError(XMLMessages.MSG_ATTVALUE_CHANGED_DURING_NORMALIZATION_WHEN_STANDALONE,
4640                                            XMLMessages.VC_STANDALONE_DOCUMENT_DECLARATION,
4641                                            fStringPool.toString(attribute.rawname), attValue, newAttValue);
4642               }
4643               attValueHandle = fStringPool.addSymbol(newAttValue);
4644            } else {
4645               attValueHandle = fStringPool.addSymbol(attValueHandle);
4646            }
4647            //
4648
// ENUMERATION - check that value is in the AttDef enumeration (V_TAG9)
4649
//
4650
if (!fStringPool.stringInList(enumHandle, attValueHandle)) {
4651               reportRecoverableXMLError(XMLMessages.MSG_ATTRIBUTE_VALUE_NOT_IN_LIST,
4652                                         XMLMessages.VC_ENUMERATION,
4653                                         fStringPool.toString(attribute.rawname),
4654                                         newAttValue, fStringPool.stringListAsString(enumHandle));
4655            }
4656         } else if (newAttValue != attValue) {
4657            // REVISIT - can we release the old string?
4658
attValueHandle = fStringPool.addSymbol(newAttValue);
4659         }
4660         return attValueHandle;
4661
4662      } // normalize(QName,QName,int,int,int):int
4663

4664      //
4665
// Package methods
4666
//
4667

4668      /** Returns true if invalid standalone attribute definition. */
4669      boolean invalidStandaloneAttDef(QName element, QName attribute) {
4670         if (fStandaloneReader == -1) {
4671            return false;
4672         }
4673         // we are normalizing a default att value... this ok?
4674
if (element.rawname == -1) {
4675            return false;
4676         }
4677         return getAttDefIsExternal(element, attribute);
4678      }
4679
4680   } // class AttValidatorENUMERATION
4681

4682    // xpath matcher information
4683

4684    /**
4685     * Stack of XPath matchers for identity constraints.
4686     *
4687     * @author Andy Clark, IBM
4688     */

4689    protected static class XPathMatcherStack {
4690
4691        //
4692
// Data
4693
//
4694

4695        /** Active matchers. */
4696        protected XPathMatcher[] fMatchers = new XPathMatcher[4];
4697
4698        /** Count of active matchers. */
4699        protected int fMatchersCount;
4700
4701        /** Offset stack for contexts. */
4702        protected IntStack fContextStack = new IntStack();
4703
4704        //
4705
// Constructors
4706
//
4707

4708        public XPathMatcherStack() {
4709        } // <init>()
4710

4711        //
4712
// Public methods
4713
//
4714

4715        /** Resets the XPath matcher stack. */
4716        public void clear() {
4717            for (int i = 0; i < fMatchersCount; i++) {
4718                fMatchers[i] = null;
4719            }
4720            fMatchersCount = 0;
4721            fContextStack.clear();
4722        } // clear()
4723

4724        /** Returns the size of the stack. */
4725        public int size() {
4726            return fContextStack.size();
4727        } // size():int
4728

4729        /** Returns the count of XPath matchers. */
4730        public int getMatcherCount() {
4731            return fMatchersCount;
4732        } // getMatcherCount():int
4733

4734        /** Adds a matcher. */
4735        public void addMatcher(XPathMatcher matcher) {
4736            ensureMatcherCapacity();
4737            fMatchers[fMatchersCount++] = matcher;
4738        } // addMatcher(XPathMatcher)
4739

4740        /** Returns the XPath matcher at the specified index. */
4741        public XPathMatcher getMatcherAt(int index) {
4742            return fMatchers[index];
4743        } // getMatcherAt(index):XPathMatcher
4744

4745        /** Pushes a new context onto the stack. */
4746        public void pushContext() {
4747            fContextStack.push(fMatchersCount);
4748        } // pushContext()
4749

4750        /** Pops a context off of the stack. */
4751        public void popContext() {
4752            fMatchersCount = fContextStack.pop();
4753        } // popContext()
4754

4755        //
4756
// Private methods
4757
//
4758

4759        /** Ensures the size of the matchers array. */
4760        private void ensureMatcherCapacity() {
4761            if (fMatchersCount == fMatchers.length) {
4762                XPathMatcher[] array = new XPathMatcher[fMatchers.length * 2];
4763                System.arraycopy(fMatchers, 0, array, 0, fMatchers.length);
4764                fMatchers = array;
4765            }
4766        } // ensureMatcherCapacity()
4767

4768    } // class XPathMatcherStack
4769

4770    // value store implementations
4771

4772    /**
4773     * Value store implementation base class. There are specific subclasses
4774     * for handling unique, key, and keyref.
4775     *
4776     * @author Andy Clark, IBM
4777     */

4778    protected abstract class ValueStoreBase
4779        implements ValueStore {
4780
4781        //
4782
// Constants
4783
//
4784

4785        /** Not a value (Unicode: #FFFF). */
4786        protected IDValue NOT_AN_IDVALUE = new IDValue("\uFFFF", null);
4787
4788        //
4789
// Data
4790
//
4791

4792        /** Identity constraint. */
4793        protected IdentityConstraint fIdentityConstraint;
4794
4795        /** Current data values. */
4796        protected final OrderedHashtable fValues = new OrderedHashtable();
4797
4798        /** Current data value count. */
4799        protected int fValuesCount;
4800
4801        /** Data value tuples. */
4802        protected final Vector JavaDoc fValueTuples = new Vector JavaDoc();
4803
4804        //
4805
// Constructors
4806
//
4807

4808        /** Constructs a value store for the specified identity constraint. */
4809        protected ValueStoreBase(IdentityConstraint identityConstraint) {
4810            fIdentityConstraint = identityConstraint;
4811        } // <init>(IdentityConstraint)
4812

4813        //
4814
// Public methods
4815
//
4816

4817        // destroys this ValueStore; useful when, for instanc,e a
4818
// locally-scoped ID constraint is involved.
4819
public void destroy() {
4820            fValuesCount = 0;
4821            fValues.clear();
4822            fValueTuples.removeAllElements();
4823        } // end destroy():void
4824

4825        // appends the contents of one ValueStore to those of us.
4826
public void append(ValueStoreBase newVal) {
4827            for (int i = 0; i < newVal.fValueTuples.size(); i++) {
4828                OrderedHashtable o = (OrderedHashtable)newVal.fValueTuples.elementAt(i);
4829                if (!contains(o))
4830                    fValueTuples.addElement(o);
4831            }
4832        } // append(ValueStoreBase)
4833

4834        /** Start scope for value store. */
4835        public void startValueScope() throws Exception JavaDoc {
4836            if (DEBUG_VALUE_STORES) {
4837                System.out.println("<VS>: "+toString()+"#startValueScope()");
4838            }
4839            fValuesCount = 0;
4840            int count = fIdentityConstraint.getFieldCount();
4841            for (int i = 0; i < count; i++) {
4842                fValues.put(fIdentityConstraint.getFieldAt(i), NOT_AN_IDVALUE);
4843            }
4844        } // startValueScope()
4845

4846        /** Ends scope for value store. */
4847        public void endValueScope() throws Exception JavaDoc {
4848            if (DEBUG_VALUE_STORES) {
4849                System.out.println("<VS>: "+toString()+"#endValueScope()");
4850            }
4851
4852            // is there anything to do?
4853
// REVISIT: This check solves the problem with field matchers
4854
// that get activated because they are at the same
4855
// level as the declaring element (e.g. selector xpath
4856
// is ".") but never match.
4857
// However, this doesn't help us catch the problem
4858
// when we expect a field value but never see it. A
4859
// better solution has to be found. -Ac
4860
// REVISIT: Is this a problem? -Ac
4861
// Yes - NG
4862
if (fValuesCount == 0) {
4863                if(fIdentityConstraint.getType() == IdentityConstraint.KEY) {
4864                    int code = SchemaMessageProvider.AbsentKeyValue;
4865                    String JavaDoc eName = fIdentityConstraint.getElementName();
4866                    reportSchemaError(code, new Object JavaDoc[]{eName});
4867                }
4868                return;
4869            }
4870
4871            // do we have enough values?
4872
if (fValuesCount != fIdentityConstraint.getFieldCount()) {
4873                switch (fIdentityConstraint.getType()) {
4874                    case IdentityConstraint.UNIQUE: {
4875                        int code = SchemaMessageProvider.UniqueNotEnoughValues;
4876                        String JavaDoc ename = fIdentityConstraint.getElementName();
4877                        reportSchemaError(code, new Object JavaDoc[]{ename});
4878                        break;
4879                    }
4880                    case IdentityConstraint.KEY: {
4881                        int code = SchemaMessageProvider.KeyNotEnoughValues;
4882                        Key key = (Key)fIdentityConstraint;
4883                        String JavaDoc ename = fIdentityConstraint.getElementName();
4884                        String JavaDoc kname = key.getIdentityConstraintName();
4885                        reportSchemaError(code, new Object JavaDoc[]{ename,kname});
4886                        break;
4887                    }
4888                    case IdentityConstraint.KEYREF: {
4889                        int code = SchemaMessageProvider.KeyRefNotEnoughValues;
4890                        KeyRef keyref = (KeyRef)fIdentityConstraint;
4891                        String JavaDoc ename = fIdentityConstraint.getElementName();
4892                        String JavaDoc kname = (keyref.getKey()).getIdentityConstraintName();
4893                        reportSchemaError(code, new Object JavaDoc[]{ename,kname});
4894                        break;
4895                    }
4896                }
4897                return;
4898            }
4899
4900
4901        } // endValueScope()
4902

4903        // This is needed to allow keyref's to look for matched keys
4904
// in the correct scope. Unique and Key may also need to
4905
// override this method for purposes of their own.
4906
// This method is called whenever the DocumentFragment
4907
// of an ID Constraint goes out of scope.
4908
public void endDocumentFragment() throws Exception JavaDoc {
4909        } // endDocumentFragment():void
4910

4911        /**
4912         * Signals the end of the document. This is where the specific
4913         * instances of value stores can verify the integrity of the
4914         * identity constraints.
4915         */

4916        public void endDocument() throws Exception JavaDoc {
4917            if (DEBUG_VALUE_STORES) {
4918                System.out.println("<VS>: "+toString()+"#endDocument()");
4919            }
4920        } // endDocument()
4921

4922        //
4923
// ValueStore methods
4924
//
4925

4926        /* reports an error if an element is matched
4927         * has nillable true and is matched by a key.
4928         */

4929
4930        public void reportNilError(IdentityConstraint id) throws Exception JavaDoc {
4931            if(id.getType() == IdentityConstraint.KEY) {
4932                int code = SchemaMessageProvider.KeyMatchesNillable;
4933                reportSchemaError(code, new Object JavaDoc[]{id.getElementName()});
4934            }
4935        } // reportNilError
4936

4937        /**
4938         * Adds the specified value to the value store.
4939         *
4940         * @param value The value to add.
4941         * @param field The field associated to the value. This reference
4942         * is used to ensure that each field only adds a value
4943         * once within a selection scope.
4944         */

4945        public void addValue(Field field, IDValue value) throws Exception JavaDoc {
4946            if(!field.mayMatch()) {
4947                int code = SchemaMessageProvider.FieldMultipleMatch;
4948                reportSchemaError(code, new Object JavaDoc[]{field.toString()});
4949            }
4950            if (DEBUG_VALUE_STORES) {
4951                System.out.println("<VS>: "+toString()+"#addValue("+
4952                                   "field="+field+','+
4953                                   "value="+value+
4954                                   ")");
4955            }
4956
4957            // do we even know this field?
4958
int index = fValues.indexOf(field);
4959            if (index == -1) {
4960                int code = SchemaMessageProvider.UnknownField;
4961                reportSchemaError(code, new Object JavaDoc[]{field.toString()});
4962                return;
4963            }
4964
4965            // store value
4966
IDValue storedValue = fValues.valueAt(index);
4967            if (storedValue.isDuplicateOf(NOT_AN_IDVALUE)) {
4968                fValuesCount++;
4969            }
4970            fValues.put(field, value);
4971
4972            if (fValuesCount == fValues.size()) {
4973                // is this value as a group duplicated?
4974
if (contains(fValues)) {
4975                    duplicateValue(fValues);
4976                }
4977
4978                // store values
4979
OrderedHashtable values = (OrderedHashtable)fValues.clone();
4980                fValueTuples.addElement(values);
4981            }
4982
4983        } // addValue(String,Field)
4984

4985        /**
4986         * Returns true if this value store contains the specified
4987         * values tuple.
4988         */

4989        public boolean contains(OrderedHashtable tuple) {
4990            if (DEBUG_VALUE_STORES) {
4991                System.out.println("<VS>: "+this.toString()+"#contains("+toString(tuple)+")");
4992            }
4993
4994            // do sizes match?
4995
int tcount = tuple.size();
4996
4997            // iterate over tuples to find it
4998
int count = fValueTuples.size();
4999            LOOP: for (int i = 0; i < count; i++) {
5000                OrderedHashtable vtuple = (OrderedHashtable)fValueTuples.elementAt(i);
5001                // compare values
5002
for (int j = 0; j < tcount; j++) {
5003                    IDValue value1 = vtuple.valueAt(j);
5004                    IDValue value2 = tuple.valueAt(j);
5005                    if(!(value1.isDuplicateOf(value2))) {
5006                        continue LOOP;
5007                    }
5008                }
5009
5010                // found it
5011
return true;
5012            }
5013
5014            // didn't find it
5015
return false;
5016
5017        } // contains(Hashtable):boolean
5018

5019        //
5020
// Protected methods
5021
//
5022

5023        /**
5024         * Called when a duplicate value is added. Subclasses should override
5025         * this method to perform error checking.
5026         *
5027         * @param tuple The duplicate value tuple.
5028         */

5029        protected void duplicateValue(OrderedHashtable tuple)
5030            throws Exception JavaDoc {
5031            // no-op
5032
} // duplicateValue(Hashtable)
5033

5034        /** Returns a string of the specified values. */
5035        protected String JavaDoc toString(OrderedHashtable tuple) {
5036
5037            // no values
5038
int size = tuple.size();
5039            if (size == 0) {
5040                return "";
5041            }
5042
5043            // construct value string
5044
StringBuffer JavaDoc str = new StringBuffer JavaDoc();
5045            for (int i = 0; i < size; i++) {
5046                if (i > 0) {
5047                    str.append(',');
5048                }
5049                str.append(tuple.valueAt(i));
5050            }
5051            return str.toString();
5052
5053        } // toString(OrderedHashtable):String
5054

5055        //
5056
// Object methods
5057
//
5058

5059        /** Returns a string representation of this object. */
5060        public String JavaDoc toString() {
5061            String JavaDoc s = super.toString();
5062            int index1 = s.lastIndexOf('$');
5063            if (index1 != -1) {
5064                s = s.substring(index1 + 1);
5065            }
5066            int index2 = s.lastIndexOf('.');
5067            if (index2 != -1) {
5068                s = s.substring(index2 + 1);
5069            }
5070            return s + '[' + fIdentityConstraint + ']';
5071        } // toString():String
5072

5073    } // class ValueStoreBase
5074

5075    /**
5076     * Unique value store.
5077     *
5078     * @author Andy Clark, IBM
5079     */

5080    protected class UniqueValueStore
5081        extends ValueStoreBase {
5082
5083        //
5084
// Constructors
5085
//
5086

5087        /** Constructs a unique value store. */
5088        public UniqueValueStore(Unique unique) {
5089            super(unique);
5090        } // <init>(Unique)
5091

5092        //
5093
// ValueStoreBase protected methods
5094
//
5095

5096        /**
5097         * Called when a duplicate value is added.
5098         *
5099         * @param tuple The duplicate value tuple.
5100         */

5101        protected void duplicateValue(OrderedHashtable tuple)
5102            throws Exception JavaDoc {
5103            int code = SchemaMessageProvider.DuplicateUnique;
5104            String JavaDoc value = toString(tuple);
5105            String JavaDoc ename = fIdentityConstraint.getElementName();
5106            reportSchemaError(code, new Object JavaDoc[]{value,ename});
5107        } // duplicateValue(Hashtable)
5108

5109    } // class UniqueValueStore
5110

5111    /**
5112     * Key value store.
5113     *
5114     * @author Andy Clark, IBM
5115     */

5116    protected class KeyValueStore
5117        extends ValueStoreBase {
5118
5119        // REVISIT: Implement a more efficient storage mechanism. -Ac
5120

5121        //
5122
// Constructors
5123
//
5124

5125        /** Constructs a key value store. */
5126        public KeyValueStore(Key key) {
5127            super(key);
5128        } // <init>(Key)
5129

5130        //
5131
// ValueStoreBase protected methods
5132
//
5133

5134        /**
5135         * Called when a duplicate value is added.
5136         *
5137         * @param tuple The duplicate value tuple.
5138         */

5139        protected void duplicateValue(OrderedHashtable tuple)
5140            throws Exception JavaDoc {
5141            int code = SchemaMessageProvider.DuplicateKey;
5142            String JavaDoc value = toString(tuple);
5143            String JavaDoc ename = fIdentityConstraint.getElementName();
5144            reportSchemaError(code, new Object JavaDoc[]{value,ename});
5145        } // duplicateValue(Hashtable)
5146

5147    } // class KeyValueStore
5148

5149    /**
5150     * Key reference value store.
5151     *
5152     * @author Andy Clark, IBM
5153     */

5154    protected class KeyRefValueStore
5155        extends ValueStoreBase {
5156
5157        //
5158
// Data
5159
//
5160

5161        /** Key value store. */
5162        protected ValueStoreBase fKeyValueStore;
5163
5164        //
5165
// Constructors
5166
//
5167

5168        /** Constructs a key value store. */
5169        public KeyRefValueStore(KeyRef keyRef, KeyValueStore keyValueStore) {
5170            super(keyRef);
5171            fKeyValueStore = keyValueStore;
5172        } // <init>(KeyRef)
5173

5174        //
5175
// ValueStoreBase methods
5176
//
5177

5178        // end the value Scope; here's where we have to tie
5179
// up keyRef loose ends.
5180
public void endDocumentFragment () throws Exception JavaDoc {
5181
5182            // do all the necessary management...
5183
super.endDocumentFragment ();
5184
5185            // verify references
5186
// get the key store corresponding (if it exists):
5187
fKeyValueStore = (ValueStoreBase)fValueStoreCache.fGlobalIDConstraintMap.get(((KeyRef)fIdentityConstraint).getKey());
5188
5189            if(fKeyValueStore == null) {
5190                // report error
5191
int code = SchemaMessageProvider.KeyRefOutOfScope;
5192                String JavaDoc value = fIdentityConstraint.toString();
5193                reportSchemaError(code, new Object JavaDoc[]{value});
5194                return;
5195            }
5196
5197            int count = fValueTuples.size();
5198            for (int i = 0; i < count; i++) {
5199                OrderedHashtable values = (OrderedHashtable)fValueTuples.elementAt(i);
5200                if (!fKeyValueStore.contains(values)) {
5201                    int code = SchemaMessageProvider.KeyNotFound;
5202                    String JavaDoc value = toString(values);
5203                    String JavaDoc element = fIdentityConstraint.getElementName();
5204                    reportSchemaError(code, new Object JavaDoc[]{value,element});
5205                }
5206            }
5207
5208        } // endDocumentFragment()
5209

5210        /** End document. */
5211        public void endDocument() throws Exception JavaDoc {
5212            super.endDocument();
5213
5214        } // endDocument()
5215

5216    } // class KeyRefValueStore
5217

5218    // value store management
5219

5220    /**
5221     * Value store cache. This class is used to store the values for
5222     * identity constraints.
5223     *
5224     * @author Andy Clark, IBM
5225     */

5226    protected class ValueStoreCache {
5227
5228        //
5229
// Data
5230
//
5231

5232        // values stores
5233

5234        /** stores all global Values stores. */
5235        protected final Vector JavaDoc fValueStores = new Vector JavaDoc();
5236
5237        /** Values stores associated to specific identity constraints. */
5238        protected final Hashtable JavaDoc fIdentityConstraint2ValueStoreMap = new Hashtable JavaDoc();
5239
5240        // sketch of algorithm:
5241
// - when a constraint is first encountered, its
5242
// values are stored in the (local) fIdentityConstraint2ValueStoreMap;
5243
// - Once it is validated (i.e., wen it goes out of scope),
5244
// its values are merged into the fGlobalIDConstraintMap;
5245
// - as we encounter keyref's, we look at the global table to
5246
// validate them.
5247
// the fGlobalIDMapStack has the following structure:
5248
// - validation always occurs against the fGlobalIDConstraintMap
5249
// (which comprises all the "eligible" id constraints);
5250
// When an endelement is found, this Hashtable is merged with the one
5251
// below in the stack.
5252
// When a start tag is encountered, we create a new
5253
// fGlobalIDConstraintMap.
5254
// i.e., the top of the fGlobalIDMapStack always contains
5255
// the preceding siblings' eligible id constraints;
5256
// the fGlobalIDConstraintMap contains descendants+self.
5257
// keyrefs can only match descendants+self.
5258
protected final Stack JavaDoc fGlobalMapStack = new Stack JavaDoc();
5259        protected final Hashtable JavaDoc fGlobalIDConstraintMap = new Hashtable JavaDoc();
5260
5261        //
5262
// Constructors
5263
//
5264

5265        /** Default constructor. */
5266        public ValueStoreCache() {
5267        } // <init>()
5268

5269        //
5270
// Public methods
5271
//
5272

5273        /** Resets the identity constraint cache. */
5274        public void startDocument() throws Exception JavaDoc {
5275            if (DEBUG_VALUE_STORES) {
5276                System.out.println("<VS>: "+toString()+"#startDocument()");
5277            }
5278            fValueStores.removeAllElements();
5279            fIdentityConstraint2ValueStoreMap.clear();
5280            fGlobalIDConstraintMap.clear();
5281            fGlobalMapStack.removeAllElements();
5282        } // startDocument()
5283

5284        // startElement: pushes the current fGlobalIDConstraintMap
5285
// onto fGlobalMapStack and clears fGlobalIDConstraint map.
5286
public void startElement() {
5287            fGlobalMapStack.push(fGlobalIDConstraintMap.clone());
5288            fGlobalIDConstraintMap.clear();
5289        } // startElement(void)
5290

5291        // endElement(): merges contents of fGlobalIDConstraintMap with the
5292
// top of fGlobalMapStack into fGlobalIDConstraintMap.
5293
public void endElement() {
5294            if (fGlobalMapStack.isEmpty()) return; // must be an invalid doc!
5295
Hashtable JavaDoc oldMap = (Hashtable JavaDoc)fGlobalMapStack.pop();
5296            Enumeration JavaDoc keys = oldMap.keys();
5297            while(keys.hasMoreElements()) {
5298                IdentityConstraint id = (IdentityConstraint)keys.nextElement();
5299                ValueStoreBase oldVal = (ValueStoreBase)oldMap.get(id);
5300                if(oldVal != null) {
5301                    ValueStoreBase currVal = (ValueStoreBase)fGlobalIDConstraintMap.get(id);
5302                    if (currVal == null)
5303                        fGlobalIDConstraintMap.put(id, oldVal);
5304                    else {
5305                        currVal.append(oldVal);
5306                        fGlobalIDConstraintMap.put(id, currVal);
5307                    }
5308                }
5309            }
5310        } // endElement()
5311

5312        /**
5313         * Initializes the value stores for the specified element
5314         * declaration.
5315         */

5316        public void initValueStoresFor(XMLElementDecl eDecl)
5317            throws Exception JavaDoc {
5318            if (DEBUG_VALUE_STORES) {
5319                System.out.println("<VS>: "+toString()+"#initValueStoresFor("+
5320                                   fStringPool.toString(eDecl.name.rawname)+
5321                                   ")");
5322            }
5323
5324            // initialize value stores for unique fields
5325
Vector JavaDoc uVector = eDecl.unique;
5326            int uCount = uVector.size();
5327            for (int i = 0; i < uCount; i++) {
5328                Unique unique = (Unique)uVector.elementAt(i);
5329                UniqueValueStore valueStore = (UniqueValueStore)fIdentityConstraint2ValueStoreMap.get(unique);
5330                if (valueStore != null) {
5331                    // NOTE: If already initialized, don't need to
5332
// do it again. -Ac
5333
continue;
5334                }
5335                valueStore = new UniqueValueStore(unique);
5336                fValueStores.addElement(valueStore);
5337                if (DEBUG_VALUE_STORES) {
5338                    System.out.println("<VS>: "+unique+" -> "+valueStore);
5339                }
5340                fIdentityConstraint2ValueStoreMap.put(unique, valueStore);
5341            }
5342
5343            // initialize value stores for key fields
5344
Vector JavaDoc kVector = eDecl.key;
5345            int kCount = kVector.size();
5346            for (int i = 0; i < kCount; i++) {
5347                Key key = (Key)kVector.elementAt(i);
5348                KeyValueStore valueStore = (KeyValueStore)fIdentityConstraint2ValueStoreMap.get(key);
5349                if (valueStore != null) {
5350                    // NOTE: If already initialized, don't need to
5351
// do it again. -Ac
5352
continue;
5353                }
5354                valueStore = new KeyValueStore(key);
5355                fValueStores.addElement(valueStore);
5356                if (DEBUG_VALUE_STORES) {
5357                    System.out.println("<VS>: "+key+" -> "+valueStore);
5358                }
5359                fIdentityConstraint2ValueStoreMap.put(key, valueStore);
5360            }
5361
5362            // initialize value stores for key reference fields
5363
Vector JavaDoc krVector = eDecl.keyRef;
5364            int krCount = krVector.size();
5365            for (int i = 0; i < krCount; i++) {
5366                KeyRef keyRef = (KeyRef)krVector.elementAt(i);
5367                KeyRefValueStore keyRefValueStore = new KeyRefValueStore(keyRef, null);
5368                fValueStores.addElement(keyRefValueStore);
5369                if (DEBUG_VALUE_STORES) {
5370                    System.out.println("<VS>: "+keyRef+" -> "+keyRefValueStore);
5371                }
5372                fIdentityConstraint2ValueStoreMap.put(keyRef, keyRefValueStore);
5373            }
5374
5375        } // initValueStoresFor(XMLElementDecl)
5376

5377        /** Returns the value store associated to the specified field. */
5378        public ValueStoreBase getValueStoreFor(Field field) {
5379            if (DEBUG_VALUE_STORES) {
5380                System.out.println("<VS>: "+toString()+"#getValueStoreFor("+field+")");
5381            }
5382            IdentityConstraint identityConstraint = field.getIdentityConstraint();
5383            return (ValueStoreBase)fIdentityConstraint2ValueStoreMap.get(identityConstraint);
5384        } // getValueStoreFor(Field):ValueStoreBase
5385

5386        /** Returns the value store associated to the specified IdentityConstraint. */
5387        public ValueStoreBase getValueStoreFor(IdentityConstraint id) {
5388            if (DEBUG_VALUE_STORES) {
5389                System.out.println("<VS>: "+toString()+"#getValueStoreFor("+id+")");
5390            }
5391            return (ValueStoreBase)fIdentityConstraint2ValueStoreMap.get(id);
5392        } // getValueStoreFor(IdentityConstraint):ValueStoreBase
5393

5394        /** Returns the global value store associated to the specified IdentityConstraint. */
5395        public ValueStoreBase getGlobalValueStoreFor(IdentityConstraint id) {
5396            if (DEBUG_VALUE_STORES) {
5397                System.out.println("<VS>: "+toString()+"#getGlobalValueStoreFor("+id+")");
5398            }
5399            return (ValueStoreBase)fGlobalIDConstraintMap.get(id);
5400        } // getValueStoreFor(IdentityConstraint):ValueStoreBase
5401
// This method takes the contents of the (local) ValueStore
5402
// associated with id and moves them into the global
5403
// hashtable, if id is a <unique> or a <key>.
5404
// If it's a <keyRef>, then we leave it for later.
5405
public void transplant(IdentityConstraint id) throws Exception JavaDoc {
5406            if (id.getType() == IdentityConstraint.KEYREF ) return;
5407            ValueStoreBase newVals = (ValueStoreBase)fIdentityConstraint2ValueStoreMap.get(id);
5408            fIdentityConstraint2ValueStoreMap.remove(id);
5409            ValueStoreBase currVals = (ValueStoreBase)fGlobalIDConstraintMap.get(id);
5410            if (currVals != null) {
5411                currVals.append(newVals);
5412                fGlobalIDConstraintMap.put(id, currVals);
5413            } else
5414                fGlobalIDConstraintMap.put(id, newVals);
5415
5416        } // transplant(id)
5417

5418        /** Check identity constraints. */
5419        public void endDocument() throws Exception JavaDoc {
5420            if (DEBUG_VALUE_STORES) {
5421                System.out.println("<VS>: "+toString()+"#endDocument()");
5422            }
5423
5424            int count = fValueStores.size();
5425            for (int i = 0; i < count; i++) {
5426                ValueStoreBase valueStore = (ValueStoreBase)fValueStores.elementAt(i);
5427                valueStore.endDocument();
5428            }
5429
5430        } // endDocument()
5431

5432        //
5433
// Object methods
5434
//
5435

5436        /** Returns a string representation of this object. */
5437        public String JavaDoc toString() {
5438            String JavaDoc s = super.toString();
5439            int index1 = s.lastIndexOf('$');
5440            if (index1 != -1) {
5441                return s.substring(index1 + 1);
5442            }
5443            int index2 = s.lastIndexOf('.');
5444            if (index2 != -1) {
5445                return s.substring(index2 + 1);
5446            }
5447            return s;
5448        } // toString():String
5449

5450    } // class ValueStoreCache
5451

5452    // utility classes
5453

5454    /**
5455     * Ordered hashtable. This class acts as a hashtable with
5456     * <code>put()</code> and <code>get()</code> operations but also
5457     * allows values to be queried via the order that they were
5458     * added to the hashtable.
5459     * <p>
5460     * <strong>Note:</strong> This class does not perform any error
5461     * checking.
5462     * <p>
5463     * <strong>Note:</strong> This class is <em>not</em> efficient but
5464     * is assumed to be used for a very small set of values.
5465     *
5466     * @author Andy Clark, IBM
5467     */

5468    static final class OrderedHashtable
5469        implements Cloneable JavaDoc {
5470
5471        //
5472
// Data
5473
//
5474

5475        /** Size. */
5476        private int fSize;
5477
5478        /** Hashtable entries. */
5479        private Entry[] fEntries = null;
5480
5481        //
5482
// Public methods
5483
//
5484

5485        /** Returns the number of entries in the hashtable. */
5486        public int size() {
5487            return fSize;
5488        } // size():int
5489

5490        /** Puts an entry into the hashtable. */
5491        public void put(Field key, IDValue value) {
5492            int index = indexOf(key);
5493            if (index == -1) {
5494                ensureCapacity(fSize);
5495                index = fSize++;
5496                fEntries[index].key = key;
5497            }
5498            fEntries[index].value = value;
5499        } // put(Field,String)
5500

5501        /** Returns the value associated to the specified key. */
5502        public IDValue get(Field key) {
5503            return fEntries[indexOf(key)].value;
5504        } // get(Field):String
5505

5506        /** Returns the index of the entry with the specified key. */
5507        public int indexOf(Field key) {
5508            for (int i = 0; i < fSize; i++) {
5509                // NOTE: Only way to be sure that the keys are the
5510
// same is by using a reference comparison. In
5511
// order to rely on the equals method, each
5512
// field would have to take into account its
5513
// position in the identity constraint, the
5514
// identity constraint, the declaring element,
5515
// and the grammar that it is defined in.
5516
// Otherwise, you have the possibility that
5517
// the equals method would return true for two
5518
// fields that look *very* similar.
5519
// The reference compare isn't bad, actually,
5520
// because the field objects are cacheable. -Ac
5521
if (fEntries[i].key == key) {
5522                    return i;
5523                }
5524            }
5525            return -1;
5526        } // indexOf(Field):int
5527

5528        /** Returns the key at the specified index. */
5529        public Field keyAt(int index) {
5530            return fEntries[index].key;
5531        } // keyAt(int):Field
5532

5533        /** Returns the value at the specified index. */
5534        public IDValue valueAt(int index) {
5535            return fEntries[index].value;
5536        } // valueAt(int):String
5537

5538        /** Removes all of the entries from the hashtable. */
5539        public void clear() {
5540            fSize = 0;
5541        } // clear()
5542

5543        //
5544
// Private methods
5545
//
5546

5547        /** Ensures the capacity of the entries array. */
5548        private void ensureCapacity(int size) {
5549
5550            // sizes
5551
int osize = -1;
5552            int nsize = -1;
5553
5554            // create array
5555
if (fEntries == null) {
5556                osize = 0;
5557                nsize = 2;
5558                fEntries = new Entry[nsize];
5559            }
5560
5561            // resize array
5562
else if (fEntries.length <= size) {
5563                osize = fEntries.length;
5564                nsize = 2 * osize;
5565                Entry[] array = new Entry[nsize];
5566                System.arraycopy(fEntries, 0, array, 0, osize);
5567                fEntries = array;
5568            }
5569
5570            // create new entries
5571
for (int i = osize; i < nsize; i++) {
5572                fEntries[i] = new Entry();
5573            }
5574
5575        } // ensureCapacity(int)
5576

5577        //
5578
// Cloneable methods
5579
//
5580

5581        /** Clones this object. */
5582        public Object JavaDoc clone() {
5583
5584            OrderedHashtable hashtable = new OrderedHashtable();
5585            for (int i = 0; i < fSize; i++) {
5586                hashtable.put(fEntries[i].key, fEntries[i].value);
5587            }
5588            return hashtable;
5589
5590        } // clone():Object
5591

5592        //
5593
// Object methods
5594
//
5595

5596        /** Returns a string representation of this object. */
5597        public String JavaDoc toString() {
5598            if (fSize == 0) {
5599                return "[]";
5600            }
5601            StringBuffer JavaDoc str = new StringBuffer JavaDoc();
5602            str.append('[');
5603            for (int i = 0; i < fSize; i++) {
5604                if (i > 0) {
5605                    str.append(',');
5606                }
5607                str.append('{');
5608                str.append(fEntries[i].key);
5609                str.append(',');
5610                str.append(fEntries[i].value);
5611                str.append('}');
5612            }
5613            str.append(']');
5614            return str.toString();
5615        } // toString():String
5616

5617        //
5618
// Classes
5619
//
5620

5621        /**
5622         * Hashtable entry.
5623         */

5624        public static final class Entry {
5625
5626            //
5627
// Data
5628
//
5629

5630            /** Key. */
5631            public Field key;
5632
5633            /** Value. */
5634            public IDValue value;
5635
5636        } // class Entry
5637

5638    } // class OrderedHashtable
5639

5640} // class XMLValidator
5641
Popular Tags