KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > impl > xs > XMLSchemaValidator


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

16
17 package org.apache.xerces.impl.xs;
18
19 import java.io.IOException JavaDoc;
20 import java.util.Enumeration JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Hashtable JavaDoc;
23 import java.util.Stack JavaDoc;
24 import java.util.Vector JavaDoc;
25
26 import org.apache.xerces.impl.Constants;
27 import org.apache.xerces.impl.RevalidationHandler;
28 import org.apache.xerces.impl.XMLErrorReporter;
29 import org.apache.xerces.impl.dv.DatatypeException;
30 import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
31 import org.apache.xerces.impl.dv.ValidatedInfo;
32 import org.apache.xerces.impl.dv.XSSimpleType;
33 import org.apache.xerces.impl.validation.ValidationManager;
34 import org.apache.xerces.impl.validation.ValidationState;
35 import org.apache.xerces.impl.xs.identity.Field;
36 import org.apache.xerces.impl.xs.identity.FieldActivator;
37 import org.apache.xerces.impl.xs.identity.IdentityConstraint;
38 import org.apache.xerces.impl.xs.identity.KeyRef;
39 import org.apache.xerces.impl.xs.identity.Selector;
40 import org.apache.xerces.impl.xs.identity.UniqueOrKey;
41 import org.apache.xerces.impl.xs.identity.ValueStore;
42 import org.apache.xerces.impl.xs.identity.XPathMatcher;
43 import org.apache.xerces.impl.xs.models.CMBuilder;
44 import org.apache.xerces.impl.xs.models.CMNodeFactory;
45 import org.apache.xerces.impl.xs.models.XSCMValidator;
46 import org.apache.xerces.util.AugmentationsImpl;
47 import org.apache.xerces.util.IntStack;
48 import org.apache.xerces.util.SymbolTable;
49 import org.apache.xerces.util.XMLAttributesImpl;
50 import org.apache.xerces.util.XMLChar;
51 import org.apache.xerces.util.XMLSymbols;
52 import org.apache.xerces.xni.Augmentations;
53 import org.apache.xerces.xni.NamespaceContext;
54 import org.apache.xerces.xni.QName;
55 import org.apache.xerces.xni.XMLAttributes;
56 import org.apache.xerces.xni.XMLDocumentHandler;
57 import org.apache.xerces.xni.XMLLocator;
58 import org.apache.xerces.xni.XMLResourceIdentifier;
59 import org.apache.xerces.xni.XMLString;
60 import org.apache.xerces.xni.XNIException;
61 import org.apache.xerces.xni.grammars.XMLGrammarDescription;
62 import org.apache.xerces.xni.grammars.XMLGrammarPool;
63 import org.apache.xerces.xni.parser.XMLComponent;
64 import org.apache.xerces.xni.parser.XMLComponentManager;
65 import org.apache.xerces.xni.parser.XMLConfigurationException;
66 import org.apache.xerces.xni.parser.XMLDocumentFilter;
67 import org.apache.xerces.xni.parser.XMLDocumentSource;
68 import org.apache.xerces.xni.parser.XMLEntityResolver;
69 import org.apache.xerces.xni.parser.XMLInputSource;
70 import org.apache.xerces.xs.AttributePSVI;
71 import org.apache.xerces.xs.ElementPSVI;
72 import org.apache.xerces.xs.ShortList;
73 import org.apache.xerces.xs.XSConstants;
74 import org.apache.xerces.xs.XSObjectList;
75 import org.apache.xerces.xs.XSTypeDefinition;
76 import org.xml.sax.SAXNotRecognizedException JavaDoc;
77 import org.xml.sax.SAXNotSupportedException JavaDoc;
78
79 /**
80  * The XML Schema validator. The validator implements a document
81  * filter: receiving document events from the scanner; validating
82  * the content and structure; augmenting the InfoSet, if applicable;
83  * and notifying the parser of the information resulting from the
84  * validation process.
85  * <p>
86  * This component requires the following features and properties from the
87  * component manager that uses it:
88  * <ul>
89  * <li>http://xml.org/sax/features/validation</li>
90  * <li>http://apache.org/xml/properties/internal/symbol-table</li>
91  * <li>http://apache.org/xml/properties/internal/error-reporter</li>
92  * <li>http://apache.org/xml/properties/internal/entity-resolver</li>
93  * </ul>
94  *
95  * @xerces.internal
96  *
97  * @author Sandy Gao IBM
98  * @author Elena Litani IBM
99  * @author Andy Clark IBM
100  * @author Neeraj Bajaj, Sun Microsystems, inc.
101  * @version $Id: XMLSchemaValidator.java,v 1.179 2005/07/24 22:55:21 mrglavas Exp $
102  */

103 public class XMLSchemaValidator
104     implements XMLComponent, XMLDocumentFilter, FieldActivator, RevalidationHandler {
105
106     //
107
// Constants
108
//
109
private static final boolean DEBUG = false;
110
111     // feature identifiers
112

113     /** Feature identifier: validation. */
114     protected static final String JavaDoc VALIDATION =
115         Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
116
117     /** Feature identifier: validation. */
118     protected static final String JavaDoc SCHEMA_VALIDATION =
119         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
120
121     /** Feature identifier: schema full checking*/
122     protected static final String JavaDoc SCHEMA_FULL_CHECKING =
123         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING;
124
125     /** Feature identifier: dynamic validation. */
126     protected static final String JavaDoc DYNAMIC_VALIDATION =
127         Constants.XERCES_FEATURE_PREFIX + Constants.DYNAMIC_VALIDATION_FEATURE;
128
129     /** Feature identifier: expose schema normalized value */
130     protected static final String JavaDoc NORMALIZE_DATA =
131         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE;
132
133     /** Feature identifier: send element default value via characters() */
134     protected static final String JavaDoc SCHEMA_ELEMENT_DEFAULT =
135         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_ELEMENT_DEFAULT;
136
137     /** Feature identifier: augment PSVI */
138     protected static final String JavaDoc SCHEMA_AUGMENT_PSVI =
139         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_AUGMENT_PSVI;
140
141     /** Feature identifier: whether to recognize java encoding names */
142     protected static final String JavaDoc ALLOW_JAVA_ENCODINGS =
143         Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
144
145     /** Feature identifier: standard uri conformant feature. */
146     protected static final String JavaDoc STANDARD_URI_CONFORMANT_FEATURE =
147         Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE;
148     
149     /** Feature: generate synthetic annotations */
150     protected static final String JavaDoc GENERATE_SYNTHETIC_ANNOTATIONS =
151         Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE;
152     
153     /** Feature identifier: validate annotations. */
154     protected static final String JavaDoc VALIDATE_ANNOTATIONS =
155         Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATE_ANNOTATIONS_FEATURE;
156     
157     /** Feature identifier: honour all schemaLocations */
158     protected static final String JavaDoc HONOUR_ALL_SCHEMALOCATIONS =
159         Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE;
160
161     /** Feature identifier: use grammar pool only */
162     protected static final String JavaDoc USE_GRAMMAR_POOL_ONLY =
163         Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE;
164
165     /** Feature identifier: whether to continue parsing a schema after a fatal error is encountered */
166     protected static final String JavaDoc CONTINUE_AFTER_FATAL_ERROR =
167         Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
168
169     protected static final String JavaDoc PARSER_SETTINGS =
170             Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
171
172     // property identifiers
173

174     /** Property identifier: symbol table. */
175     public static final String JavaDoc SYMBOL_TABLE =
176         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
177
178     /** Property identifier: error reporter. */
179     public static final String JavaDoc ERROR_REPORTER =
180         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
181
182     /** Property identifier: entity resolver. */
183     public static final String JavaDoc ENTITY_RESOLVER =
184         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
185
186     /** Property identifier: grammar pool. */
187     public static final String JavaDoc XMLGRAMMAR_POOL =
188         Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
189
190     protected static final String JavaDoc VALIDATION_MANAGER =
191         Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
192
193     protected static final String JavaDoc ENTITY_MANAGER =
194         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
195
196     /** Property identifier: schema location. */
197     protected static final String JavaDoc SCHEMA_LOCATION =
198         Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_LOCATION;
199
200     /** Property identifier: no namespace schema location. */
201     protected static final String JavaDoc SCHEMA_NONS_LOCATION =
202         Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_NONS_LOCATION;
203
204     /** Property identifier: JAXP schema source. */
205     protected static final String JavaDoc JAXP_SCHEMA_SOURCE =
206         Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
207
208     /** Property identifier: JAXP schema language. */
209     protected static final String JavaDoc JAXP_SCHEMA_LANGUAGE =
210         Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE;
211
212     // recognized features and properties
213

214     /** Recognized features. */
215     private static final String JavaDoc[] RECOGNIZED_FEATURES =
216         {
217             VALIDATION,
218             SCHEMA_VALIDATION,
219             DYNAMIC_VALIDATION,
220             SCHEMA_FULL_CHECKING,
221             ALLOW_JAVA_ENCODINGS,
222             CONTINUE_AFTER_FATAL_ERROR,
223             STANDARD_URI_CONFORMANT_FEATURE,
224             GENERATE_SYNTHETIC_ANNOTATIONS,
225             VALIDATE_ANNOTATIONS,
226             HONOUR_ALL_SCHEMALOCATIONS,
227             USE_GRAMMAR_POOL_ONLY};
228
229
230     /** Feature defaults. */
231     private static final Boolean JavaDoc[] FEATURE_DEFAULTS = { null,
232         // NOTE: The following defaults are nulled out on purpose.
233
// If they are set, then when the XML Schema validator
234
// is constructed dynamically, these values may override
235
// those set by the application. This goes against the
236
// whole purpose of XMLComponent#getFeatureDefault but
237
// it can't be helped in this case. -Ac
238
null, //Boolean.FALSE,
239
null, //Boolean.FALSE,
240
null, //Boolean.FALSE,
241
null, //Boolean.FALSE,
242
null, //Boolean.FALSE,
243
null,
244         null,
245         null,
246         null,
247         null};
248
249     /** Recognized properties. */
250     private static final String JavaDoc[] RECOGNIZED_PROPERTIES =
251         {
252             SYMBOL_TABLE,
253             ERROR_REPORTER,
254             ENTITY_RESOLVER,
255             VALIDATION_MANAGER,
256             SCHEMA_LOCATION,
257             SCHEMA_NONS_LOCATION,
258             JAXP_SCHEMA_SOURCE,
259             JAXP_SCHEMA_LANGUAGE,
260             };
261
262     /** Property defaults. */
263     private static final Object JavaDoc[] PROPERTY_DEFAULTS =
264         { null, null, null, null, null, null, null, null, };
265
266     // this is the number of valuestores of each kind
267
// we expect an element to have. It's almost
268
// never > 1; so leave it at that.
269
protected static final int ID_CONSTRAINT_NUM = 1;
270
271     //
272
// Data
273
//
274

275     /** current PSVI element info */
276     protected ElementPSVImpl fCurrentPSVI = new ElementPSVImpl();
277
278     // since it is the responsibility of each component to an
279
// Augmentations parameter if one is null, to save ourselves from
280
// having to create this object continually, it is created here.
281
// If it is not present in calls that we're passing on, we *must*
282
// clear this before we introduce it into the pipeline.
283
protected final AugmentationsImpl fAugmentations = new AugmentationsImpl();
284
285     /**
286      * Map which is used to catch instance documents that try
287      * and match a field several times in the same scope.
288      */

289     protected final HashMap JavaDoc fMayMatchFieldMap = new HashMap JavaDoc();
290
291     // this is included for the convenience of handleEndElement
292
protected XMLString fDefaultValue;
293
294     // Validation features
295
protected boolean fDynamicValidation = false;
296     protected boolean fSchemaDynamicValidation = false;
297     protected boolean fDoValidation = false;
298     protected boolean fFullChecking = false;
299     protected boolean fNormalizeData = true;
300     protected boolean fSchemaElementDefault = true;
301     protected boolean fAugPSVI = true;
302     protected boolean fIdConstraint = false;
303     protected boolean fUseGrammarPoolOnly = false;
304
305     /** Schema type: None, DTD, Schema */
306     private String JavaDoc fSchemaType = null;
307
308     // to indicate whether we are in the scope of entity reference or CData
309
protected boolean fEntityRef = false;
310     protected boolean fInCDATA = false;
311
312     // properties
313

314     /** Symbol table. */
315     protected SymbolTable fSymbolTable;
316
317     /**
318      * While parsing a document, keep the location of the document.
319      */

320     private XMLLocator fLocator;
321
322     /**
323      * A wrapper of the standard error reporter. We'll store all schema errors
324      * in this wrapper object, so that we can get all errors (error codes) of
325      * a specific element. This is useful for PSVI.
326      */

327     protected final class XSIErrorReporter {
328
329         // the error reporter property
330
XMLErrorReporter fErrorReporter;
331
332         // store error codes; starting position of the errors for each element;
333
// number of element (depth); and whether to record error
334
Vector JavaDoc fErrors = new Vector JavaDoc();
335         int[] fContext = new int[INITIAL_STACK_SIZE];
336         int fContextCount;
337
338         // set the external error reporter, clear errors
339
public void reset(XMLErrorReporter errorReporter) {
340             fErrorReporter = errorReporter;
341             fErrors.removeAllElements();
342             fContextCount = 0;
343         }
344
345         // should be called when starting process an element or an attribute.
346
// store the starting position for the current context
347
public void pushContext() {
348             if (!fAugPSVI) {
349                 return;
350             }
351             // resize array if necessary
352
if (fContextCount == fContext.length) {
353                 int newSize = fContextCount + INC_STACK_SIZE;
354                 int[] newArray = new int[newSize];
355                 System.arraycopy(fContext, 0, newArray, 0, fContextCount);
356                 fContext = newArray;
357             }
358
359             fContext[fContextCount++] = fErrors.size();
360         }
361
362         // should be called on endElement: get all errors of the current element
363
public String JavaDoc[] popContext() {
364             if (!fAugPSVI) {
365                 return null;
366             }
367             // get starting position of the current element
368
int contextPos = fContext[--fContextCount];
369             // number of errors of the current element
370
int size = fErrors.size() - contextPos;
371             // if no errors, return null
372
if (size == 0)
373                 return null;
374             // copy errors from the list to an string array
375
String JavaDoc[] errors = new String JavaDoc[size];
376             for (int i = 0; i < size; i++) {
377                 errors[i] = (String JavaDoc) fErrors.elementAt(contextPos + i);
378             }
379             // remove errors of the current element
380
fErrors.setSize(contextPos);
381             return errors;
382         }
383
384         // should be called when an attribute is done: get all errors of
385
// this attribute, but leave the errors to the containing element
386
// also called after an element was strictly assessed.
387
public String JavaDoc[] mergeContext() {
388             if (!fAugPSVI) {
389                 return null;
390             }
391             // get starting position of the current element
392
int contextPos = fContext[--fContextCount];
393             // number of errors of the current element
394
int size = fErrors.size() - contextPos;
395             // if no errors, return null
396
if (size == 0)
397                 return null;
398             // copy errors from the list to an string array
399
String JavaDoc[] errors = new String JavaDoc[size];
400             for (int i = 0; i < size; i++) {
401                 errors[i] = (String JavaDoc) fErrors.elementAt(contextPos + i);
402             }
403             // don't resize the vector: leave the errors for this attribute
404
// to the containing element
405
return errors;
406         }
407
408         public void reportError(String JavaDoc domain, String JavaDoc key, Object JavaDoc[] arguments, short severity)
409             throws XNIException {
410             fErrorReporter.reportError(domain, key, arguments, severity);
411             if (fAugPSVI) {
412                 fErrors.addElement(key);
413             }
414         } // reportError(String,String,Object[],short)
415

416         public void reportError(
417             XMLLocator location,
418             String JavaDoc domain,
419             String JavaDoc key,
420             Object JavaDoc[] arguments,
421             short severity)
422             throws XNIException {
423             fErrorReporter.reportError(location, domain, key, arguments, severity);
424             if (fAugPSVI) {
425                 fErrors.addElement(key);
426             }
427         } // reportError(XMLLocator,String,String,Object[],short)
428
}
429
430     /** Error reporter. */
431     protected final XSIErrorReporter fXSIErrorReporter = new XSIErrorReporter();
432
433     /** Entity resolver */
434     protected XMLEntityResolver fEntityResolver;
435
436     // updated during reset
437
protected ValidationManager fValidationManager = null;
438     protected ValidationState fValidationState = new ValidationState();
439     protected XMLGrammarPool fGrammarPool;
440
441     // schema location property values
442
protected String JavaDoc fExternalSchemas = null;
443     protected String JavaDoc fExternalNoNamespaceSchema = null;
444
445     //JAXP Schema Source property
446
protected Object JavaDoc fJaxpSchemaSource = null;
447
448     /** Schema Grammar Description passed, to give a chance to application to supply the Grammar */
449     protected final XSDDescription fXSDDescription = new XSDDescription();
450     protected final Hashtable JavaDoc fLocationPairs = new Hashtable JavaDoc();
451
452
453     // handlers
454

455     /** Document handler. */
456     protected XMLDocumentHandler fDocumentHandler;
457
458     protected XMLDocumentSource fDocumentSource;
459
460     //
461
// XMLComponent methods
462
//
463

464     /**
465      * Returns a list of feature identifiers that are recognized by
466      * this component. This method may return null if no features
467      * are recognized by this component.
468      */

469     public String JavaDoc[] getRecognizedFeatures() {
470         return (String JavaDoc[]) (RECOGNIZED_FEATURES.clone());
471     } // getRecognizedFeatures():String[]
472

473     /**
474      * Sets the state of a feature. This method is called by the component
475      * manager any time after reset when a feature changes state.
476      * <p>
477      * <strong>Note:</strong> Components should silently ignore features
478      * that do not affect the operation of the component.
479      *
480      * @param featureId The feature identifier.
481      * @param state The state of the feature.
482      *
483      * @throws SAXNotRecognizedException The component should not throw
484      * this exception.
485      * @throws SAXNotSupportedException The component should not throw
486      * this exception.
487      */

488     public void setFeature(String JavaDoc featureId, boolean state) throws XMLConfigurationException {
489     } // setFeature(String,boolean)
490

491     /**
492      * Returns a list of property identifiers that are recognized by
493      * this component. This method may return null if no properties
494      * are recognized by this component.
495      */

496     public String JavaDoc[] getRecognizedProperties() {
497         return (String JavaDoc[]) (RECOGNIZED_PROPERTIES.clone());
498     } // getRecognizedProperties():String[]
499

500     /**
501      * Sets the value of a property. This method is called by the component
502      * manager any time after reset when a property changes value.
503      * <p>
504      * <strong>Note:</strong> Components should silently ignore properties
505      * that do not affect the operation of the component.
506      *
507      * @param propertyId The property identifier.
508      * @param value The value of the property.
509      *
510      * @throws SAXNotRecognizedException The component should not throw
511      * this exception.
512      * @throws SAXNotSupportedException The component should not throw
513      * this exception.
514      */

515     public void setProperty(String JavaDoc propertyId, Object JavaDoc value) throws XMLConfigurationException {
516     } // setProperty(String,Object)
517

518     /**
519      * Returns the default state for a feature, or null if this
520      * component does not want to report a default value for this
521      * feature.
522      *
523      * @param featureId The feature identifier.
524      *
525      * @since Xerces 2.2.0
526      */

527     public Boolean JavaDoc getFeatureDefault(String JavaDoc featureId) {
528         for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
529             if (RECOGNIZED_FEATURES[i].equals(featureId)) {
530                 return FEATURE_DEFAULTS[i];
531             }
532         }
533         return null;
534     } // getFeatureDefault(String):Boolean
535

536     /**
537      * Returns the default state for a property, or null if this
538      * component does not want to report a default value for this
539      * property.
540      *
541      * @param propertyId The property identifier.
542      *
543      * @since Xerces 2.2.0
544      */

545     public Object JavaDoc getPropertyDefault(String JavaDoc propertyId) {
546         for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
547             if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
548                 return PROPERTY_DEFAULTS[i];
549             }
550         }
551         return null;
552     } // getPropertyDefault(String):Object
553

554     //
555
// XMLDocumentSource methods
556
//
557

558     /** Sets the document handler to receive information about the document. */
559     public void setDocumentHandler(XMLDocumentHandler documentHandler) {
560         fDocumentHandler = documentHandler;
561     } // setDocumentHandler(XMLDocumentHandler)
562

563     /** Returns the document handler */
564     public XMLDocumentHandler getDocumentHandler() {
565         return fDocumentHandler;
566     } // setDocumentHandler(XMLDocumentHandler)
567

568     //
569
// XMLDocumentHandler methods
570
//
571

572     /** Sets the document source */
573     public void setDocumentSource(XMLDocumentSource source) {
574         fDocumentSource = source;
575     } // setDocumentSource
576

577     /** Returns the document source */
578     public XMLDocumentSource getDocumentSource() {
579         return fDocumentSource;
580     } // getDocumentSource
581

582     /**
583      * The start of the document.
584      *
585      * @param locator The system identifier of the entity if the entity
586      * is external, null otherwise.
587      * @param encoding The auto-detected IANA encoding name of the entity
588      * stream. This value will be null in those situations
589      * where the entity encoding is not auto-detected (e.g.
590      * internal entities or a document entity that is
591      * parsed from a java.io.Reader).
592      * @param namespaceContext
593      * The namespace context in effect at the
594      * start of this document.
595      * This object represents the current context.
596      * Implementors of this class are responsible
597      * for copying the namespace bindings from the
598      * the current context (and its parent contexts)
599      * if that information is important.
600      * @param augs Additional information that may include infoset augmentations
601      *
602      * @throws XNIException Thrown by handler to signal an error.
603      */

604     public void startDocument(
605         XMLLocator locator,
606         String JavaDoc encoding,
607         NamespaceContext namespaceContext,
608         Augmentations augs)
609         throws XNIException {
610
611         fValidationState.setNamespaceSupport(namespaceContext);
612         fState4XsiType.setNamespaceSupport(namespaceContext);
613         fState4ApplyDefault.setNamespaceSupport(namespaceContext);
614         fLocator = locator;
615
616         handleStartDocument(locator, encoding);
617         // call handlers
618
if (fDocumentHandler != null) {
619             fDocumentHandler.startDocument(locator, encoding, namespaceContext, augs);
620         }
621
622     } // startDocument(XMLLocator,String)
623

624     /**
625      * Notifies of the presence of an XMLDecl line in the document. If
626      * present, this method will be called immediately following the
627      * startDocument call.
628      *
629      * @param version The XML version.
630      * @param encoding The IANA encoding name of the document, or null if
631      * not specified.
632      * @param standalone The standalone value, or null if not specified.
633      * @param augs Additional information that may include infoset augmentations
634      *
635      * @throws XNIException Thrown by handler to signal an error.
636      */

637     public void xmlDecl(String JavaDoc version, String JavaDoc encoding, String JavaDoc standalone, Augmentations augs)
638         throws XNIException {
639
640         // call handlers
641
if (fDocumentHandler != null) {
642             fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
643         }
644
645     } // xmlDecl(String,String,String)
646

647     /**
648      * Notifies of the presence of the DOCTYPE line in the document.
649      *
650      * @param rootElement The name of the root element.
651      * @param publicId The public identifier if an external DTD or null
652      * if the external DTD is specified using SYSTEM.
653      * @param systemId The system identifier if an external DTD, null
654      * otherwise.
655      * @param augs Additional information that may include infoset augmentations
656      *
657      * @throws XNIException Thrown by handler to signal an error.
658      */

659     public void doctypeDecl(
660         String JavaDoc rootElement,
661         String JavaDoc publicId,
662         String JavaDoc systemId,
663         Augmentations augs)
664         throws XNIException {
665
666         // call handlers
667
if (fDocumentHandler != null) {
668             fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
669         }
670
671     } // doctypeDecl(String,String,String)
672

673     /**
674      * The start of an element.
675      *
676      * @param element The name of the element.
677      * @param attributes The element attributes.
678      * @param augs Additional information that may include infoset augmentations
679      *
680      * @throws XNIException Thrown by handler to signal an error.
681      */

682     public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
683         throws XNIException {
684
685         Augmentations modifiedAugs = handleStartElement(element, attributes, augs);
686         // call handlers
687
if (fDocumentHandler != null) {
688             fDocumentHandler.startElement(element, attributes, modifiedAugs);
689         }
690
691     } // startElement(QName,XMLAttributes, Augmentations)
692

693     /**
694      * An empty element.
695      *
696      * @param element The name of the element.
697      * @param attributes The element attributes.
698      * @param augs Additional information that may include infoset augmentations
699      *
700      * @throws XNIException Thrown by handler to signal an error.
701      */

702     public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
703         throws XNIException {
704
705         Augmentations modifiedAugs = handleStartElement(element, attributes, augs);
706
707         // in the case where there is a {value constraint}, and the element
708
// doesn't have any text content, change emptyElement call to
709
// start + characters + end
710
fDefaultValue = null;
711         // fElementDepth == -2 indicates that the schema validator was removed
712
// from the pipeline. then we don't need to call handleEndElement.
713
if (fElementDepth != -2)
714             modifiedAugs = handleEndElement(element, modifiedAugs);
715
716         // call handlers
717
if (fDocumentHandler != null) {
718             if (!fSchemaElementDefault || fDefaultValue == null) {
719                 fDocumentHandler.emptyElement(element, attributes, modifiedAugs);
720             } else {
721                 fDocumentHandler.startElement(element, attributes, modifiedAugs);
722                 fDocumentHandler.characters(fDefaultValue, null);
723                 fDocumentHandler.endElement(element, modifiedAugs);
724             }
725         }
726     } // emptyElement(QName,XMLAttributes, Augmentations)
727

728     /**
729      * Character content.
730      *
731      * @param text The content.
732      * @param augs Additional information that may include infoset augmentations
733      *
734      * @throws XNIException Thrown by handler to signal an error.
735      */

736     public void characters(XMLString text, Augmentations augs) throws XNIException {
737
738         text = handleCharacters(text);
739         // call handlers
740
if (fDocumentHandler != null) {
741             if (fNormalizeData && fUnionType) {
742                 // for union types we can't normalize data
743
// thus we only need to send augs information if any;
744
// the normalized data for union will be send
745
// after normalization is performed (at the endElement())
746
if (augs != null)
747                     fDocumentHandler.characters(fEmptyXMLStr, augs);
748             } else {
749                 fDocumentHandler.characters(text, augs);
750             }
751         }
752
753     } // characters(XMLString)
754

755     /**
756      * Ignorable whitespace. For this method to be called, the document
757      * source must have some way of determining that the text containing
758      * only whitespace characters should be considered ignorable. For
759      * example, the validator can determine if a length of whitespace
760      * characters in the document are ignorable based on the element
761      * content model.
762      *
763      * @param text The ignorable whitespace.
764      * @param augs Additional information that may include infoset augmentations
765      *
766      * @throws XNIException Thrown by handler to signal an error.
767      */

768     public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
769
770         handleIgnorableWhitespace(text);
771         // call handlers
772
if (fDocumentHandler != null) {
773             fDocumentHandler.ignorableWhitespace(text, augs);
774         }
775
776     } // ignorableWhitespace(XMLString)
777

778     /**
779      * The end of an element.
780      *
781      * @param element The name of the element.
782      * @param augs Additional information that may include infoset augmentations
783      *
784      * @throws XNIException Thrown by handler to signal an error.
785      */

786     public void endElement(QName element, Augmentations augs) throws XNIException {
787
788         // in the case where there is a {value constraint}, and the element
789
// doesn't have any text content, add a characters call.
790
fDefaultValue = null;
791         Augmentations modifiedAugs = handleEndElement(element, augs);
792         // call handlers
793
if (fDocumentHandler != null) {
794             if (!fSchemaElementDefault || fDefaultValue == null) {
795                 fDocumentHandler.endElement(element, modifiedAugs);
796             } else {
797                 fDocumentHandler.characters(fDefaultValue, null);
798                 fDocumentHandler.endElement(element, modifiedAugs);
799             }
800         }
801     } // endElement(QName, Augmentations)
802

803     /**
804     * The start of a CDATA section.
805     *
806     * @param augs Additional information that may include infoset augmentations
807     *
808     * @throws XNIException Thrown by handler to signal an error.
809     */

810     public void startCDATA(Augmentations augs) throws XNIException {
811
812         // REVISIT: what should we do here if schema normalization is on??
813
fInCDATA = true;
814         // call handlers
815
if (fDocumentHandler != null) {
816             fDocumentHandler.startCDATA(augs);
817         }
818
819     } // startCDATA()
820

821     /**
822      * The end of a CDATA section.
823      *
824      * @param augs Additional information that may include infoset augmentations
825      *
826      * @throws XNIException Thrown by handler to signal an error.
827      */

828     public void endCDATA(Augmentations augs) throws XNIException {
829
830         // call handlers
831
fInCDATA = false;
832         if (fDocumentHandler != null) {
833             fDocumentHandler.endCDATA(augs);
834         }
835
836     } // endCDATA()
837

838     /**
839      * The end of the document.
840      *
841      * @param augs Additional information that may include infoset augmentations
842      *
843      * @throws XNIException Thrown by handler to signal an error.
844      */

845     public void endDocument(Augmentations augs) throws XNIException {
846
847         handleEndDocument();
848
849         // call handlers
850
if (fDocumentHandler != null) {
851             fDocumentHandler.endDocument(augs);
852         }
853         fLocator = null;
854
855     } // endDocument(Augmentations)
856

857     //
858
// DOMRevalidationHandler methods
859
//
860

861
862
863
864
865     public boolean characterData(String JavaDoc data, Augmentations augs) {
866
867         fSawText = fSawText || data.length() > 0;
868
869         // REVISIT: this methods basically duplicates implementation of
870
// handleCharacters(). We should be able to reuse some code
871

872         // if whitespace == -1 skip normalization, because it is a complexType
873
// or a union type.
874
if (fNormalizeData && fWhiteSpace != -1 && fWhiteSpace != XSSimpleType.WS_PRESERVE) {
875             // normalize data
876
normalizeWhitespace(data, fWhiteSpace == XSSimpleType.WS_COLLAPSE);
877             fBuffer.append(fNormalizedStr.ch, fNormalizedStr.offset, fNormalizedStr.length);
878         } else {
879             if (fAppendBuffer)
880                 fBuffer.append(data);
881         }
882
883         // When it's a complex type with element-only content, we need to
884
// find out whether the content contains any non-whitespace character.
885
boolean allWhiteSpace = true;
886         if (fCurrentType != null
887             && fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
888             XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
889             if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
890                 // data outside of element content
891
for (int i = 0; i < data.length(); i++) {
892                     if (!XMLChar.isSpace(data.charAt(i))) {
893                         allWhiteSpace = false;
894                         fSawCharacters = true;
895                         break;
896                     }
897                 }
898             }
899         }
900
901         return allWhiteSpace;
902     }
903
904     public void elementDefault(String JavaDoc data) {
905         // no-op
906
}
907
908     //
909
// XMLDocumentHandler and XMLDTDHandler methods
910
//
911

912     /**
913      * This method notifies the start of a general entity.
914      * <p>
915      * <strong>Note:</strong> This method is not called for entity references
916      * appearing as part of attribute values.
917      *
918      * @param name The name of the general entity.
919      * @param identifier The resource identifier.
920      * @param encoding The auto-detected IANA encoding name of the entity
921      * stream. This value will be null in those situations
922      * where the entity encoding is not auto-detected (e.g.
923      * internal entities or a document entity that is
924      * parsed from a java.io.Reader).
925      * @param augs Additional information that may include infoset augmentations
926      *
927      * @exception XNIException Thrown by handler to signal an error.
928      */

929     public void startGeneralEntity(
930         String JavaDoc name,
931         XMLResourceIdentifier identifier,
932         String JavaDoc encoding,
933         Augmentations augs)
934         throws XNIException {
935
936         // REVISIT: what should happen if normalize_data_ is on??
937
fEntityRef = true;
938         // call handlers
939
if (fDocumentHandler != null) {
940             fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
941         }
942
943     } // startEntity(String,String,String,String,String)
944

945     /**
946      * Notifies of the presence of a TextDecl line in an entity. If present,
947      * this method will be called immediately following the startEntity call.
948      * <p>
949      * <strong>Note:</strong> This method will never be called for the
950      * document entity; it is only called for external general entities
951      * referenced in document content.
952      * <p>
953      * <strong>Note:</strong> This method is not called for entity references
954      * appearing as part of attribute values.
955      *
956      * @param version The XML version, or null if not specified.
957      * @param encoding The IANA encoding name of the entity.
958      * @param augs Additional information that may include infoset augmentations
959      *
960      * @throws XNIException Thrown by handler to signal an error.
961      */

962     public void textDecl(String JavaDoc version, String JavaDoc encoding, Augmentations augs) throws XNIException {
963
964         // call handlers
965
if (fDocumentHandler != null) {
966             fDocumentHandler.textDecl(version, encoding, augs);
967         }
968
969     } // textDecl(String,String)
970

971     /**
972      * A comment.
973      *
974      * @param text The text in the comment.
975      * @param augs Additional information that may include infoset augmentations
976      *
977      * @throws XNIException Thrown by application to signal an error.
978      */

979     public void comment(XMLString text, Augmentations augs) throws XNIException {
980         
981         // call handlers
982
if (fDocumentHandler != null) {
983             fDocumentHandler.comment(text, augs);
984         }
985
986     } // comment(XMLString)
987

988     /**
989      * A processing instruction. Processing instructions consist of a
990      * target name and, optionally, text data. The data is only meaningful
991      * to the application.
992      * <p>
993      * Typically, a processing instruction's data will contain a series
994      * of pseudo-attributes. These pseudo-attributes follow the form of
995      * element attributes but are <strong>not</strong> parsed or presented
996      * to the application as anything other than text. The application is
997      * responsible for parsing the data.
998      *
999      * @param target The target.
1000     * @param data The data or null if none specified.
1001     * @param augs Additional information that may include infoset augmentations
1002     *
1003     * @throws XNIException Thrown by handler to signal an error.
1004     */

1005    public void processingInstruction(String JavaDoc target, XMLString data, Augmentations augs)
1006        throws XNIException {
1007
1008        // call handlers
1009
if (fDocumentHandler != null) {
1010            fDocumentHandler.processingInstruction(target, data, augs);
1011        }
1012
1013    } // processingInstruction(String,XMLString)
1014

1015    /**
1016     * This method notifies the end of a general entity.
1017     * <p>
1018     * <strong>Note:</strong> This method is not called for entity references
1019     * appearing as part of attribute values.
1020     *
1021     * @param name The name of the entity.
1022     * @param augs Additional information that may include infoset augmentations
1023     *
1024     * @exception XNIException
1025     * Thrown by handler to signal an error.
1026     */

1027    public void endGeneralEntity(String JavaDoc name, Augmentations augs) throws XNIException {
1028
1029        // call handlers
1030
fEntityRef = false;
1031        if (fDocumentHandler != null) {
1032            fDocumentHandler.endGeneralEntity(name, augs);
1033        }
1034
1035    } // endEntity(String)
1036

1037    // constants
1038

1039    static final int INITIAL_STACK_SIZE = 8;
1040    static final int INC_STACK_SIZE = 8;
1041
1042    //
1043
// Data
1044
//
1045

1046    // Schema Normalization
1047

1048    private static final boolean DEBUG_NORMALIZATION = false;
1049    // temporary empty string buffer.
1050
private final XMLString fEmptyXMLStr = new XMLString(null, 0, -1);
1051    // temporary character buffer, and empty string buffer.
1052
private static final int BUFFER_SIZE = 20;
1053    private final XMLString fNormalizedStr = new XMLString();
1054    private boolean fFirstChunk = true;
1055    // got first chunk in characters() (SAX)
1056
private boolean fTrailing = false; // Previous chunk had a trailing space
1057
private short fWhiteSpace = -1; //whiteSpace: preserve/replace/collapse
1058
private boolean fUnionType = false;
1059
1060    /** Schema grammar resolver. */
1061    private final XSGrammarBucket fGrammarBucket = new XSGrammarBucket();
1062    private final SubstitutionGroupHandler fSubGroupHandler = new SubstitutionGroupHandler(fGrammarBucket);
1063
1064    /** the DV usd to convert xsi:type to a QName */
1065    // REVISIT: in new simple type design, make things in DVs static,
1066
// so that we can QNameDV.getCompiledForm()
1067
private final XSSimpleType fQNameDV =
1068        (XSSimpleType) SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(SchemaSymbols.ATTVAL_QNAME);
1069
1070    private final CMNodeFactory nodeFactory = new CMNodeFactory();
1071    /** used to build content models */
1072    // REVISIT: create decl pool, and pass it to each traversers
1073
private final CMBuilder fCMBuilder = new CMBuilder(nodeFactory);
1074    
1075    // Schema grammar loader
1076
private final XMLSchemaLoader fSchemaLoader =
1077        new XMLSchemaLoader(
1078                fXSIErrorReporter.fErrorReporter,
1079                fGrammarBucket,
1080                fSubGroupHandler,
1081                fCMBuilder);
1082
1083    // state
1084

1085    /** String representation of the validation root. */
1086    // REVISIT: what do we store here? QName, XPATH, some ID? use rawname now.
1087
private String JavaDoc fValidationRoot;
1088
1089    /** Skip validation: anything below this level should be skipped */
1090    private int fSkipValidationDepth;
1091
1092    /** anything above this level has validation_attempted != full */
1093    private int fNFullValidationDepth;
1094
1095    /** anything above this level has validation_attempted != none */
1096    private int fNNoneValidationDepth;
1097
1098    /** Element depth: -2: validator not in pipeline; >= -1 current depth. */
1099    private int fElementDepth;
1100
1101    /** Seen sub elements. */
1102    private boolean fSubElement;
1103
1104    /** Seen sub elements stack. */
1105    private boolean[] fSubElementStack = new boolean[INITIAL_STACK_SIZE];
1106
1107    /** Current element declaration. */
1108    private XSElementDecl fCurrentElemDecl;
1109
1110    /** Element decl stack. */
1111    private XSElementDecl[] fElemDeclStack = new XSElementDecl[INITIAL_STACK_SIZE];
1112
1113    /** nil value of the current element */
1114    private boolean fNil;
1115
1116    /** nil value stack */
1117    private boolean[] fNilStack = new boolean[INITIAL_STACK_SIZE];
1118
1119    /** notation value of the current element */
1120    private XSNotationDecl fNotation;
1121
1122    /** notation stack */
1123    private XSNotationDecl[] fNotationStack = new XSNotationDecl[INITIAL_STACK_SIZE];
1124
1125    /** Current type. */
1126    private XSTypeDefinition fCurrentType;
1127
1128    /** type stack. */
1129    private XSTypeDefinition[] fTypeStack = new XSTypeDefinition[INITIAL_STACK_SIZE];
1130
1131    /** Current content model. */
1132    private XSCMValidator fCurrentCM;
1133
1134    /** Content model stack. */
1135    private XSCMValidator[] fCMStack = new XSCMValidator[INITIAL_STACK_SIZE];
1136
1137    /** the current state of the current content model */
1138    private int[] fCurrCMState;
1139
1140    /** stack to hold content model states */
1141    private int[][] fCMStateStack = new int[INITIAL_STACK_SIZE][];
1142
1143    /** whether the curret element is strictly assessed */
1144    private boolean fStrictAssess = true;
1145
1146    /** strict assess stack */
1147    private boolean[] fStrictAssessStack = new boolean[INITIAL_STACK_SIZE];
1148
1149    /** Temporary string buffers. */
1150    private final StringBuffer JavaDoc fBuffer = new StringBuffer JavaDoc();
1151
1152    /** Whether need to append characters to fBuffer */
1153    private boolean fAppendBuffer = true;
1154
1155    /** Did we see any character data? */
1156    private boolean fSawText = false;
1157
1158    /** stack to record if we saw character data */
1159    private boolean[] fSawTextStack = new boolean[INITIAL_STACK_SIZE];
1160
1161    /** Did we see non-whitespace character data? */
1162    private boolean fSawCharacters = false;
1163
1164    /** Stack to record if we saw character data outside of element content*/
1165    private boolean[] fStringContent = new boolean[INITIAL_STACK_SIZE];
1166
1167    /** temporary qname */
1168    private final QName fTempQName = new QName();
1169
1170    /** temporary validated info */
1171    private ValidatedInfo fValidatedInfo = new ValidatedInfo();
1172
1173    // used to validate default/fixed values against xsi:type
1174
// only need to check facets, so we set extraChecking to false (in reset)
1175
private ValidationState fState4XsiType = new ValidationState();
1176
1177    // used to apply default/fixed values
1178
// only need to check id/idref/entity, so we set checkFacets to false
1179
private ValidationState fState4ApplyDefault = new ValidationState();
1180
1181    // identity constraint information
1182

1183    /**
1184     * Stack of active XPath matchers for identity constraints. All
1185     * active XPath matchers are notified of startElement
1186     * and endElement callbacks in order to perform their matches.
1187     * <p>
1188     * For each element with identity constraints, the selector of
1189     * each identity constraint is activated. When the selector matches
1190     * its XPath, then all the fields of the identity constraint are
1191     * activated.
1192     * <p>
1193     * <strong>Note:</strong> Once the activation scope is left, the
1194     * XPath matchers are automatically removed from the stack of
1195     * active matchers and no longer receive callbacks.
1196     */

1197    protected XPathMatcherStack fMatcherStack = new XPathMatcherStack();
1198
1199    /** Cache of value stores for identity constraint fields. */
1200    protected ValueStoreCache fValueStoreCache = new ValueStoreCache();
1201
1202    //
1203
// Constructors
1204
//
1205

1206    /** Default constructor. */
1207    public XMLSchemaValidator() {
1208        fState4XsiType.setExtraChecking(false);
1209        fState4ApplyDefault.setFacetChecking(false);
1210
1211    } // <init>()
1212

1213    /*
1214     * Resets the component. The component can query the component manager
1215     * about any features and properties that affect the operation of the
1216     * component.
1217     *
1218     * @param componentManager The component manager.
1219     *
1220     * @throws SAXException Thrown by component on finitialization error.
1221     * For example, if a feature or property is
1222     * required for the operation of the component, the
1223     * component manager may throw a
1224     * SAXNotRecognizedException or a
1225     * SAXNotSupportedException.
1226     */

1227    public void reset(XMLComponentManager componentManager) throws XMLConfigurationException {
1228
1229
1230        fIdConstraint = false;
1231        //reset XSDDescription
1232
fLocationPairs.clear();
1233
1234        // cleanup id table
1235
fValidationState.resetIDTables();
1236
1237        //pass the component manager to the factory..
1238
nodeFactory.reset(componentManager);
1239
1240        // reset schema loader
1241
fSchemaLoader.reset(componentManager);
1242
1243        // initialize state
1244
fCurrentElemDecl = null;
1245        fCurrentCM = null;
1246        fCurrCMState = null;
1247        fSkipValidationDepth = -1;
1248        fNFullValidationDepth = -1;
1249        fNNoneValidationDepth = -1;
1250        fElementDepth = -1;
1251        fSubElement = false;
1252        fSchemaDynamicValidation = false;
1253
1254        // datatype normalization
1255
fEntityRef = false;
1256        fInCDATA = false;
1257
1258        fMatcherStack.clear();
1259
1260        if (!fMayMatchFieldMap.isEmpty()) {
1261            // should only clear this if the last schema had identity constraints.
1262
fMayMatchFieldMap.clear();
1263        }
1264
1265        // get error reporter
1266
fXSIErrorReporter.reset((XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER));
1267
1268        boolean parser_settings;
1269        try {
1270            parser_settings = componentManager.getFeature(PARSER_SETTINGS);
1271        }
1272        catch (XMLConfigurationException e){
1273            parser_settings = true;
1274        }
1275
1276        if (!parser_settings){
1277            // parser settings have not been changed
1278
fValidationManager.addValidationState(fValidationState);
1279            // Re-parse external schema location properties.
1280
XMLSchemaLoader.processExternalHints(
1281                fExternalSchemas,
1282                fExternalNoNamespaceSchema,
1283                fLocationPairs,
1284                fXSIErrorReporter.fErrorReporter);
1285            return;
1286        }
1287
1288
1289        // get symbol table. if it's a new one, add symbols to it.
1290
SymbolTable symbolTable = (SymbolTable) componentManager.getProperty(SYMBOL_TABLE);
1291        if (symbolTable != fSymbolTable) {
1292            fSymbolTable = symbolTable;
1293        }
1294
1295        try {
1296            fDynamicValidation = componentManager.getFeature(DYNAMIC_VALIDATION);
1297        } catch (XMLConfigurationException e) {
1298            fDynamicValidation = false;
1299        }
1300
1301        if (fDynamicValidation) {
1302            fDoValidation = true;
1303        } else {
1304            try {
1305                fDoValidation = componentManager.getFeature(VALIDATION);
1306            } catch (XMLConfigurationException e) {
1307                fDoValidation = false;
1308            }
1309        }
1310
1311        if (fDoValidation) {
1312            try {
1313                fDoValidation = componentManager.getFeature(XMLSchemaValidator.SCHEMA_VALIDATION);
1314            } catch (XMLConfigurationException e) {
1315            }
1316        }
1317
1318        try {
1319            fFullChecking = componentManager.getFeature(SCHEMA_FULL_CHECKING);
1320        } catch (XMLConfigurationException e) {
1321            fFullChecking = false;
1322        }
1323
1324        try {
1325            fNormalizeData = componentManager.getFeature(NORMALIZE_DATA);
1326        } catch (XMLConfigurationException e) {
1327            fNormalizeData = false;
1328        }
1329
1330        try {
1331            fSchemaElementDefault = componentManager.getFeature(SCHEMA_ELEMENT_DEFAULT);
1332        } catch (XMLConfigurationException e) {
1333            fSchemaElementDefault = false;
1334        }
1335
1336        try {
1337            fAugPSVI = componentManager.getFeature(SCHEMA_AUGMENT_PSVI);
1338        } catch (XMLConfigurationException e) {
1339            fAugPSVI = true;
1340        }
1341        try {
1342            fSchemaType =
1343                (String JavaDoc) componentManager.getProperty(
1344                    Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE);
1345        } catch (XMLConfigurationException e) {
1346            fSchemaType = null;
1347        }
1348        
1349        try {
1350            fUseGrammarPoolOnly = componentManager.getFeature(USE_GRAMMAR_POOL_ONLY);
1351        }
1352        catch (XMLConfigurationException e) {
1353            fUseGrammarPoolOnly = false;
1354        }
1355
1356        fEntityResolver = (XMLEntityResolver) componentManager.getProperty(ENTITY_MANAGER);
1357
1358        fValidationManager = (ValidationManager) componentManager.getProperty(VALIDATION_MANAGER);
1359        fValidationManager.addValidationState(fValidationState);
1360        fValidationState.setSymbolTable(fSymbolTable);
1361
1362
1363        // get schema location properties
1364
try {
1365            fExternalSchemas = (String JavaDoc) componentManager.getProperty(SCHEMA_LOCATION);
1366            fExternalNoNamespaceSchema =
1367                (String JavaDoc) componentManager.getProperty(SCHEMA_NONS_LOCATION);
1368        } catch (XMLConfigurationException e) {
1369            fExternalSchemas = null;
1370            fExternalNoNamespaceSchema = null;
1371        }
1372
1373        // store the external schema locations. they are set when reset is called,
1374
// so any other schemaLocation declaration for the same namespace will be
1375
// effectively ignored. becuase we choose to take first location hint
1376
// available for a particular namespace.
1377
XMLSchemaLoader.processExternalHints(
1378            fExternalSchemas,
1379            fExternalNoNamespaceSchema,
1380            fLocationPairs,
1381            fXSIErrorReporter.fErrorReporter);
1382
1383        try {
1384            fJaxpSchemaSource = componentManager.getProperty(JAXP_SCHEMA_SOURCE);
1385        } catch (XMLConfigurationException e) {
1386            fJaxpSchemaSource = null;
1387
1388        }
1389
1390        // clear grammars, and put the one for schema namespace there
1391
try {
1392            fGrammarPool = (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL);
1393        } catch (XMLConfigurationException e) {
1394            fGrammarPool = null;
1395        }
1396
1397        fState4XsiType.setSymbolTable(symbolTable);
1398        fState4ApplyDefault.setSymbolTable(symbolTable);
1399
1400    } // reset(XMLComponentManager)
1401

1402    //
1403
// FieldActivator methods
1404
//
1405

1406    /**
1407     * Start the value scope for the specified identity constraint. This
1408     * method is called when the selector matches in order to initialize
1409     * the value store.
1410     *
1411     * @param identityConstraint The identity constraint.
1412     */

1413    public void startValueScopeFor(IdentityConstraint identityConstraint, int initialDepth) {
1414
1415        ValueStoreBase valueStore =
1416            fValueStoreCache.getValueStoreFor(identityConstraint, initialDepth);
1417        valueStore.startValueScope();
1418
1419    } // startValueScopeFor(IdentityConstraint identityConstraint)
1420

1421    /**
1422     * Request to activate the specified field. This method returns the
1423     * matcher for the field.
1424     *
1425     * @param field The field to activate.
1426     */

1427    public XPathMatcher activateField(Field field, int initialDepth) {
1428        ValueStore valueStore =
1429            fValueStoreCache.getValueStoreFor(field.getIdentityConstraint(), initialDepth);
1430        setMayMatch(field, Boolean.TRUE);
1431        XPathMatcher matcher = field.createMatcher(this, valueStore);
1432        fMatcherStack.addMatcher(matcher);
1433        matcher.startDocumentFragment();
1434        return matcher;
1435    } // activateField(Field):XPathMatcher
1436

1437    /**
1438     * Ends the value scope for the specified identity constraint.
1439     *
1440     * @param identityConstraint The identity constraint.
1441     */

1442    public void endValueScopeFor(IdentityConstraint identityConstraint, int initialDepth) {
1443
1444        ValueStoreBase valueStore =
1445            fValueStoreCache.getValueStoreFor(identityConstraint, initialDepth);
1446        valueStore.endValueScope();
1447
1448    } // endValueScopeFor(IdentityConstraint)
1449

1450    /**
1451     * Sets whether the given field is permitted to match a value.
1452     * This should be used to catch instance documents that try
1453     * and match a field several times in the same scope.
1454     *
1455     * @param field The field that may be permitted to be matched.
1456     * @param state Boolean indiciating whether the field may be matched.
1457     */

1458    public void setMayMatch(Field field, Boolean JavaDoc state) {
1459        fMayMatchFieldMap.put(field, state);
1460    } // setMayMatch(Field, Boolean)
1461

1462    /**
1463     * Returns whether the given field is permitted to match a value.
1464     *
1465     * @param field The field that may be permitted to be matched.
1466     * @return Boolean indicating whether the field may be matched.
1467     */

1468    public Boolean JavaDoc mayMatch(Field field) {
1469        return (Boolean JavaDoc) fMayMatchFieldMap.get(field);
1470    } // mayMatch(Field):Boolean
1471

1472    // a utility method for Identity constraints
1473
private void activateSelectorFor(IdentityConstraint ic) {
1474        Selector selector = ic.getSelector();
1475        FieldActivator activator = this;
1476        if (selector == null)
1477            return;
1478        XPathMatcher matcher = selector.createMatcher(activator, fElementDepth);
1479        fMatcherStack.addMatcher(matcher);
1480        matcher.startDocumentFragment();
1481    }
1482
1483    //
1484
// Protected methods
1485
//
1486

1487    /** ensure element stack capacity */
1488    void ensureStackCapacity() {
1489
1490        if (fElementDepth == fElemDeclStack.length) {
1491            int newSize = fElementDepth + INC_STACK_SIZE;
1492            boolean[] newArrayB = new boolean[newSize];
1493            System.arraycopy(fSubElementStack, 0, newArrayB, 0, fElementDepth);
1494            fSubElementStack = newArrayB;
1495
1496            XSElementDecl[] newArrayE = new XSElementDecl[newSize];
1497            System.arraycopy(fElemDeclStack, 0, newArrayE, 0, fElementDepth);
1498            fElemDeclStack = newArrayE;
1499
1500            newArrayB = new boolean[newSize];
1501            System.arraycopy(fNilStack, 0, newArrayB, 0, fElementDepth);
1502            fNilStack = newArrayB;
1503
1504            XSNotationDecl[] newArrayN = new XSNotationDecl[newSize];
1505            System.arraycopy(fNotationStack, 0, newArrayN, 0, fElementDepth);
1506            fNotationStack = newArrayN;
1507
1508            XSTypeDefinition[] newArrayT = new XSTypeDefinition[newSize];
1509            System.arraycopy(fTypeStack, 0, newArrayT, 0, fElementDepth);
1510            fTypeStack = newArrayT;
1511
1512            XSCMValidator[] newArrayC = new XSCMValidator[newSize];
1513            System.arraycopy(fCMStack, 0, newArrayC, 0, fElementDepth);
1514            fCMStack = newArrayC;
1515
1516            newArrayB = new boolean[newSize];
1517            System.arraycopy(fSawTextStack, 0, newArrayB, 0, fElementDepth);
1518            fSawTextStack = newArrayB;
1519
1520            newArrayB = new boolean[newSize];
1521            System.arraycopy(fStringContent, 0, newArrayB, 0, fElementDepth);
1522            fStringContent = newArrayB;
1523
1524            newArrayB = new boolean[newSize];
1525            System.arraycopy(fStrictAssessStack, 0, newArrayB, 0, fElementDepth);
1526            fStrictAssessStack = newArrayB;
1527
1528            int[][] newArrayIA = new int[newSize][];
1529            System.arraycopy(fCMStateStack, 0, newArrayIA, 0, fElementDepth);
1530            fCMStateStack = newArrayIA;
1531        }
1532
1533    } // ensureStackCapacity
1534

1535    // handle start document
1536
void handleStartDocument(XMLLocator locator, String JavaDoc encoding) {
1537        fValueStoreCache.startDocument();
1538        if (fAugPSVI) {
1539            fCurrentPSVI.fGrammars = null;
1540            fCurrentPSVI.fSchemaInformation = null;
1541        }
1542    } // handleStartDocument(XMLLocator,String)
1543

1544    void handleEndDocument() {
1545        fValueStoreCache.endDocument();
1546    } // handleEndDocument()
1547

1548    // handle character contents
1549
// returns the normalized string if possible, otherwise the original string
1550
XMLString handleCharacters(XMLString text) {
1551
1552        if (fSkipValidationDepth >= 0)
1553            return text;
1554
1555        fSawText = fSawText || text.length > 0;
1556
1557        // Note: data in EntityRef and CDATA is normalized as well
1558
// if whitespace == -1 skip normalization, because it is a complexType
1559
// or a union type.
1560
if (fNormalizeData && fWhiteSpace != -1 && fWhiteSpace != XSSimpleType.WS_PRESERVE) {
1561            // normalize data
1562
normalizeWhitespace(text, fWhiteSpace == XSSimpleType.WS_COLLAPSE);
1563            text = fNormalizedStr;
1564        }
1565        if (fAppendBuffer)
1566            fBuffer.append(text.ch, text.offset, text.length);
1567
1568        // When it's a complex type with element-only content, we need to
1569
// find out whether the content contains any non-whitespace character.
1570
if (fCurrentType != null
1571            && fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
1572            XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
1573            if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
1574                // data outside of element content
1575
for (int i = text.offset; i < text.offset + text.length; i++) {
1576                    if (!XMLChar.isSpace(text.ch[i])) {
1577                        fSawCharacters = true;
1578                        break;
1579                    }
1580                }
1581            }
1582        }
1583
1584        return text;
1585    } // handleCharacters(XMLString)
1586

1587    /**
1588     * Normalize whitespace in an XMLString according to the rules defined
1589     * in XML Schema specifications.
1590     * @param value The string to normalize.
1591     * @param collapse replace or collapse
1592     */

1593    private void normalizeWhitespace(XMLString value, boolean collapse) {
1594        boolean skipSpace = collapse;
1595        boolean sawNonWS = false;
1596        boolean leading = false;
1597        boolean trailing = false;
1598        char c;
1599        int size = value.offset + value.length;
1600
1601        // ensure the ch array is big enough
1602
if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < value.length + 1) {
1603            fNormalizedStr.ch = new char[value.length + 1];
1604        }
1605        // don't include the leading ' ' for now. might include it later.
1606
fNormalizedStr.offset = 1;
1607        fNormalizedStr.length = 1;
1608
1609        for (int i = value.offset; i < size; i++) {
1610            c = value.ch[i];
1611            if (XMLChar.isSpace(c)) {
1612                if (!skipSpace) {
1613                    // take the first whitespace as a space and skip the others
1614
fNormalizedStr.ch[fNormalizedStr.length++] = ' ';
1615                    skipSpace = collapse;
1616                }
1617                if (!sawNonWS) {
1618                    // this is a leading whitespace, record it
1619
leading = true;
1620                }
1621            } else {
1622                fNormalizedStr.ch[fNormalizedStr.length++] = c;
1623                skipSpace = false;
1624                sawNonWS = true;
1625            }
1626        }
1627        if (skipSpace) {
1628            if (fNormalizedStr.length > 1) {
1629                // if we finished on a space trim it but also record it
1630
fNormalizedStr.length--;
1631                trailing = true;
1632            } else if (leading && !fFirstChunk) {
1633                // if all we had was whitespace we skipped record it as
1634
// trailing whitespace as well
1635
trailing = true;
1636            }
1637        }
1638
1639        if (fNormalizedStr.length > 1) {
1640            if (!fFirstChunk && (fWhiteSpace == XSSimpleType.WS_COLLAPSE)) {
1641                if (fTrailing) {
1642                    // previous chunk ended on whitespace
1643
// insert whitespace
1644
fNormalizedStr.offset = 0;
1645                    fNormalizedStr.ch[0] = ' ';
1646                } else if (leading) {
1647                    // previous chunk ended on character,
1648
// this chunk starts with whitespace
1649
fNormalizedStr.offset = 0;
1650                    fNormalizedStr.ch[0] = ' ';
1651                }
1652            }
1653        }
1654
1655        // The length includes the leading ' '. Now removing it.
1656
fNormalizedStr.length -= fNormalizedStr.offset;
1657
1658        fTrailing = trailing;
1659
1660        if (trailing || sawNonWS)
1661            fFirstChunk = false;
1662    }
1663
1664    private void normalizeWhitespace(String JavaDoc value, boolean collapse) {
1665        boolean skipSpace = collapse;
1666        char c;
1667        int size = value.length();
1668
1669        // ensure the ch array is big enough
1670
if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < size) {
1671            fNormalizedStr.ch = new char[size];
1672        }
1673        fNormalizedStr.offset = 0;
1674        fNormalizedStr.length = 0;
1675
1676        for (int i = 0; i < size; i++) {
1677            c = value.charAt(i);
1678            if (XMLChar.isSpace(c)) {
1679                if (!skipSpace) {
1680                    // take the first whitespace as a space and skip the others
1681
fNormalizedStr.ch[fNormalizedStr.length++] = ' ';
1682                    skipSpace = collapse;
1683                }
1684            } else {
1685                fNormalizedStr.ch[fNormalizedStr.length++] = c;
1686                skipSpace = false;
1687            }
1688        }
1689        if (skipSpace) {
1690            if (fNormalizedStr.length != 0)
1691                // if we finished on a space trim it but also record it
1692
fNormalizedStr.length--;
1693        }
1694    }
1695
1696    // handle ignorable whitespace
1697
void handleIgnorableWhitespace(XMLString text) {
1698
1699        if (fSkipValidationDepth >= 0)
1700            return;
1701
1702        // REVISIT: the same process needs to be performed as handleCharacters.
1703
// only it's simpler here: we know all characters are whitespaces.
1704

1705    } // handleIgnorableWhitespace(XMLString)
1706

1707    /** Handle element. */
1708    Augmentations handleStartElement(QName element, XMLAttributes attributes, Augmentations augs) {
1709
1710        if (DEBUG) {
1711            System.out.println("==>handleStartElement: " + element);
1712        }
1713
1714        // root element
1715
if (fElementDepth == -1 && fValidationManager.isGrammarFound()) {
1716            if (fSchemaType == null) {
1717                // schemaType is not specified
1718
// if a DTD grammar is found, we do the same thing as Dynamic:
1719
// if a schema grammar is found, validation is performed;
1720
// otherwise, skip the whole document.
1721
fSchemaDynamicValidation = true;
1722            } else {
1723                // [1] Either schemaType is DTD, and in this case validate/schema is turned off
1724
// [2] Validating against XML Schemas only
1725
// [a] dynamic validation is false: report error if SchemaGrammar is not found
1726
// [b] dynamic validation is true: if grammar is not found ignore.
1727
}
1728
1729        }
1730
1731        // get xsi:schemaLocation and xsi:noNamespaceSchemaLocation attributes,
1732
// parse them to get the grammars
1733

1734        String JavaDoc sLocation =
1735            attributes.getValue(SchemaSymbols.URI_XSI, SchemaSymbols.XSI_SCHEMALOCATION);
1736        String JavaDoc nsLocation =
1737            attributes.getValue(SchemaSymbols.URI_XSI, SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION);
1738        //store the location hints.. we need to do it so that we can defer the loading of grammar until
1739
//there is a reference to a component from that namespace. To provide location hints to the
1740
//application for a namespace
1741
storeLocations(sLocation, nsLocation);
1742
1743        // if we are in the content of "skip", then just skip this element
1744
// REVISIT: is this the correct behaviour for ID constraints? -NG
1745
if (fSkipValidationDepth >= 0) {
1746            fElementDepth++;
1747            if (fAugPSVI)
1748                augs = getEmptyAugs(augs);
1749            return augs;
1750        }
1751
1752        //try to find schema grammar by different means..
1753
SchemaGrammar sGrammar =
1754            findSchemaGrammar(
1755                XSDDescription.CONTEXT_ELEMENT,
1756                element.uri,
1757                null,
1758                element,
1759                attributes);
1760
1761        // if we are not skipping this element, and there is a content model,
1762
// we try to find the corresponding decl object for this element.
1763
// the reason we move this part of code here is to make sure the
1764
// error reported here (if any) is stored within the parent element's
1765
// context, instead of that of the current element.
1766
Object JavaDoc decl = null;
1767        if (fCurrentCM != null) {
1768            decl = fCurrentCM.oneTransition(element, fCurrCMState, fSubGroupHandler);
1769            // it could be an element decl or a wildcard decl
1770
if (fCurrCMState[0] == XSCMValidator.FIRST_ERROR) {
1771                XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
1772                //REVISIT: is it the only case we will have particle = null?
1773
Vector JavaDoc next;
1774                if (ctype.fParticle != null
1775                    && (next = fCurrentCM.whatCanGoHere(fCurrCMState)).size() > 0) {
1776                    String JavaDoc expected = expectedStr(next);
1777                    reportSchemaError(
1778                        "cvc-complex-type.2.4.a",
1779                        new Object JavaDoc[] { element.rawname, expected });
1780                } else {
1781                    reportSchemaError("cvc-complex-type.2.4.d", new Object JavaDoc[] { element.rawname });
1782                }
1783            }
1784        }
1785
1786        // if it's not the root element, we push the current states in the stacks
1787
if (fElementDepth != -1) {
1788            ensureStackCapacity();
1789            fSubElementStack[fElementDepth] = true;
1790            fSubElement = false;
1791            fElemDeclStack[fElementDepth] = fCurrentElemDecl;
1792            fNilStack[fElementDepth] = fNil;
1793            fNotationStack[fElementDepth] = fNotation;
1794            fTypeStack[fElementDepth] = fCurrentType;
1795            fStrictAssessStack[fElementDepth] = fStrictAssess;
1796            fCMStack[fElementDepth] = fCurrentCM;
1797            fCMStateStack[fElementDepth] = fCurrCMState;
1798            fSawTextStack[fElementDepth] = fSawText;
1799            fStringContent[fElementDepth] = fSawCharacters;
1800        }
1801
1802        // increase the element depth after we've saved
1803
// all states for the parent element
1804
fElementDepth++;
1805        fCurrentElemDecl = null;
1806        XSWildcardDecl wildcard = null;
1807        fCurrentType = null;
1808        fStrictAssess = true;
1809        fNil = false;
1810        fNotation = null;
1811
1812        // and the buffer to hold the value of the element
1813
fBuffer.setLength(0);
1814        fSawText = false;
1815        fSawCharacters = false;
1816
1817        // check what kind of declaration the "decl" from
1818
// oneTransition() maps to
1819
if (decl != null) {
1820            if (decl instanceof XSElementDecl) {
1821                fCurrentElemDecl = (XSElementDecl) decl;
1822            } else {
1823                wildcard = (XSWildcardDecl) decl;
1824            }
1825        }
1826
1827        // if the wildcard is skip, then return
1828
if (wildcard != null && wildcard.fProcessContents == XSWildcardDecl.PC_SKIP) {
1829            fSkipValidationDepth = fElementDepth;
1830            if (fAugPSVI)
1831                augs = getEmptyAugs(augs);
1832            return augs;
1833        }
1834
1835        // try again to get the element decl:
1836
// case 1: find declaration for root element
1837
// case 2: find declaration for element from another namespace
1838
if (fCurrentElemDecl == null) {
1839            if (sGrammar != null) {
1840                fCurrentElemDecl = sGrammar.getGlobalElementDecl(element.localpart);
1841            }
1842        }
1843
1844        if (fCurrentElemDecl != null) {
1845            // then get the type
1846
fCurrentType = fCurrentElemDecl.fType;
1847        }
1848
1849        // get type from xsi:type
1850
String JavaDoc xsiType = attributes.getValue(SchemaSymbols.URI_XSI, SchemaSymbols.XSI_TYPE);
1851
1852        // if no decl/type found for the current element
1853
if (fCurrentType == null && xsiType == null) {
1854            // if this is the validation root, report an error, because
1855
// we can't find eith decl or type for this element
1856
// REVISIT: should we report error, or warning?
1857
if (fElementDepth == 0) {
1858                // for dynamic validation, skip the whole content,
1859
// because no grammar was found.
1860
if (fDynamicValidation || fSchemaDynamicValidation) {
1861                    // no schema grammar was found, but it's either dynamic
1862
// validation, or another kind of grammar was found (DTD,
1863
// for example). The intended behavior here is to skip
1864
// the whole document. To improve performance, we try to
1865
// remove the validator from the pipeline, since it's not
1866
// supposed to do anything.
1867
if (fDocumentSource != null) {
1868                        fDocumentSource.setDocumentHandler(fDocumentHandler);
1869                        if (fDocumentHandler != null)
1870                            fDocumentHandler.setDocumentSource(fDocumentSource);
1871                        // indicate that the validator was removed.
1872
fElementDepth = -2;
1873                        return augs;
1874                    }
1875
1876                    fSkipValidationDepth = fElementDepth;
1877                    if (fAugPSVI)
1878                        augs = getEmptyAugs(augs);
1879                    return augs;
1880                }
1881                // We don't call reportSchemaError here, because the spec
1882
// doesn't think it's invalid not to be able to find a
1883
// declaration or type definition for an element. Xerces is
1884
// reporting it as an error for historical reasons, but in
1885
// PSVI, we shouldn't mark this element as invalid because
1886
// of this. - SG
1887
fXSIErrorReporter.fErrorReporter.reportError(
1888                    XSMessageFormatter.SCHEMA_DOMAIN,
1889                    "cvc-elt.1",
1890                    new Object JavaDoc[] { element.rawname },
1891                    XMLErrorReporter.SEVERITY_ERROR);
1892            }
1893            // if wildcard = strict, report error.
1894
// needs to be called before fXSIErrorReporter.pushContext()
1895
// so that the error belongs to the parent element.
1896
else if (wildcard != null && wildcard.fProcessContents == XSWildcardDecl.PC_STRICT) {
1897                // report error, because wilcard = strict
1898
reportSchemaError("cvc-complex-type.2.4.c", new Object JavaDoc[] { element.rawname });
1899            }
1900            // no element decl or type found for this element.
1901
// Allowed by the spec, we can choose to either laxly assess this
1902
// element, or to skip it. Now we choose lax assessment.
1903
fCurrentType = SchemaGrammar.fAnyType;
1904            fStrictAssess = false;
1905            fNFullValidationDepth = fElementDepth;
1906            // any type has mixed content, so we don't need to append buffer
1907
fAppendBuffer = false;
1908
1909            // push error reporter context: record the current position
1910
// This has to happen after we process skip contents,
1911
// otherwise push and pop won't be correctly paired.
1912
fXSIErrorReporter.pushContext();
1913        } else {
1914            // push error reporter context: record the current position
1915
// This has to happen after we process skip contents,
1916
// otherwise push and pop won't be correctly paired.
1917
fXSIErrorReporter.pushContext();
1918
1919            // get xsi:type
1920
if (xsiType != null) {
1921                XSTypeDefinition oldType = fCurrentType;
1922                fCurrentType = getAndCheckXsiType(element, xsiType, attributes);
1923                // If it fails, use the old type. Use anyType if ther is no old type.
1924
if (fCurrentType == null) {
1925                    if (oldType == null)
1926                        fCurrentType = SchemaGrammar.fAnyType;
1927                    else
1928                        fCurrentType = oldType;
1929                }
1930            }
1931
1932            fNNoneValidationDepth = fElementDepth;
1933            // if the element has a fixed value constraint, we need to append
1934
if (fCurrentElemDecl != null
1935                && fCurrentElemDecl.getConstraintType() == XSConstants.VC_FIXED) {
1936                fAppendBuffer = true;
1937            }
1938            // if the type is simple, we need to append
1939
else if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
1940                fAppendBuffer = true;
1941            } else {
1942                // if the type is simple content complex type, we need to append
1943
XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
1944                fAppendBuffer = (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE);
1945            }
1946        }
1947
1948        // Element Locally Valid (Element)
1949
// 2 Its {abstract} must be false.
1950
if (fCurrentElemDecl != null && fCurrentElemDecl.getAbstract())
1951            reportSchemaError("cvc-elt.2", new Object JavaDoc[] { element.rawname });
1952
1953        // make the current element validation root
1954
if (fElementDepth == 0) {
1955            fValidationRoot = element.rawname;
1956        }
1957
1958        // update normalization flags
1959
if (fNormalizeData) {
1960            // reset values
1961
fFirstChunk = true;
1962            fTrailing = false;
1963            fUnionType = false;
1964            fWhiteSpace = -1;
1965        }
1966
1967        // Element Locally Valid (Type)
1968
// 2 Its {abstract} must be false.
1969
if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
1970            XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
1971            if (ctype.getAbstract()) {
1972                reportSchemaError("cvc-type.2", new Object JavaDoc[] { element.rawname });
1973            }
1974            if (fNormalizeData) {
1975                // find out if the content type is simple and if variety is union
1976
// to be able to do character normalization
1977
if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
1978                    if (ctype.fXSSimpleType.getVariety() == XSSimpleType.VARIETY_UNION) {
1979                        fUnionType = true;
1980                    } else {
1981                        try {
1982                            fWhiteSpace = ctype.fXSSimpleType.getWhitespace();
1983                        } catch (DatatypeException e) {
1984                            // do nothing
1985
}
1986                    }
1987                }
1988            }
1989        }
1990        // normalization: simple type
1991
else if (fNormalizeData) {
1992            // if !union type
1993
XSSimpleType dv = (XSSimpleType) fCurrentType;
1994            if (dv.getVariety() == XSSimpleType.VARIETY_UNION) {
1995                fUnionType = true;
1996            } else {
1997                try {
1998                    fWhiteSpace = dv.getWhitespace();
1999                } catch (DatatypeException e) {
2000                    // do nothing
2001
}
2002            }
2003        }
2004
2005        // then try to get the content model
2006
fCurrentCM = null;
2007        if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
2008            fCurrentCM = ((XSComplexTypeDecl) fCurrentType).getContentModel(fCMBuilder);
2009        }
2010
2011        // and get the initial content model state
2012
fCurrCMState = null;
2013        if (fCurrentCM != null)
2014            fCurrCMState = fCurrentCM.startContentModel();
2015
2016        // get information about xsi:nil
2017
String JavaDoc xsiNil = attributes.getValue(SchemaSymbols.URI_XSI, SchemaSymbols.XSI_NIL);
2018        // only deal with xsi:nil when there is an element declaration
2019
if (xsiNil != null && fCurrentElemDecl != null)
2020            fNil = getXsiNil(element, xsiNil);
2021
2022        // now validate everything related with the attributes
2023
// first, get the attribute group
2024
XSAttributeGroupDecl attrGrp = null;
2025        if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
2026            XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
2027            attrGrp = ctype.getAttrGrp();
2028        }
2029        // activate identity constraints
2030
fValueStoreCache.startElement();
2031        fMatcherStack.pushContext();
2032        if (fCurrentElemDecl != null && fCurrentElemDecl.fIDCPos > 0) {
2033            fIdConstraint = true;
2034            // initialize when identity constrains are defined for the elem
2035
fValueStoreCache.initValueStoresFor(fCurrentElemDecl, this);
2036        }
2037        processAttributes(element, attributes, attrGrp);
2038
2039        // add default attributes
2040
if (attrGrp != null) {
2041            addDefaultAttributes(element, attributes, attrGrp);
2042        }
2043
2044        // call all active identity constraints
2045
int count = fMatcherStack.getMatcherCount();
2046        for (int i = 0; i < count; i++) {
2047            XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
2048            matcher.startElement( element, attributes);
2049        }
2050
2051        if (fAugPSVI) {
2052            augs = getEmptyAugs(augs);
2053
2054            // PSVI: add validation context
2055
fCurrentPSVI.fValidationContext = fValidationRoot;
2056            // PSVI: add element declaration
2057
fCurrentPSVI.fDeclaration = fCurrentElemDecl;
2058            // PSVI: add element type
2059
fCurrentPSVI.fTypeDecl = fCurrentType;
2060            // PSVI: add notation attribute
2061
fCurrentPSVI.fNotation = fNotation;
2062        }
2063
2064        return augs;
2065
2066    } // handleStartElement(QName,XMLAttributes,boolean)
2067

2068    /**
2069     * Handle end element. If there is not text content, and there is a
2070     * {value constraint} on the corresponding element decl, then
2071     * set the fDefaultValue XMLString representing the default value.
2072     */

2073    Augmentations handleEndElement(QName element, Augmentations augs) {
2074
2075        if (DEBUG) {
2076            System.out.println("==>handleEndElement:" + element);
2077        }
2078        // if we are skipping, return
2079
if (fSkipValidationDepth >= 0) {
2080            // but if this is the top element that we are skipping,
2081
// restore the states.
2082
if (fSkipValidationDepth == fElementDepth && fSkipValidationDepth > 0) {
2083                // set the partial validation depth to the depth of parent
2084
fNFullValidationDepth = fSkipValidationDepth - 1;
2085                fSkipValidationDepth = -1;
2086                fElementDepth--;
2087                fSubElement = fSubElementStack[fElementDepth];
2088                fCurrentElemDecl = fElemDeclStack[fElementDepth];
2089                fNil = fNilStack[fElementDepth];
2090                fNotation = fNotationStack[fElementDepth];
2091                fCurrentType = fTypeStack[fElementDepth];
2092                fCurrentCM = fCMStack[fElementDepth];
2093                fStrictAssess = fStrictAssessStack[fElementDepth];
2094                fCurrCMState = fCMStateStack[fElementDepth];
2095                fSawText = fSawTextStack[fElementDepth];
2096                fSawCharacters = fStringContent[fElementDepth];
2097            }
2098            else {
2099                fElementDepth--;
2100            }
2101
2102            // PSVI: validation attempted:
2103
// use default values in psvi item for
2104
// validation attempted, validity, and error codes
2105

2106            // check extra schema constraints on root element
2107
if (fElementDepth == -1 && fFullChecking) {
2108                XSConstraints.fullSchemaChecking(
2109                    fGrammarBucket,
2110                    fSubGroupHandler,
2111                    fCMBuilder,
2112                    fXSIErrorReporter.fErrorReporter);
2113            }
2114
2115            if (fAugPSVI)
2116                augs = getEmptyAugs(augs);
2117            return augs;
2118        }
2119
2120        // now validate the content of the element
2121
processElementContent(element);
2122
2123        // Element Locally Valid (Element)
2124
// 6 The element information item must be valid with respect to each of the {identity-constraint definitions} as per Identity-constraint Satisfied (3.11.4).
2125

2126        // call matchers and de-activate context
2127
int oldCount = fMatcherStack.getMatcherCount();
2128        for (int i = oldCount - 1; i >= 0; i--) {
2129            XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
2130            if (fCurrentElemDecl == null)
2131                matcher.endElement(element, null, false, fValidatedInfo.actualValue, fValidatedInfo.actualValueType, fValidatedInfo.itemValueTypes);
2132
2133            else
2134                matcher.endElement(
2135                    element,
2136                    fCurrentType,
2137                    fCurrentElemDecl.getNillable(),
2138                    fDefaultValue == null
2139                        ? fValidatedInfo.actualValue
2140                        : fCurrentElemDecl.fDefault.actualValue,
2141                    fDefaultValue == null
2142                        ? fValidatedInfo.actualValueType
2143                        : fCurrentElemDecl.fDefault.actualValueType,
2144                    fDefaultValue == null
2145                        ? fValidatedInfo.itemValueTypes
2146                        : fCurrentElemDecl.fDefault.itemValueTypes);
2147        }
2148
2149        if (fMatcherStack.size() > 0) {
2150            fMatcherStack.popContext();
2151        }
2152
2153        int newCount = fMatcherStack.getMatcherCount();
2154        // handle everything *but* keyref's.
2155
for (int i = oldCount - 1; i >= newCount; i--) {
2156            XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
2157            if (matcher instanceof Selector.Matcher) {
2158                Selector.Matcher selMatcher = (Selector.Matcher) matcher;
2159                IdentityConstraint id;
2160                if ((id = selMatcher.getIdentityConstraint()) != null
2161                    && id.getCategory() != IdentityConstraint.IC_KEYREF) {
2162                    fValueStoreCache.transplant(id, selMatcher.getInitialDepth());
2163                }
2164            }
2165        }
2166
2167        // now handle keyref's/...
2168
for (int i = oldCount - 1; i >= newCount; i--) {
2169            XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
2170            if (matcher instanceof Selector.Matcher) {
2171                Selector.Matcher selMatcher = (Selector.Matcher) matcher;
2172                IdentityConstraint id;
2173                if ((id = selMatcher.getIdentityConstraint()) != null
2174                    && id.getCategory() == IdentityConstraint.IC_KEYREF) {
2175                    ValueStoreBase values =
2176                        fValueStoreCache.getValueStoreFor(id, selMatcher.getInitialDepth());
2177                    if (values != null) // nothing to do if nothing matched!
2178
values.endDocumentFragment();
2179                }
2180            }
2181        }
2182        fValueStoreCache.endElement();
2183
2184        SchemaGrammar[] grammars = null;
2185        // have we reached the end tag of the validation root?
2186
if (fElementDepth == 0) {
2187            // 7 If the element information item is the validation root, it must be valid per Validation Root Valid (ID/IDREF) (3.3.4).
2188
String JavaDoc invIdRef = fValidationState.checkIDRefID();
2189            fValidationState.resetIDTables();
2190            if (invIdRef != null) {
2191                reportSchemaError("cvc-id.1", new Object JavaDoc[] { invIdRef });
2192            }
2193            // check extra schema constraints
2194
if (fFullChecking) {
2195                XSConstraints.fullSchemaChecking(
2196                    fGrammarBucket,
2197                    fSubGroupHandler,
2198                    fCMBuilder,
2199                    fXSIErrorReporter.fErrorReporter);
2200            }
2201
2202            grammars = fGrammarBucket.getGrammars();
2203            // return the final set of grammars validator ended up with
2204
if (fGrammarPool != null) {
2205                fGrammarPool.cacheGrammars(XMLGrammarDescription.XML_SCHEMA, grammars);
2206            }
2207            augs = endElementPSVI(true, grammars, augs);
2208        } else {
2209            augs = endElementPSVI(false, grammars, augs);
2210
2211            // decrease element depth and restore states
2212
fElementDepth--;
2213
2214            // get the states for the parent element.
2215
fSubElement = fSubElementStack[fElementDepth];
2216            fCurrentElemDecl = fElemDeclStack[fElementDepth];
2217            fNil = fNilStack[fElementDepth];
2218            fNotation = fNotationStack[fElementDepth];
2219            fCurrentType = fTypeStack[fElementDepth];
2220            fCurrentCM = fCMStack[fElementDepth];
2221            fStrictAssess = fStrictAssessStack[fElementDepth];
2222            fCurrCMState = fCMStateStack[fElementDepth];
2223            fSawText = fSawTextStack[fElementDepth];
2224            fSawCharacters = fStringContent[fElementDepth];
2225
2226            // We should have a stack for whitespace value, and pop it up here.
2227
// But when fWhiteSpace != -1, and we see a sub-element, it must be
2228
// an error (at least for Schema 1.0). So for valid documents, the
2229
// only value we are going to push/pop in the stack is -1.
2230
// Here we just mimic the effect of popping -1. -SG
2231
fWhiteSpace = -1;
2232            // Same for append buffer. Simple types and elements with fixed
2233
// value constraint don't allow sub-elements. -SG
2234
fAppendBuffer = false;
2235            // same here.
2236
fUnionType = false;
2237        }
2238
2239        return augs;
2240    } // handleEndElement(QName,boolean)*/
2241

2242    final Augmentations endElementPSVI(
2243        boolean root,
2244        SchemaGrammar[] grammars,
2245        Augmentations augs) {
2246
2247        if (fAugPSVI) {
2248            augs = getEmptyAugs(augs);
2249
2250            // the 4 properties sent on startElement calls
2251
fCurrentPSVI.fDeclaration = this.fCurrentElemDecl;
2252            fCurrentPSVI.fTypeDecl = this.fCurrentType;
2253            fCurrentPSVI.fNotation = this.fNotation;
2254            fCurrentPSVI.fValidationContext = this.fValidationRoot;
2255            // PSVI: validation attempted
2256
// nothing below or at the same level has none or partial
2257
// (which means this level is strictly assessed, and all chidren
2258
// are full), so this one has full
2259
if (fElementDepth > fNFullValidationDepth) {
2260                fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_FULL;
2261            }
2262            // nothing below or at the same level has full or partial
2263
// (which means this level is not strictly assessed, and all chidren
2264
// are none), so this one has none
2265
else if (fElementDepth > fNNoneValidationDepth) {
2266                fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_NONE;
2267            }
2268            // otherwise partial, and anything above this level will be partial
2269
else {
2270                fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_PARTIAL;
2271                fNFullValidationDepth = fNNoneValidationDepth = fElementDepth - 1;
2272            }
2273
2274            if (fDefaultValue != null)
2275                fCurrentPSVI.fSpecified = true;
2276            fCurrentPSVI.fNil = fNil;
2277            fCurrentPSVI.fMemberType = fValidatedInfo.memberType;
2278            fCurrentPSVI.fNormalizedValue = fValidatedInfo.normalizedValue;
2279            fCurrentPSVI.fActualValue = fValidatedInfo.actualValue;
2280            fCurrentPSVI.fActualValueType = fValidatedInfo.actualValueType;
2281            fCurrentPSVI.fItemValueTypes = fValidatedInfo.itemValueTypes;
2282
2283            if (fStrictAssess) {
2284                // get all errors for the current element, its attribute,
2285
// and subelements (if they were strictly assessed).
2286
// any error would make this element invalid.
2287
// and we merge these errors to the parent element.
2288
String JavaDoc[] errors = fXSIErrorReporter.mergeContext();
2289
2290                // PSVI: error codes
2291
fCurrentPSVI.fErrorCodes = errors;
2292                // PSVI: validity
2293
fCurrentPSVI.fValidity =
2294                    (errors == null) ? ElementPSVI.VALIDITY_VALID : ElementPSVI.VALIDITY_INVALID;
2295            } else {
2296                // PSVI: validity
2297
fCurrentPSVI.fValidity = ElementPSVI.VALIDITY_NOTKNOWN;
2298                // Discard the current context: ignore any error happened within
2299
// the sub-elements/attributes of this element, because those
2300
// errors won't affect the validity of the parent elements.
2301
fXSIErrorReporter.popContext();
2302            }
2303
2304            if (root) {
2305                // store [schema information] in the PSVI
2306
fCurrentPSVI.fGrammars = grammars;
2307                fCurrentPSVI.fSchemaInformation = null;
2308            }
2309        }
2310
2311        return augs;
2312
2313    }
2314
2315    Augmentations getEmptyAugs(Augmentations augs) {
2316        if (augs == null) {
2317            augs = fAugmentations;
2318            augs.removeAllItems();
2319        }
2320        augs.putItem(Constants.ELEMENT_PSVI, fCurrentPSVI);
2321        fCurrentPSVI.reset();
2322
2323        return augs;
2324    }
2325
2326    void storeLocations(String JavaDoc sLocation, String JavaDoc nsLocation) {
2327        if (sLocation != null) {
2328            if (!XMLSchemaLoader.tokenizeSchemaLocationStr(sLocation, fLocationPairs)) {
2329                // error!
2330
fXSIErrorReporter.reportError(
2331                    XSMessageFormatter.SCHEMA_DOMAIN,
2332                    "SchemaLocation",
2333                    new Object JavaDoc[] { sLocation },
2334                    XMLErrorReporter.SEVERITY_WARNING);
2335            }
2336        }
2337        if (nsLocation != null) {
2338            XMLSchemaLoader.LocationArray la =
2339                ((XMLSchemaLoader.LocationArray) fLocationPairs.get(XMLSymbols.EMPTY_STRING));
2340            if (la == null) {
2341                la = new XMLSchemaLoader.LocationArray();
2342                fLocationPairs.put(XMLSymbols.EMPTY_STRING, la);
2343            }
2344            la.addLocation(nsLocation);
2345        }
2346
2347    } //storeLocations
2348

2349    //this is the function where logic of retrieving grammar is written , parser first tries to get the grammar from
2350
//the local pool, if not in local pool, it gives chance to application to be able to retrieve the grammar, then it
2351
//tries to parse the grammar using location hints from the give namespace.
2352
SchemaGrammar findSchemaGrammar(
2353        short contextType,
2354        String JavaDoc namespace,
2355        QName enclosingElement,
2356        QName triggeringComponet,
2357        XMLAttributes attributes) {
2358        SchemaGrammar grammar = null;
2359        //get the grammar from local pool...
2360
grammar = fGrammarBucket.getGrammar(namespace);
2361        if (grammar == null) {
2362            fXSDDescription.reset();
2363            fXSDDescription.fContextType = contextType;
2364            fXSDDescription.setNamespace(namespace);
2365            fXSDDescription.fEnclosedElementName = enclosingElement;
2366            fXSDDescription.fTriggeringComponent = triggeringComponet;
2367            fXSDDescription.fAttributes = attributes;
2368            if (fLocator != null) {
2369                fXSDDescription.setBaseSystemId(fLocator.getExpandedSystemId());
2370            }
2371
2372            String JavaDoc[] temp = null;
2373            Object JavaDoc locationArray =
2374                fLocationPairs.get(namespace == null ? XMLSymbols.EMPTY_STRING : namespace);
2375            if (locationArray != null)
2376                temp = ((XMLSchemaLoader.LocationArray) locationArray).getLocationArray();
2377            if (temp != null && temp.length != 0) {
2378                fXSDDescription.fLocationHints = new String JavaDoc[temp.length];
2379                System.arraycopy(temp, 0, fXSDDescription.fLocationHints, 0, temp.length);
2380            }
2381
2382            // give a chance to application to be able to retreive the grammar.
2383
if (fGrammarPool != null) {
2384                grammar = (SchemaGrammar) fGrammarPool.retrieveGrammar(fXSDDescription);
2385                if (grammar != null) {
2386                    // put this grammar into the bucket, along with grammars
2387
// imported by it (directly or indirectly)
2388
if (!fGrammarBucket.putGrammar(grammar, true)) {
2389                        // REVISIT: a conflict between new grammar(s) and grammars
2390
// in the bucket. What to do? A warning? An exception?
2391
fXSIErrorReporter.fErrorReporter.reportError(
2392                            XSMessageFormatter.SCHEMA_DOMAIN,
2393                            "GrammarConflict",
2394                            null,
2395                            XMLErrorReporter.SEVERITY_WARNING);
2396                        grammar = null;
2397                    }
2398                }
2399            }
2400            if (grammar == null && !fUseGrammarPoolOnly) {
2401                // try to parse the grammar using location hints from that namespace..
2402
try {
2403                    XMLInputSource xis =
2404                        XMLSchemaLoader.resolveDocument(
2405                            fXSDDescription,
2406                            fLocationPairs,
2407                            fEntityResolver);
2408                    grammar = fSchemaLoader.loadSchema(fXSDDescription, xis, fLocationPairs);
2409                } catch (IOException JavaDoc ex) {
2410                    final String JavaDoc [] locationHints = fXSDDescription.getLocationHints();
2411                    fXSIErrorReporter.fErrorReporter.reportError(
2412                        XSMessageFormatter.SCHEMA_DOMAIN,
2413                        "schema_reference.4",
2414                        new Object JavaDoc[] { locationHints != null ? locationHints[0] : XMLSymbols.EMPTY_STRING },
2415                        XMLErrorReporter.SEVERITY_WARNING);
2416                }
2417            }
2418        }
2419
2420        return grammar;
2421
2422    } //findSchemaGrammar
2423

2424    XSTypeDefinition getAndCheckXsiType(QName element, String JavaDoc xsiType, XMLAttributes attributes) {
2425        // This method also deals with clause 1.2.1.2 of the constraint
2426
// Validation Rule: Schema-Validity Assessment (Element)
2427

2428        // Element Locally Valid (Element)
2429
// 4 If there is an attribute information item among the element information item's [attributes] whose [namespace name] is identical to http://www.w3.org/2001/XMLSchema-instance and whose [local name] is type, then all of the following must be true:
2430
// 4.1 The normalized value of that attribute information item must be valid with respect to the built-in QName simple type, as defined by String Valid (3.14.4);
2431
QName typeName = null;
2432        try {
2433            typeName = (QName) fQNameDV.validate(xsiType, fValidationState, null);
2434        } catch (InvalidDatatypeValueException e) {
2435            reportSchemaError(e.getKey(), e.getArgs());
2436            reportSchemaError(
2437                "cvc-elt.4.1",
2438                new Object JavaDoc[] {
2439                    element.rawname,
2440                    SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_TYPE,
2441                    xsiType });
2442            return null;
2443        }
2444
2445        // 4.2 The local name and namespace name (as defined in QName Interpretation (3.15.3)), of the actual value of that attribute information item must resolve to a type definition, as defined in QName resolution (Instance) (3.15.4)
2446
XSTypeDefinition type = null;
2447        // if the namespace is schema namespace, first try built-in types
2448
if (typeName.uri == SchemaSymbols.URI_SCHEMAFORSCHEMA) {
2449            type = SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(typeName.localpart);
2450        }
2451        // if it's not schema built-in types, then try to get a grammar
2452
if (type == null) {
2453            //try to find schema grammar by different means....
2454
SchemaGrammar grammar =
2455                findSchemaGrammar(
2456                    XSDDescription.CONTEXT_XSITYPE,
2457                    typeName.uri,
2458                    element,
2459                    typeName,
2460                    attributes);
2461
2462            if (grammar != null)
2463                type = grammar.getGlobalTypeDecl(typeName.localpart);
2464        }
2465        // still couldn't find the type, report an error
2466
if (type == null) {
2467            reportSchemaError("cvc-elt.4.2", new Object JavaDoc[] { element.rawname, xsiType });
2468            return null;
2469        }
2470
2471        // if there is no current type, set this one as current.
2472
// and we don't need to do extra checking
2473
if (fCurrentType != null) {
2474            // 4.3 The local type definition must be validly derived from the {type definition} given the union of the {disallowed substitutions} and the {type definition}'s {prohibited substitutions}, as defined in Type Derivation OK (Complex) (3.4.6) (if it is a complex type definition), or given {disallowed substitutions} as defined in Type Derivation OK (Simple) (3.14.6) (if it is a simple type definition).
2475
short block = fCurrentElemDecl.fBlock;
2476            if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE)
2477                block |= ((XSComplexTypeDecl) fCurrentType).fBlock;
2478            if (!XSConstraints.checkTypeDerivationOk(type, fCurrentType, block))
2479                reportSchemaError(
2480                    "cvc-elt.4.3",
2481                    new Object JavaDoc[] { element.rawname, xsiType, fCurrentType.getName()});
2482        }
2483
2484        return type;
2485    } //getAndCheckXsiType
2486

2487    boolean getXsiNil(QName element, String JavaDoc xsiNil) {
2488        // Element Locally Valid (Element)
2489
// 3 The appropriate case among the following must be true:
2490
// 3.1 If {nillable} is false, then there must be no attribute information item among the element information item's [attributes] whose [namespace name] is identical to http://www.w3.org/2001/XMLSchema-instance and whose [local name] is nil.
2491
if (fCurrentElemDecl != null && !fCurrentElemDecl.getNillable()) {
2492            reportSchemaError(
2493                "cvc-elt.3.1",
2494                new Object JavaDoc[] {
2495                    element.rawname,
2496                    SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_NIL });
2497        }
2498        // 3.2 If {nillable} is true and there is such an attribute information item and its actual value is true , then all of the following must be true:
2499
// 3.2.2 There must be no fixed {value constraint}.
2500
else {
2501            String JavaDoc value = xsiNil.trim();
2502            if (value.equals(SchemaSymbols.ATTVAL_TRUE)
2503                || value.equals(SchemaSymbols.ATTVAL_TRUE_1)) {
2504                if (fCurrentElemDecl != null
2505                    && fCurrentElemDecl.getConstraintType() == XSConstants.VC_FIXED) {
2506                    reportSchemaError(
2507                        "cvc-elt.3.2.2",
2508                        new Object JavaDoc[] {
2509                            element.rawname,
2510                            SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_NIL });
2511                }
2512                return true;
2513            }
2514        }
2515        return false;
2516    }
2517
2518    void processAttributes(QName element, XMLAttributes attributes, XSAttributeGroupDecl attrGrp) {
2519
2520        if (DEBUG) {
2521            System.out.println("==>processAttributes: " + attributes.getLength());
2522        }
2523
2524        // whether we have seen a Wildcard ID.
2525
String JavaDoc wildcardIDName = null;
2526
2527        // for each present attribute
2528
int attCount = attributes.getLength();
2529
2530        Augmentations augs = null;
2531        AttributePSVImpl attrPSVI = null;
2532
2533        boolean isSimple =
2534            fCurrentType == null || fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE;
2535
2536        XSObjectList attrUses = null;
2537        int useCount = 0;
2538        XSWildcardDecl attrWildcard = null;
2539        if (!isSimple) {
2540            attrUses = attrGrp.getAttributeUses();
2541            useCount = attrUses.getLength();
2542            attrWildcard = attrGrp.fAttributeWC;
2543        }
2544
2545        // Element Locally Valid (Complex Type)
2546
// 3 For each attribute information item in the element information item's [attributes] excepting those whose [namespace name] is identical to http://www.w3.org/2001/XMLSchema-instance and whose [local name] is one of type, nil, schemaLocation or noNamespaceSchemaLocation, the appropriate case among the following must be true:
2547
// get the corresponding attribute decl
2548
for (int index = 0; index < attCount; index++) {
2549
2550            attributes.getName(index, fTempQName);
2551
2552            if (DEBUG) {
2553                System.out.println("==>process attribute: " + fTempQName);
2554            }
2555
2556            if (fAugPSVI || fIdConstraint) {
2557                augs = attributes.getAugmentations(index);
2558                attrPSVI = (AttributePSVImpl) augs.getItem(Constants.ATTRIBUTE_PSVI);
2559                if (attrPSVI != null) {
2560                    attrPSVI.reset();
2561                } else {
2562                    attrPSVI = new AttributePSVImpl();
2563                    augs.putItem(Constants.ATTRIBUTE_PSVI, attrPSVI);
2564                }
2565                // PSVI attribute: validation context
2566
attrPSVI.fValidationContext = fValidationRoot;
2567            }
2568
2569            // Element Locally Valid (Type)
2570
// 3.1.1 The element information item's [attributes] must be empty, excepting those
2571
// whose [namespace name] is identical to http://www.w3.org/2001/XMLSchema-instance and
2572
// whose [local name] is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
2573

2574            // for the 4 xsi attributes, get appropriate decl, and validate
2575
if (fTempQName.uri == SchemaSymbols.URI_XSI) {
2576                XSAttributeDecl attrDecl = null;
2577                if (fTempQName.localpart == SchemaSymbols.XSI_SCHEMALOCATION)
2578                    attrDecl =
2579                        SchemaGrammar.SG_XSI.getGlobalAttributeDecl(
2580                            SchemaSymbols.XSI_SCHEMALOCATION);
2581                else if (fTempQName.localpart == SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION)
2582                    attrDecl =
2583                        SchemaGrammar.SG_XSI.getGlobalAttributeDecl(
2584                            SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION);
2585                else if (fTempQName.localpart == SchemaSymbols.XSI_NIL)
2586                    attrDecl = SchemaGrammar.SG_XSI.getGlobalAttributeDecl(SchemaSymbols.XSI_NIL);
2587                else if (fTempQName.localpart == SchemaSymbols.XSI_TYPE)
2588                    attrDecl = SchemaGrammar.SG_XSI.getGlobalAttributeDecl(SchemaSymbols.XSI_TYPE);
2589                if (attrDecl != null) {
2590                    processOneAttribute(element, attributes, index, attrDecl, null, attrPSVI);
2591                    continue;
2592                }
2593            }
2594
2595            // for namespace attributes, no_validation/unknow_validity
2596
if (fTempQName.rawname == XMLSymbols.PREFIX_XMLNS
2597                || fTempQName.rawname.startsWith("xmlns:")) {
2598                continue;
2599            }
2600
2601            // simple type doesn't allow any other attributes
2602
if (isSimple) {
2603                reportSchemaError(
2604                    "cvc-type.3.1.1",
2605                    new Object JavaDoc[] { element.rawname, fTempQName.rawname });
2606                continue;
2607            }
2608
2609            // it's not xmlns, and not xsi, then we need to find a decl for it
2610
XSAttributeUseImpl currUse = null, oneUse;
2611            for (int i = 0; i < useCount; i++) {
2612                oneUse = (XSAttributeUseImpl) attrUses.item(i);
2613                if (oneUse.fAttrDecl.fName == fTempQName.localpart
2614                    && oneUse.fAttrDecl.fTargetNamespace == fTempQName.uri) {
2615                    currUse = oneUse;
2616                    break;
2617                }
2618            }
2619
2620            // 3.2 otherwise all of the following must be true:
2621
// 3.2.1 There must be an {attribute wildcard}.
2622
// 3.2.2 The attribute information item must be valid with respect to it as defined in Item Valid (Wildcard) (3.10.4).
2623

2624            // if failed, get it from wildcard
2625
if (currUse == null) {
2626                //if (attrWildcard == null)
2627
// reportSchemaError("cvc-complex-type.3.2.1", new Object[]{element.rawname, fTempQName.rawname});
2628
if (attrWildcard == null || !attrWildcard.allowNamespace(fTempQName.uri)) {
2629                    // so this attribute is not allowed
2630
reportSchemaError(
2631                        "cvc-complex-type.3.2.2",
2632                        new Object JavaDoc[] { element.rawname, fTempQName.rawname });
2633                    continue;
2634                }
2635            }
2636
2637            XSAttributeDecl currDecl = null;
2638            if (currUse != null) {
2639                currDecl = currUse.fAttrDecl;
2640            } else {
2641                // which means it matches a wildcard
2642
// skip it if processContents is skip
2643
if (attrWildcard.fProcessContents == XSWildcardDecl.PC_SKIP)
2644                    continue;
2645
2646                //try to find grammar by different means...
2647
SchemaGrammar grammar =
2648                    findSchemaGrammar(
2649                        XSDDescription.CONTEXT_ATTRIBUTE,
2650                        fTempQName.uri,
2651                        element,
2652                        fTempQName,
2653                        attributes);
2654
2655                if (grammar != null) {
2656                    currDecl = grammar.getGlobalAttributeDecl(fTempQName.localpart);
2657                }
2658
2659                // if can't find
2660
if (currDecl == null) {
2661                    // if strict, report error
2662
if (attrWildcard.fProcessContents == XSWildcardDecl.PC_STRICT) {
2663                        reportSchemaError(
2664                            "cvc-complex-type.3.2.2",
2665                            new Object JavaDoc[] { element.rawname, fTempQName.rawname });
2666                    }
2667
2668                    // then continue to the next attribute
2669
continue;
2670                } else {
2671                    // 5 Let [Definition:] the wild IDs be the set of all attribute information item to which clause 3.2 applied and whose validation resulted in a context-determined declaration of mustFind or no context-determined declaration at all, and whose [local name] and [namespace name] resolve (as defined by QName resolution (Instance) (3.15.4)) to an attribute declaration whose {type definition} is or is derived from ID. Then all of the following must be true:
2672
// 5.1 There must be no more than one item in wild IDs.
2673
if (currDecl.fType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE
2674                        && ((XSSimpleType) currDecl.fType).isIDType()) {
2675                        if (wildcardIDName != null) {
2676                            reportSchemaError(
2677                                "cvc-complex-type.5.1",
2678                                new Object JavaDoc[] { element.rawname, currDecl.fName, wildcardIDName });
2679                        } else
2680                            wildcardIDName = currDecl.fName;
2681                    }
2682                }
2683            }
2684
2685            processOneAttribute(element, attributes, index, currDecl, currUse, attrPSVI);
2686        } // end of for (all attributes)
2687

2688        // 5.2 If wild IDs is non-empty, there must not be any attribute uses among the {attribute uses} whose {attribute declaration}'s {type definition} is or is derived from ID.
2689
if (!isSimple && attrGrp.fIDAttrName != null && wildcardIDName != null) {
2690            reportSchemaError(
2691                "cvc-complex-type.5.2",
2692                new Object JavaDoc[] { element.rawname, wildcardIDName, attrGrp.fIDAttrName });
2693        }
2694
2695    } //processAttributes
2696

2697    void processOneAttribute(
2698        QName element,
2699        XMLAttributes attributes,
2700        int index,
2701        XSAttributeDecl currDecl,
2702        XSAttributeUseImpl currUse,
2703        AttributePSVImpl attrPSVI) {
2704
2705        String JavaDoc attrValue = attributes.getValue(index);
2706        fXSIErrorReporter.pushContext();
2707
2708        // Attribute Locally Valid
2709
// For an attribute information item to be locally valid with respect to an attribute declaration all of the following must be true:
2710
// 1 The declaration must not be absent (see Missing Sub-components (5.3) for how this can fail to be the case).
2711
// 2 Its {type definition} must not be absent.
2712
// 3 The item's normalized value must be locally valid with respect to that {type definition} as per String Valid (3.14.4).
2713
// get simple type
2714
XSSimpleType attDV = currDecl.fType;
2715
2716        Object JavaDoc actualValue = null;
2717        try {
2718            actualValue = attDV.validate(attrValue, fValidationState, fValidatedInfo);
2719            // store the normalized value
2720
if (fNormalizeData)
2721                attributes.setValue(index, fValidatedInfo.normalizedValue);
2722            if (attributes instanceof XMLAttributesImpl) {
2723                XMLAttributesImpl attrs = (XMLAttributesImpl) attributes;
2724                boolean schemaId =
2725                    fValidatedInfo.memberType != null
2726                        ? fValidatedInfo.memberType.isIDType()
2727                        : attDV.isIDType();
2728                attrs.setSchemaId(index, schemaId);
2729            }
2730
2731            // PSVI: element notation
2732
if (attDV.getVariety() == XSSimpleType.VARIETY_ATOMIC
2733                && attDV.getPrimitiveKind() == XSSimpleType.PRIMITIVE_NOTATION) {
2734                QName qName = (QName) actualValue;
2735                SchemaGrammar grammar = fGrammarBucket.getGrammar(qName.uri);
2736
2737                //REVISIT: is it possible for the notation to be in different namespace than the attribute
2738
//with which it is associated, CHECK !! <fof n1:att1 = "n2:notation1" ..>
2739
// should we give chance to the application to be able to retrieve a grammar - nb
2740
//REVISIT: what would be the triggering component here.. if it is attribute value that
2741
// triggered the loading of grammar ?? -nb
2742

2743                if (grammar != null) {
2744                    fNotation = grammar.getGlobalNotationDecl(qName.localpart);
2745                }
2746            }
2747        } catch (InvalidDatatypeValueException idve) {
2748            reportSchemaError(idve.getKey(), idve.getArgs());
2749            reportSchemaError(
2750                "cvc-attribute.3",
2751                new Object JavaDoc[] { element.rawname, fTempQName.rawname, attrValue, attDV.getName()});
2752        }
2753
2754        // get the value constraint from use or decl
2755
// 4 The item's actual value must match the value of the {value constraint}, if it is present and fixed. // now check the value against the simpleType
2756
if (actualValue != null && currDecl.getConstraintType() == XSConstants.VC_FIXED) {
2757            if (!isComparable(fValidatedInfo, currDecl.fDefault) || !actualValue.equals(currDecl.fDefault.actualValue)) {
2758                reportSchemaError(
2759                    "cvc-attribute.4",
2760                    new Object JavaDoc[] {
2761                        element.rawname,
2762                        fTempQName.rawname,
2763                        attrValue,
2764                        currDecl.fDefault.stringValue()});
2765            }
2766        }
2767
2768        // 3.1 If there is among the {attribute uses} an attribute use with an {attribute declaration} whose {name} matches the attribute information item's [local name] and whose {target namespace} is identical to the attribute information item's [namespace name] (where an absent {target namespace} is taken to be identical to a [namespace name] with no value), then the attribute information must be valid with respect to that attribute use as per Attribute Locally Valid (Use) (3.5.4). In this case the {attribute declaration} of that attribute use is the context-determined declaration for the attribute information item with respect to Schema-Validity Assessment (Attribute) (3.2.4) and Assessment Outcome (Attribute) (3.2.5).
2769
if (actualValue != null
2770            && currUse != null
2771            && currUse.fConstraintType == XSConstants.VC_FIXED) {
2772            if (!isComparable(fValidatedInfo, currUse.fDefault) || !actualValue.equals(currUse.fDefault.actualValue)) {
2773                reportSchemaError(
2774                    "cvc-complex-type.3.1",
2775                    new Object JavaDoc[] {
2776                        element.rawname,
2777                        fTempQName.rawname,
2778                        attrValue,
2779                        currUse.fDefault.stringValue()});
2780            }
2781        }
2782        if (fIdConstraint) {
2783            attrPSVI.fActualValue = actualValue;
2784        }
2785
2786        if (fAugPSVI) {
2787            // PSVI: attribute declaration
2788
attrPSVI.fDeclaration = currDecl;
2789            // PSVI: attribute type
2790
attrPSVI.fTypeDecl = attDV;
2791
2792            // PSVI: attribute memberType
2793
attrPSVI.fMemberType = fValidatedInfo.memberType;
2794            // PSVI: attribute normalized value
2795
// NOTE: we always store the normalized value, even if it's invlid,
2796
// because it might still be useful to the user. But when the it's
2797
// not valid, the normalized value is not trustable.
2798
attrPSVI.fNormalizedValue = fValidatedInfo.normalizedValue;
2799            attrPSVI.fActualValue = fValidatedInfo.actualValue;
2800            attrPSVI.fActualValueType = fValidatedInfo.actualValueType;
2801            attrPSVI.fItemValueTypes = fValidatedInfo.itemValueTypes;
2802
2803
2804
2805            // PSVI: validation attempted:
2806
attrPSVI.fValidationAttempted = AttributePSVI.VALIDATION_FULL;
2807
2808            String JavaDoc[] errors = fXSIErrorReporter.mergeContext();
2809            // PSVI: error codes
2810
attrPSVI.fErrorCodes = errors;
2811            // PSVI: validity
2812
attrPSVI.fValidity =
2813                (errors == null) ? AttributePSVI.VALIDITY_VALID : AttributePSVI.VALIDITY_INVALID;
2814        }
2815    }
2816
2817    void addDefaultAttributes(
2818        QName element,
2819        XMLAttributes attributes,
2820        XSAttributeGroupDecl attrGrp) {
2821        // Check after all specified attrs are scanned
2822
// (1) report error for REQUIRED attrs that are missing (V_TAGc)
2823
// REVISIT: should we check prohibited attributes?
2824
// (2) report error for PROHIBITED attrs that are present (V_TAGc)
2825
// (3) add default attrs (FIXED and NOT_FIXED)
2826
//
2827
if (DEBUG) {
2828            System.out.println("==>addDefaultAttributes: " + element);
2829        }
2830        XSObjectList attrUses = attrGrp.getAttributeUses();
2831        int useCount = attrUses.getLength();
2832        XSAttributeUseImpl currUse;
2833        XSAttributeDecl currDecl;
2834        short constType;
2835        ValidatedInfo defaultValue;
2836        boolean isSpecified;
2837        QName attName;
2838        // for each attribute use
2839
for (int i = 0; i < useCount; i++) {
2840
2841            currUse = (XSAttributeUseImpl) attrUses.item(i);
2842            currDecl = currUse.fAttrDecl;
2843            // get value constraint
2844
constType = currUse.fConstraintType;
2845            defaultValue = currUse.fDefault;
2846            if (constType == XSConstants.VC_NONE) {
2847                constType = currDecl.getConstraintType();
2848                defaultValue = currDecl.fDefault;
2849            }
2850            // whether this attribute is specified
2851
isSpecified = attributes.getValue(currDecl.fTargetNamespace, currDecl.fName) != null;
2852
2853            // Element Locally Valid (Complex Type)
2854
// 4 The {attribute declaration} of each attribute use in the {attribute uses} whose
2855
// {required} is true matches one of the attribute information items in the element
2856
// information item's [attributes] as per clause 3.1 above.
2857
if (currUse.fUse == SchemaSymbols.USE_REQUIRED) {
2858                if (!isSpecified)
2859                    reportSchemaError(
2860                        "cvc-complex-type.4",
2861                        new Object JavaDoc[] { element.rawname, currDecl.fName });
2862            }
2863            // if the attribute is not specified, then apply the value constraint
2864
if (!isSpecified && constType != XSConstants.VC_NONE) {
2865                attName =
2866                    new QName(null, currDecl.fName, currDecl.fName, currDecl.fTargetNamespace);
2867                String JavaDoc normalized = (defaultValue != null) ? defaultValue.stringValue() : "";
2868                int attrIndex = attributes.addAttribute(attName, "CDATA", normalized);
2869                if (attributes instanceof XMLAttributesImpl) {
2870                    XMLAttributesImpl attrs = (XMLAttributesImpl) attributes;
2871                    boolean schemaId =
2872                        defaultValue != null
2873                            && defaultValue.memberType != null
2874                                ? defaultValue.memberType.isIDType()
2875                                : currDecl.fType.isIDType();
2876                    attrs.setSchemaId(attrIndex, schemaId);
2877                }
2878
2879                if (fAugPSVI) {
2880
2881                    // PSVI: attribute is "schema" specified
2882
Augmentations augs = attributes.getAugmentations(attrIndex);
2883                    AttributePSVImpl attrPSVI = new AttributePSVImpl();
2884                    augs.putItem(Constants.ATTRIBUTE_PSVI, attrPSVI);
2885
2886                    attrPSVI.fDeclaration = currDecl;
2887                    attrPSVI.fTypeDecl = currDecl.fType;
2888                    attrPSVI.fMemberType = defaultValue.memberType;
2889                    attrPSVI.fNormalizedValue = normalized;
2890                    attrPSVI.fActualValue = defaultValue.actualValue;
2891                    attrPSVI.fActualValueType = defaultValue.actualValueType;
2892                    attrPSVI.fItemValueTypes = defaultValue.itemValueTypes;
2893                    attrPSVI.fValidationContext = fValidationRoot;
2894                    attrPSVI.fValidity = AttributePSVI.VALIDITY_VALID;
2895                    attrPSVI.fValidationAttempted = AttributePSVI.VALIDATION_FULL;
2896                    attrPSVI.fSpecified = true;
2897                }
2898            }
2899
2900        } // for
2901
} // addDefaultAttributes
2902

2903    /**
2904     * If there is not text content, and there is a
2905     * {value constraint} on the corresponding element decl, then return
2906     * an XMLString representing the default value.
2907     */

2908    void processElementContent(QName element) {
2909        // 1 If the item is ?valid? with respect to an element declaration as per Element Locally Valid (Element) (?3.3.4) and the {value constraint} is present, but clause 3.2 of Element Locally Valid (Element) (?3.3.4) above is not satisfied and the item has no element or character information item [children], then schema. Furthermore, the post-schema-validation infoset has the canonical lexical representation of the {value constraint} value as the item's [schema normalized value] property.
2910
if (fCurrentElemDecl != null
2911            && fCurrentElemDecl.fDefault != null
2912            && !fSawText
2913            && !fSubElement
2914            && !fNil) {
2915
2916            String JavaDoc strv = fCurrentElemDecl.fDefault.stringValue();
2917            int bufLen = strv.length();
2918            if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < bufLen) {
2919                fNormalizedStr.ch = new char[bufLen];
2920            }
2921            strv.getChars(0, bufLen, fNormalizedStr.ch, 0);
2922            fNormalizedStr.offset = 0;
2923            fNormalizedStr.length = bufLen;
2924            fDefaultValue = fNormalizedStr;
2925        }
2926        // fixed values are handled later, after xsi:type determined.
2927

2928        fValidatedInfo.normalizedValue = null;
2929
2930        // Element Locally Valid (Element)
2931
// 3.2.1 The element information item must have no character or element information item [children].
2932
if (fNil) {
2933            if (fSubElement || fSawText) {
2934                reportSchemaError(
2935                    "cvc-elt.3.2.1",
2936                    new Object JavaDoc[] {
2937                        element.rawname,
2938                        SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_NIL });
2939            }
2940        }
2941
2942        this.fValidatedInfo.reset();
2943
2944        // 5 The appropriate case among the following must be true:
2945
// 5.1 If the declaration has a {value constraint}, the item has neither element nor character [children] and clause 3.2 has not applied, then all of the following must be true:
2946
if (fCurrentElemDecl != null
2947            && fCurrentElemDecl.getConstraintType() != XSConstants.VC_NONE
2948            && !fSubElement
2949            && !fSawText
2950            && !fNil) {
2951            // 5.1.1 If the actual type definition is a local type definition then the canonical lexical representation of the {value constraint} value must be a valid default for the actual type definition as defined in Element Default Valid (Immediate) (3.3.6).
2952
if (fCurrentType != fCurrentElemDecl.fType) {
2953                //REVISIT:we should pass ValidatedInfo here.
2954
if (XSConstraints
2955                    .ElementDefaultValidImmediate(
2956                        fCurrentType,
2957                        fCurrentElemDecl.fDefault.stringValue(),
2958                        fState4XsiType,
2959                        null)
2960                    == null)
2961                    reportSchemaError(
2962                        "cvc-elt.5.1.1",
2963                        new Object JavaDoc[] {
2964                            element.rawname,
2965                            fCurrentType.getName(),
2966                            fCurrentElemDecl.fDefault.stringValue()});
2967            }
2968            // 5.1.2 The element information item with the canonical lexical representation of the {value constraint} value used as its normalized value must be valid with respect to the actual type definition as defined by Element Locally Valid (Type) (3.3.4).
2969
// REVISIT: don't use toString, but validateActualValue instead
2970
// use the fState4ApplyDefault
2971
elementLocallyValidType(element, fCurrentElemDecl.fDefault.stringValue());
2972        } else {
2973            // The following method call also deal with clause 1.2.2 of the constraint
2974
// Validation Rule: Schema-Validity Assessment (Element)
2975

2976            // 5.2 If the declaration has no {value constraint} or the item has either element or character [children] or clause 3.2 has applied, then all of the following must be true:
2977
// 5.2.1 The element information item must be valid with respect to the actual type definition as defined by Element Locally Valid (Type) (3.3.4).
2978
Object JavaDoc actualValue = elementLocallyValidType(element, fBuffer);
2979            // 5.2.2 If there is a fixed {value constraint} and clause 3.2 has not applied, all of the following must be true:
2980
if (fCurrentElemDecl != null
2981                && fCurrentElemDecl.getConstraintType() == XSConstants.VC_FIXED
2982                && !fNil) {
2983                String JavaDoc content = fBuffer.toString();
2984                // 5.2.2.1 The element information item must have no element information item [children].
2985
if (fSubElement)
2986                    reportSchemaError("cvc-elt.5.2.2.1", new Object JavaDoc[] { element.rawname });
2987                // 5.2.2.2 The appropriate case among the following must be true:
2988
if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
2989                    XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
2990                    // 5.2.2.2.1 If the {content type} of the actual type definition is mixed, then the initial value of the item must match the canonical lexical representation of the {value constraint} value.
2991
if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
2992                        // REVISIT: how to get the initial value, does whiteSpace count?
2993
if (!fCurrentElemDecl.fDefault.normalizedValue.equals(content))
2994                            reportSchemaError(
2995                                "cvc-elt.5.2.2.2.1",
2996                                new Object JavaDoc[] {
2997                                    element.rawname,
2998                                    content,
2999                                    fCurrentElemDecl.fDefault.normalizedValue });
3000                    }
3001                    // 5.2.2.2.2 If the {content type} of the actual type definition is a simple type definition, then the actual value of the item must match the canonical lexical representation of the {value constraint} value.
3002
else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
3003                        if (actualValue != null && (!isComparable(fValidatedInfo, fCurrentElemDecl.fDefault)
3004                                || !actualValue.equals(fCurrentElemDecl.fDefault.actualValue))) {
3005                            reportSchemaError(
3006                                "cvc-elt.5.2.2.2.2",
3007                                new Object JavaDoc[] {
3008                                    element.rawname,
3009                                    content,
3010                                    fCurrentElemDecl.fDefault.stringValue()});
3011                        }
3012                    }
3013                } else if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
3014                    if (actualValue != null && (!isComparable(fValidatedInfo, fCurrentElemDecl.fDefault)
3015                            || !actualValue.equals(fCurrentElemDecl.fDefault.actualValue))) {
3016                        // REVISIT: the spec didn't mention this case: fixed
3017
// value with simple type
3018
reportSchemaError(
3019                            "cvc-elt.5.2.2.2.2",
3020                            new Object JavaDoc[] {
3021                                element.rawname,
3022                                content,
3023                                fCurrentElemDecl.fDefault.stringValue()});
3024                    }
3025                }
3026            }
3027        }
3028
3029        if (fDefaultValue == null && fNormalizeData && fDocumentHandler != null && fUnionType) {
3030            // for union types we need to send data because we delayed sending
3031
// this data when we received it in the characters() call.
3032
String JavaDoc content = fValidatedInfo.normalizedValue;
3033            if (content == null)
3034                content = fBuffer.toString();
3035
3036            int bufLen = content.length();
3037            if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < bufLen) {
3038                fNormalizedStr.ch = new char[bufLen];
3039            }
3040            content.getChars(0, bufLen, fNormalizedStr.ch, 0);
3041            fNormalizedStr.offset = 0;
3042            fNormalizedStr.length = bufLen;
3043            fDocumentHandler.characters(fNormalizedStr, null);
3044        }
3045    } // processElementContent
3046

3047    Object JavaDoc elementLocallyValidType(QName element, Object JavaDoc textContent) {
3048        if (fCurrentType == null)
3049            return null;
3050
3051        Object JavaDoc retValue = null;
3052        // Element Locally Valid (Type)
3053
// 3 The appropriate case among the following must be true:
3054
// 3.1 If the type definition is a simple type definition, then all of the following must be true:
3055
if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
3056            // 3.1.2 The element information item must have no element information item [children].
3057
if (fSubElement)
3058                reportSchemaError("cvc-type.3.1.2", new Object JavaDoc[] { element.rawname });
3059            // 3.1.3 If clause 3.2 of Element Locally Valid (Element) (3.3.4) did not apply, then the normalized value must be valid with respect to the type definition as defined by String Valid (3.14.4).
3060
if (!fNil) {
3061                XSSimpleType dv = (XSSimpleType) fCurrentType;
3062                try {
3063                    if (!fNormalizeData || fUnionType) {
3064                        fValidationState.setNormalizationRequired(true);
3065                    }
3066                    retValue = dv.validate(textContent, fValidationState, fValidatedInfo);
3067                } catch (InvalidDatatypeValueException e) {
3068                    reportSchemaError(e.getKey(), e.getArgs());
3069                    reportSchemaError(
3070                        "cvc-type.3.1.3",
3071                        new Object JavaDoc[] { element.rawname, textContent });
3072                }
3073            }
3074        } else {
3075            // 3.2 If the type definition is a complex type definition, then the element information item must be valid with respect to the type definition as per Element Locally Valid (Complex Type) (3.4.4);
3076
retValue = elementLocallyValidComplexType(element, textContent);
3077        }
3078
3079        return retValue;
3080    } // elementLocallyValidType
3081

3082    Object JavaDoc elementLocallyValidComplexType(QName element, Object JavaDoc textContent) {
3083        Object JavaDoc actualValue = null;
3084        XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
3085
3086        // Element Locally Valid (Complex Type)
3087
// For an element information item to be locally valid with respect to a complex type definition all of the following must be true:
3088
// 1 {abstract} is false.
3089
// 2 If clause 3.2 of Element Locally Valid (Element) (3.3.4) did not apply, then the appropriate case among the following must be true:
3090
if (!fNil) {
3091            // 2.1 If the {content type} is empty, then the element information item has no character or element information item [children].
3092
if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_EMPTY
3093                && (fSubElement || fSawText)) {
3094                reportSchemaError("cvc-complex-type.2.1", new Object JavaDoc[] { element.rawname });
3095            }
3096            // 2.2 If the {content type} is a simple type definition, then the element information item has no element information item [children], and the normalized value of the element information item is valid with respect to that simple type definition as defined by String Valid (3.14.4).
3097
else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
3098                if (fSubElement)
3099                    reportSchemaError("cvc-complex-type.2.2", new Object JavaDoc[] { element.rawname });
3100                XSSimpleType dv = ctype.fXSSimpleType;
3101                try {
3102                    if (!fNormalizeData || fUnionType) {
3103                        fValidationState.setNormalizationRequired(true);
3104                    }
3105                    actualValue = dv.validate(textContent, fValidationState, fValidatedInfo);
3106                } catch (InvalidDatatypeValueException e) {
3107                    reportSchemaError(e.getKey(), e.getArgs());
3108                    reportSchemaError("cvc-complex-type.2.2", new Object JavaDoc[] { element.rawname });
3109                }
3110                // REVISIT: eventually, this method should return the same actualValue as elementLocallyValidType...
3111
// obviously it'll return null when the content is complex.
3112
}
3113            // 2.3 If the {content type} is element-only, then the element information item has no character information item [children] other than those whose [character code] is defined as a white space in [XML 1.0 (Second Edition)].
3114
else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
3115                if (fSawCharacters) {
3116                    reportSchemaError("cvc-complex-type.2.3", new Object JavaDoc[] { element.rawname });
3117                }
3118            }
3119            // 2.4 If the {content type} is element-only or mixed, then the sequence of the element information item's element information item [children], if any, taken in order, is valid with respect to the {content type}'s particle, as defined in Element Sequence Locally Valid (Particle) (3.9.4).
3120
if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT
3121                || ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
3122                // if the current state is a valid state, check whether
3123
// it's one of the final states.
3124
if (DEBUG) {
3125                    System.out.println(fCurrCMState);
3126                }
3127                if (fCurrCMState[0] >= 0 && !fCurrentCM.endContentModel(fCurrCMState)) {
3128                    String JavaDoc expected = expectedStr(fCurrentCM.whatCanGoHere(fCurrCMState));
3129                    reportSchemaError(
3130                        "cvc-complex-type.2.4.b",
3131                        new Object JavaDoc[] { element.rawname, expected });
3132                }
3133            }
3134        }
3135        return actualValue;
3136    } // elementLocallyValidComplexType
3137

3138    void reportSchemaError(String JavaDoc key, Object JavaDoc[] arguments) {
3139        if (fDoValidation)
3140            fXSIErrorReporter.reportError(
3141                XSMessageFormatter.SCHEMA_DOMAIN,
3142                key,
3143                arguments,
3144                XMLErrorReporter.SEVERITY_ERROR);
3145    }
3146    
3147    /** Returns true if the two ValidatedInfo objects can be compared in the same value space. **/
3148    private boolean isComparable(ValidatedInfo info1, ValidatedInfo info2) {
3149        final short primitiveType1 = convertToPrimitiveKind(info1.actualValueType);
3150        final short primitiveType2 = convertToPrimitiveKind(info2.actualValueType);
3151        if (primitiveType1 != primitiveType2) {
3152            return (primitiveType1 == XSConstants.ANYSIMPLETYPE_DT && primitiveType2 == XSConstants.STRING_DT ||
3153                    primitiveType1 == XSConstants.STRING_DT && primitiveType2 == XSConstants.ANYSIMPLETYPE_DT);
3154        }
3155        else if (primitiveType1 == XSConstants.LIST_DT || primitiveType1 == XSConstants.LISTOFUNION_DT) {
3156            final ShortList typeList1 = info1.itemValueTypes;
3157            final ShortList typeList2 = info2.itemValueTypes;
3158            final int typeList1Length = typeList1 != null ? typeList1.getLength() : 0;
3159            final int typeList2Length = typeList2 != null ? typeList2.getLength() : 0;
3160            if (typeList1Length != typeList2Length) {
3161                return false;
3162            }
3163            for (int i = 0; i < typeList1Length; ++i) {
3164                final short primitiveItem1 = convertToPrimitiveKind(typeList1.item(i));
3165                final short primitiveItem2 = convertToPrimitiveKind(typeList2.item(i));
3166                if (primitiveItem1 != primitiveItem2) {
3167                    if (primitiveItem1 == XSConstants.ANYSIMPLETYPE_DT && primitiveItem2 == XSConstants.STRING_DT ||
3168                        primitiveItem1 == XSConstants.STRING_DT && primitiveItem2 == XSConstants.ANYSIMPLETYPE_DT) {
3169                        continue;
3170                    }
3171                    return false;
3172                }
3173            }
3174        }
3175        return true;
3176    }
3177    
3178    private short convertToPrimitiveKind(short valueType) {
3179        /** Primitive datatypes. */
3180        if (valueType <= XSConstants.NOTATION_DT) {
3181            return valueType;
3182        }
3183        /** Types derived from string. */
3184        if (valueType <= XSConstants.ENTITY_DT) {
3185            return XSConstants.STRING_DT;
3186        }
3187        /** Types derived from decimal. */
3188        if (valueType <= XSConstants.POSITIVEINTEGER_DT) {
3189            return XSConstants.DECIMAL_DT;
3190        }
3191        /** Other types. */
3192        return valueType;
3193    }
3194    
3195    private String JavaDoc expectedStr(Vector JavaDoc expected) {
3196        StringBuffer JavaDoc ret = new StringBuffer JavaDoc("{");
3197        int size = expected.size();
3198        for (int i = 0; i < size; i++) {
3199            if (i > 0)
3200                ret.append(", ");
3201            ret.append(expected.elementAt(i).toString());
3202        }
3203        ret.append('}');
3204        return ret.toString();
3205    }
3206
3207    /**********************************/
3208
3209    // xpath matcher information
3210

3211    /**
3212     * Stack of XPath matchers for identity constraints.
3213     *
3214     * @author Andy Clark, IBM
3215     */

3216    protected static class XPathMatcherStack {
3217
3218        //
3219
// Data
3220
//
3221

3222        /** Active matchers. */
3223        protected XPathMatcher[] fMatchers = new XPathMatcher[4];
3224
3225        /** Count of active matchers. */
3226        protected int fMatchersCount;
3227
3228        /** Offset stack for contexts. */
3229        protected IntStack fContextStack = new IntStack();
3230
3231        //
3232
// Constructors
3233
//
3234

3235        public XPathMatcherStack() {
3236        } // <init>()
3237

3238        //
3239
// Public methods
3240
//
3241

3242        /** Resets the XPath matcher stack. */
3243        public void clear() {
3244            for (int i = 0; i < fMatchersCount; i++) {
3245                fMatchers[i] = null;
3246            }
3247            fMatchersCount = 0;
3248            fContextStack.clear();
3249        } // clear()
3250

3251        /** Returns the size of the stack. */
3252        public int size() {
3253            return fContextStack.size();
3254        } // size():int
3255

3256        /** Returns the count of XPath matchers. */
3257        public int getMatcherCount() {
3258            return fMatchersCount;
3259        } // getMatcherCount():int
3260

3261        /** Adds a matcher. */
3262        public void addMatcher(XPathMatcher matcher) {
3263            ensureMatcherCapacity();
3264            fMatchers[fMatchersCount++] = matcher;
3265        } // addMatcher(XPathMatcher)
3266

3267        /** Returns the XPath matcher at the specified index. */
3268        public XPathMatcher getMatcherAt(int index) {
3269            return fMatchers[index];
3270        } // getMatcherAt(index):XPathMatcher
3271

3272        /** Pushes a new context onto the stack. */
3273        public void pushContext() {
3274            fContextStack.push(fMatchersCount);
3275        } // pushContext()
3276

3277        /** Pops a context off of the stack. */
3278        public void popContext() {
3279            fMatchersCount = fContextStack.pop();
3280        } // popContext()
3281

3282        //
3283
// Private methods
3284
//
3285

3286        /** Ensures the size of the matchers array. */
3287        private void ensureMatcherCapacity() {
3288            if (fMatchersCount == fMatchers.length) {
3289                XPathMatcher[] array = new XPathMatcher[fMatchers.length * 2];
3290                System.arraycopy(fMatchers, 0, array, 0, fMatchers.length);
3291                fMatchers = array;
3292            }
3293        } // ensureMatcherCapacity()
3294

3295    } // class XPathMatcherStack
3296

3297    // value store implementations
3298

3299    /**
3300     * Value store implementation base class. There are specific subclasses
3301     * for handling unique, key, and keyref.
3302     *
3303     * @author Andy Clark, IBM
3304     */

3305    protected abstract class ValueStoreBase implements ValueStore {
3306
3307        //
3308
// Data
3309
//
3310

3311        /** Identity constraint. */
3312        protected IdentityConstraint fIdentityConstraint;
3313        protected int fFieldCount = 0;
3314        protected Field[] fFields = null;
3315        /** current data */
3316        protected Object JavaDoc[] fLocalValues = null;
3317        protected short[] fLocalValueTypes = null;
3318        protected ShortList[] fLocalItemValueTypes = null;
3319
3320        /** Current data value count. */
3321        protected int fValuesCount;
3322
3323        /** global data */
3324        public final Vector JavaDoc fValues = new Vector JavaDoc();
3325        public ShortVector fValueTypes = null;
3326        public Vector JavaDoc fItemValueTypes = null;
3327        
3328        private boolean fUseValueTypeVector = false;
3329        private int fValueTypesLength = 0;
3330        private short fValueType = 0;
3331        
3332        private boolean fUseItemValueTypeVector = false;
3333        private int fItemValueTypesLength = 0;
3334        private ShortList fItemValueType = null;
3335
3336        /** buffer for error messages */
3337        final StringBuffer JavaDoc fTempBuffer = new StringBuffer JavaDoc();
3338
3339        //
3340
// Constructors
3341
//
3342

3343        /** Constructs a value store for the specified identity constraint. */
3344        protected ValueStoreBase(IdentityConstraint identityConstraint) {
3345            fIdentityConstraint = identityConstraint;
3346            fFieldCount = fIdentityConstraint.getFieldCount();
3347            fFields = new Field[fFieldCount];
3348            fLocalValues = new Object JavaDoc[fFieldCount];
3349            fLocalValueTypes = new short[fFieldCount];
3350            fLocalItemValueTypes = new ShortList[fFieldCount];
3351            for (int i = 0; i < fFieldCount; i++) {
3352                fFields[i] = fIdentityConstraint.getFieldAt(i);
3353            }
3354        } // <init>(IdentityConstraint)
3355

3356        //
3357
// Public methods
3358
//
3359

3360        // destroys this ValueStore; useful when, for instance, a
3361
// locally-scoped ID constraint is involved.
3362
public void clear() {
3363            fValuesCount = 0;
3364            fUseValueTypeVector = false;
3365            fValueTypesLength = 0;
3366            fValueType = 0;
3367            fUseItemValueTypeVector = false;
3368            fItemValueTypesLength = 0;
3369            fItemValueType = null;
3370            fValues.setSize(0);
3371            if (fValueTypes != null) {
3372                fValueTypes.clear();
3373            }
3374            if (fItemValueTypes != null) {
3375                fItemValueTypes.setSize(0);
3376            }
3377        } // end clear():void
3378

3379        // appends the contents of one ValueStore to those of us.
3380
public void append(ValueStoreBase newVal) {
3381            for (int i = 0; i < newVal.fValues.size(); i++) {
3382                fValues.addElement(newVal.fValues.elementAt(i));
3383            }
3384        } // append(ValueStoreBase)
3385

3386        /** Start scope for value store. */
3387        public void startValueScope() {
3388            fValuesCount = 0;
3389            for (int i = 0; i < fFieldCount; i++) {
3390                fLocalValues[i] = null;
3391                fLocalValueTypes[i] = 0;
3392                fLocalItemValueTypes[i] = null;
3393            }
3394        } // startValueScope()
3395

3396        /** Ends scope for value store. */
3397        public void endValueScope() {
3398
3399            if (fValuesCount == 0) {
3400                if (fIdentityConstraint.getCategory() == IdentityConstraint.IC_KEY) {
3401                    String JavaDoc code = "AbsentKeyValue";
3402                    String JavaDoc eName = fIdentityConstraint.getElementName();
3403                    reportSchemaError(code, new Object JavaDoc[] { eName });
3404                }
3405                return;
3406            }
3407
3408            // do we have enough values?
3409
if (fValuesCount != fFieldCount) {
3410                switch (fIdentityConstraint.getCategory()) {
3411                    case IdentityConstraint.IC_UNIQUE :
3412                        {
3413                            String JavaDoc code = "UniqueNotEnoughValues";
3414                            String JavaDoc ename = fIdentityConstraint.getElementName();
3415                            reportSchemaError(code, new Object JavaDoc[] { ename });
3416                            break;
3417                        }
3418                    case IdentityConstraint.IC_KEY :
3419                        {
3420                            String JavaDoc code = "KeyNotEnoughValues";
3421                            UniqueOrKey key = (UniqueOrKey) fIdentityConstraint;
3422                            String JavaDoc ename = fIdentityConstraint.getElementName();
3423                            String JavaDoc kname = key.getIdentityConstraintName();
3424                            reportSchemaError(code, new Object JavaDoc[] { ename, kname });
3425                            break;
3426                        }
3427                    case IdentityConstraint.IC_KEYREF :
3428                        {
3429                            String JavaDoc code = "KeyRefNotEnoughValues";
3430                            KeyRef keyref = (KeyRef) fIdentityConstraint;
3431                            String JavaDoc ename = fIdentityConstraint.getElementName();
3432                            String JavaDoc kname = (keyref.getKey()).getIdentityConstraintName();
3433                            reportSchemaError(code, new Object JavaDoc[] { ename, kname });
3434                            break;
3435                        }
3436                }
3437                return;
3438            }
3439
3440        } // endValueScope()
3441

3442        // This is needed to allow keyref's to look for matched keys
3443
// in the correct scope. Unique and Key may also need to
3444
// override this method for purposes of their own.
3445
// This method is called whenever the DocumentFragment
3446
// of an ID Constraint goes out of scope.
3447
public void endDocumentFragment() {
3448        } // endDocumentFragment():void
3449

3450        /**
3451         * Signals the end of the document. This is where the specific
3452         * instances of value stores can verify the integrity of the
3453         * identity constraints.
3454         */

3455        public void endDocument() {
3456        } // endDocument()
3457

3458        //
3459
// ValueStore methods
3460
//
3461

3462        /* reports an error if an element is matched
3463         * has nillable true and is matched by a key.
3464         */

3465
3466        public void reportError(String JavaDoc key, Object JavaDoc[] args) {
3467            reportSchemaError(key, args);
3468        } // reportError(String,Object[])
3469

3470        /**
3471         * Adds the specified value to the value store.
3472         *
3473         * @param field The field associated to the value. This reference
3474         * is used to ensure that each field only adds a value
3475         * once within a selection scope.
3476         * @param actualValue The value to add.
3477         */

3478        public void addValue(Field field, Object JavaDoc actualValue, short valueType, ShortList itemValueType) {
3479            int i;
3480            for (i = fFieldCount - 1; i > -1; i--) {
3481                if (fFields[i] == field) {
3482                    break;
3483                }
3484            }
3485            // do we even know this field?
3486
if (i == -1) {
3487                String JavaDoc code = "UnknownField";
3488                reportSchemaError(code, new Object JavaDoc[] { field.toString()});
3489                return;
3490            }
3491            if (Boolean.TRUE != mayMatch(field)) {
3492                String JavaDoc code = "FieldMultipleMatch";
3493                reportSchemaError(code, new Object JavaDoc[] { field.toString()});
3494            } else {
3495                fValuesCount++;
3496            }
3497            fLocalValues[i] = actualValue;
3498            fLocalValueTypes[i] = valueType;
3499            fLocalItemValueTypes[i] = itemValueType;
3500            if (fValuesCount == fFieldCount) {
3501                checkDuplicateValues();
3502                // store values
3503
for (i = 0; i < fFieldCount; i++) {
3504                    fValues.addElement(fLocalValues[i]);
3505                    addValueType(fLocalValueTypes[i]);
3506                    addItemValueType(fLocalItemValueTypes[i]);
3507                }
3508            }
3509        } // addValue(String,Field)
3510

3511        /**
3512         * Returns true if this value store contains the locally scoped value stores
3513         */

3514        public boolean contains() {
3515            // REVISIT: we can improve performance by using hash codes, instead of
3516
// traversing global vector that could be quite large.
3517
int next = 0;
3518            final int size = fValues.size();
3519            LOOP : for (int i = 0; i < size; i = next) {
3520                next = i + fFieldCount;
3521                for (int j = 0; j < fFieldCount; j++) {
3522                    Object JavaDoc value1 = fLocalValues[j];
3523                    Object JavaDoc value2 = fValues.elementAt(i);
3524                    short valueType1 = fLocalValueTypes[j];
3525                    short valueType2 = getValueTypeAt(i);
3526                    if (value1 == null || value2 == null || valueType1 != valueType2 || !(value1.equals(value2))) {
3527                        continue LOOP;
3528                    }
3529                    else if(valueType1 == XSConstants.LIST_DT || valueType1 == XSConstants.LISTOFUNION_DT) {
3530                        ShortList list1 = fLocalItemValueTypes[j];
3531                        ShortList list2 = getItemValueTypeAt(i);
3532                        if(list1 == null || list2 == null || !list1.equals(list2))
3533                            continue LOOP;
3534                    }
3535                    i++;
3536                }
3537                // found it
3538
return true;
3539            }
3540            // didn't find it
3541
return false;
3542        } // contains():boolean
3543

3544        /**
3545         * Returns -1 if this value store contains the specified
3546         * values, otherwise the index of the first field in the
3547         * key sequence.
3548         */

3549        public int contains(ValueStoreBase vsb) {
3550            
3551            final Vector JavaDoc values = vsb.fValues;
3552            final int size1 = values.size();
3553            if (fFieldCount <= 1) {
3554                for (int i = 0; i < size1; ++i) {
3555                    short val = vsb.getValueTypeAt(i);
3556                    if (!valueTypeContains(val) || !fValues.contains(values.elementAt(i))) {
3557                        return i;
3558                    }
3559                    else if(val == XSConstants.LIST_DT || val == XSConstants.LISTOFUNION_DT) {
3560                        ShortList list1 = vsb.getItemValueTypeAt(i);
3561                        if (!itemValueTypeContains(list1)) {
3562                            return i;
3563                        }
3564                    }
3565                }
3566            }
3567            /** Handle n-tuples. **/
3568            else {
3569                final int size2 = fValues.size();
3570                /** Iterate over each set of fields. **/
3571                OUTER: for (int i = 0; i < size1; i += fFieldCount) {
3572                    /** Check whether this set is contained in the value store. **/
3573                    INNER: for (int j = 0; j < size2; j += fFieldCount) {
3574                        for (int k = 0; k < fFieldCount; ++k) {
3575                            final Object JavaDoc value1 = values.elementAt(i+k);
3576                            final Object JavaDoc value2 = fValues.elementAt(j+k);
3577                            final short valueType1 = vsb.getValueTypeAt(i+k);
3578                            final short valueType2 = getValueTypeAt(j+k);
3579                            if (value1 != value2 && (valueType1 != valueType2 || value1 == null || !value1.equals(value2))) {
3580                                continue INNER;
3581                            }
3582                            else if(valueType1 == XSConstants.LIST_DT || valueType1 == XSConstants.LISTOFUNION_DT) {
3583                                ShortList list1 = vsb.getItemValueTypeAt(i+k);
3584                                ShortList list2 = getItemValueTypeAt(j+k);
3585                                if (list1 == null || list2 == null || !list1.equals(list2)) {
3586                                    continue INNER;
3587                                }
3588                            }
3589                        }
3590                        continue OUTER;
3591                    }
3592                    return i;
3593                }
3594            }
3595            return -1;
3596            
3597        } // contains(Vector):Object
3598

3599        //
3600
// Protected methods
3601
//
3602

3603        protected void checkDuplicateValues() {
3604            // no-op
3605
} // duplicateValue(Hashtable)
3606

3607        /** Returns a string of the specified values. */
3608        protected String JavaDoc toString(Object JavaDoc[] values) {
3609
3610            // no values
3611
int size = values.length;
3612            if (size == 0) {
3613                return "";
3614            }
3615
3616            fTempBuffer.setLength(0);
3617
3618            // construct value string
3619
for (int i = 0; i < size; i++) {
3620                if (i > 0) {
3621                    fTempBuffer.append(',');
3622                }
3623                fTempBuffer.append(values[i]);
3624            }
3625            return fTempBuffer.toString();
3626
3627        } // toString(Object[]):String
3628

3629        /** Returns a string of the specified values. */
3630        protected String JavaDoc toString(Vector JavaDoc values, int start, int length) {
3631
3632            // no values
3633
if (length == 0) {
3634                return "";
3635            }
3636            
3637            // one value
3638
if (length == 1) {
3639                return String.valueOf(values.elementAt(start));
3640            }
3641
3642            // construct value string
3643
StringBuffer JavaDoc str = new StringBuffer JavaDoc();
3644            for (int i = 0; i < length; i++) {
3645                if (i > 0) {
3646                    str.append(',');
3647                }
3648                str.append(values.elementAt(start + i));
3649            }
3650            return str.toString();
3651
3652        } // toString(Vector,int,int):String
3653

3654        //
3655
// Object methods
3656
//
3657

3658        /** Returns a string representation of this object. */
3659        public String JavaDoc toString() {
3660            String JavaDoc s = super.toString();
3661            int index1 = s.lastIndexOf('$');
3662            if (index1 != -1) {
3663                s = s.substring(index1 + 1);
3664            }
3665            int index2 = s.lastIndexOf('.');
3666            if (index2 != -1) {
3667                s = s.substring(index2 + 1);
3668            }
3669            return s + '[' + fIdentityConstraint + ']';
3670        } // toString():String
3671

3672        //
3673
// Private methods
3674
//
3675

3676        private void addValueType(short type) {
3677            if (fUseValueTypeVector) {
3678                fValueTypes.add(type);
3679            }
3680            else if (fValueTypesLength++ == 0) {
3681                fValueType = type;
3682            }
3683            else if (fValueType != type) {
3684                fUseValueTypeVector = true;
3685                if (fValueTypes == null) {
3686                    fValueTypes = new ShortVector(fValueTypesLength * 2);
3687                }
3688                for (int i = 1; i < fValueTypesLength; ++i) {
3689                    fValueTypes.add(fValueType);
3690                }
3691                fValueTypes.add(type);
3692            }
3693        }
3694        
3695        private short getValueTypeAt(int index) {
3696            if (fUseValueTypeVector) {
3697                return fValueTypes.valueAt(index);
3698            }
3699            return fValueType;
3700        }
3701        
3702        private boolean valueTypeContains(short value) {
3703            if (fUseValueTypeVector) {
3704                return fValueTypes.contains(value);
3705            }
3706            return fValueType == value;
3707        }
3708        
3709        private void addItemValueType(ShortList itemValueType) {
3710            if (fUseItemValueTypeVector) {
3711                fItemValueTypes.add(itemValueType);
3712            }
3713            else if (fItemValueTypesLength++ == 0) {
3714                fItemValueType = itemValueType;
3715            }
3716            else if (!(fItemValueType == itemValueType ||
3717                    (fItemValueType != null && fItemValueType.equals(itemValueType)))) {
3718                fUseItemValueTypeVector = true;
3719                if (fItemValueTypes == null) {
3720                    fItemValueTypes = new Vector JavaDoc(fItemValueTypesLength * 2);
3721                }
3722                for (int i = 1; i < fItemValueTypesLength; ++i) {
3723                    fItemValueTypes.add(fItemValueType);
3724                }
3725                fItemValueTypes.add(itemValueType);
3726            }
3727        }
3728        
3729        private ShortList getItemValueTypeAt(int index) {
3730            if (fUseItemValueTypeVector) {
3731                return (ShortList) fItemValueTypes.elementAt(index);
3732            }
3733            return fItemValueType;
3734        }
3735        
3736        private boolean itemValueTypeContains(ShortList value) {
3737            if (fUseItemValueTypeVector) {
3738                return fItemValueTypes.contains(value);
3739            }
3740            return fItemValueType == value ||
3741                (fItemValueType != null && fItemValueType.equals(value));
3742        }
3743
3744    } // class ValueStoreBase
3745

3746    /**
3747     * Unique value store.
3748     *
3749     * @author Andy Clark, IBM
3750     */

3751    protected class UniqueValueStore extends ValueStoreBase {
3752
3753        //
3754
// Constructors
3755
//
3756

3757        /** Constructs a unique value store. */
3758        public UniqueValueStore(UniqueOrKey unique) {
3759            super(unique);
3760        } // <init>(Unique)
3761

3762        //
3763
// ValueStoreBase protected methods
3764
//
3765

3766        /**
3767         * Called when a duplicate value is added.
3768         */

3769        protected void checkDuplicateValues() {
3770            // is this value as a group duplicated?
3771
if (contains()) {
3772                String JavaDoc code = "DuplicateUnique";
3773                String JavaDoc value = toString(fLocalValues);
3774                String JavaDoc ename = fIdentityConstraint.getElementName();
3775                reportSchemaError(code, new Object JavaDoc[] { value, ename });
3776            }
3777        } // duplicateValue(Hashtable)
3778

3779    } // class UniqueValueStore
3780

3781    /**
3782     * Key value store.
3783     *
3784     * @author Andy Clark, IBM
3785     */

3786    protected class KeyValueStore extends ValueStoreBase {
3787
3788        // REVISIT: Implement a more efficient storage mechanism. -Ac
3789

3790        //
3791
// Constructors
3792
//
3793

3794        /** Constructs a key value store. */
3795        public KeyValueStore(UniqueOrKey key) {
3796            super(key);
3797        } // <init>(Key)
3798

3799        //
3800
// ValueStoreBase protected methods
3801
//
3802

3803        /**
3804         * Called when a duplicate value is added.
3805         */

3806        protected void checkDuplicateValues() {
3807            if (contains()) {
3808                String JavaDoc code = "DuplicateKey";
3809                String JavaDoc value = toString(fLocalValues);
3810                String JavaDoc ename = fIdentityConstraint.getElementName();
3811                reportSchemaError(code, new Object JavaDoc[] { value, ename });
3812            }
3813        } // duplicateValue(Hashtable)
3814

3815    } // class KeyValueStore
3816

3817    /**
3818     * Key reference value store.
3819     *
3820     * @author Andy Clark, IBM
3821     */

3822    protected class KeyRefValueStore extends ValueStoreBase {
3823
3824        //
3825
// Data
3826
//
3827

3828        /** Key value store. */
3829        protected ValueStoreBase fKeyValueStore;
3830
3831        //
3832
// Constructors
3833
//
3834

3835        /** Constructs a key value store. */
3836        public KeyRefValueStore(KeyRef keyRef, KeyValueStore keyValueStore) {
3837            super(keyRef);
3838            fKeyValueStore = keyValueStore;
3839        } // <init>(KeyRef)
3840

3841        //
3842
// ValueStoreBase methods
3843
//
3844

3845        // end the value Scope; here's where we have to tie
3846
// up keyRef loose ends.
3847
public void endDocumentFragment() {
3848
3849            // do all the necessary management...
3850
super.endDocumentFragment();
3851
3852            // verify references
3853
// get the key store corresponding (if it exists):
3854
fKeyValueStore =
3855                (ValueStoreBase) fValueStoreCache.fGlobalIDConstraintMap.get(
3856                    ((KeyRef) fIdentityConstraint).getKey());
3857
3858            if (fKeyValueStore == null) {
3859                // report error
3860
String JavaDoc code = "KeyRefOutOfScope";
3861                String JavaDoc value = fIdentityConstraint.toString();
3862                reportSchemaError(code, new Object JavaDoc[] { value });
3863                return;
3864            }
3865            int errorIndex = fKeyValueStore.contains(this);
3866            if (errorIndex != -1) {
3867                String JavaDoc code = "KeyNotFound";
3868                String JavaDoc values = toString(fValues, errorIndex, fFieldCount);
3869                String JavaDoc element = fIdentityConstraint.getElementName();
3870                String JavaDoc name = fIdentityConstraint.getName();
3871                reportSchemaError(code, new Object JavaDoc[] { name, values, element });
3872            }
3873
3874        } // endDocumentFragment()
3875

3876        /** End document. */
3877        public void endDocument() {
3878            super.endDocument();
3879
3880        } // endDocument()
3881

3882    } // class KeyRefValueStore
3883

3884    // value store management
3885

3886    /**
3887     * Value store cache. This class is used to store the values for
3888     * identity constraints.
3889     *
3890     * @author Andy Clark, IBM
3891     */

3892    protected class ValueStoreCache {
3893
3894        //
3895
// Data
3896
//
3897
final LocalIDKey fLocalId = new LocalIDKey();
3898        // values stores
3899

3900        /** stores all global Values stores. */
3901        protected final Vector JavaDoc fValueStores = new Vector JavaDoc();
3902
3903        /**
3904         * Values stores associated to specific identity constraints.
3905         * This hashtable maps IdentityConstraints and
3906         * the 0-based element on which their selectors first matched to
3907         * a corresponding ValueStore. This should take care
3908         * of all cases, including where ID constraints with
3909         * descendant-or-self axes occur on recursively-defined
3910         * elements.
3911         */

3912        protected final Hashtable JavaDoc fIdentityConstraint2ValueStoreMap = new Hashtable JavaDoc();
3913
3914        // sketch of algorithm:
3915
// - when a constraint is first encountered, its
3916
// values are stored in the (local) fIdentityConstraint2ValueStoreMap;
3917
// - Once it is validated (i.e., when it goes out of scope),
3918
// its values are merged into the fGlobalIDConstraintMap;
3919
// - as we encounter keyref's, we look at the global table to
3920
// validate them.
3921
//
3922
// The fGlobalIDMapStack has the following structure:
3923
// - validation always occurs against the fGlobalIDConstraintMap
3924
// (which comprises all the "eligible" id constraints);
3925
// When an endElement is found, this Hashtable is merged with the one
3926
// below in the stack.
3927
// When a start tag is encountered, we create a new
3928
// fGlobalIDConstraintMap.
3929
// i.e., the top of the fGlobalIDMapStack always contains
3930
// the preceding siblings' eligible id constraints;
3931
// the fGlobalIDConstraintMap contains descendants+self.
3932
// keyrefs can only match descendants+self.
3933
protected final Stack JavaDoc fGlobalMapStack = new Stack JavaDoc();
3934        protected final Hashtable JavaDoc fGlobalIDConstraintMap = new Hashtable JavaDoc();
3935
3936        //
3937
// Constructors
3938
//
3939

3940        /** Default constructor. */
3941        public ValueStoreCache() {
3942        } // <init>()
3943

3944        //
3945
// Public methods
3946
//
3947

3948        /** Resets the identity constraint cache. */
3949        public void startDocument() {
3950            fValueStores.removeAllElements();
3951            fIdentityConstraint2ValueStoreMap.clear();
3952            fGlobalIDConstraintMap.clear();
3953            fGlobalMapStack.removeAllElements();
3954        } // startDocument()
3955

3956        // startElement: pushes the current fGlobalIDConstraintMap
3957
// onto fGlobalMapStack and clears fGlobalIDConstraint map.
3958
public void startElement() {
3959            // only clone the hashtable when there are elements
3960
if (fGlobalIDConstraintMap.size() > 0)
3961                fGlobalMapStack.push(fGlobalIDConstraintMap.clone());
3962            else
3963                fGlobalMapStack.push(null);
3964            fGlobalIDConstraintMap.clear();
3965        } // startElement(void)
3966

3967        /** endElement(): merges contents of fGlobalIDConstraintMap with the
3968         * top of fGlobalMapStack into fGlobalIDConstraintMap.
3969         */

3970        public void endElement() {
3971            if (fGlobalMapStack.isEmpty())
3972                return; // must be an invalid doc!
3973
Hashtable JavaDoc oldMap = (Hashtable JavaDoc) fGlobalMapStack.pop();
3974            // return if there is no element
3975
if (oldMap == null)
3976                return;
3977
3978            Enumeration JavaDoc keys = oldMap.keys();
3979            while (keys.hasMoreElements()) {
3980                IdentityConstraint id = (IdentityConstraint) keys.nextElement();
3981                ValueStoreBase oldVal = (ValueStoreBase) oldMap.get(id);
3982                if (oldVal != null) {
3983                    ValueStoreBase currVal = (ValueStoreBase) fGlobalIDConstraintMap.get(id);
3984                    if (currVal == null)
3985                        fGlobalIDConstraintMap.put(id, oldVal);
3986                    else if (currVal != oldVal) {
3987                        currVal.append(oldVal);
3988                    }
3989                }
3990            }
3991        } // endElement()
3992

3993        /**
3994         * Initializes the value stores for the specified element
3995         * declaration.
3996         */

3997        public void initValueStoresFor(XSElementDecl eDecl, FieldActivator activator) {
3998            // initialize value stores for unique fields
3999
IdentityConstraint[] icArray = eDecl.fIDConstraints;
4000            int icCount = eDecl.fIDCPos;
4001            for (int i = 0; i < icCount; i++) {
4002                switch (icArray[i].getCategory()) {
4003                    case (IdentityConstraint.IC_UNIQUE) :
4004                        // initialize value stores for unique fields
4005
UniqueOrKey unique = (UniqueOrKey) icArray[i];
4006                        LocalIDKey toHash = new LocalIDKey(unique, fElementDepth);
4007                        UniqueValueStore uniqueValueStore =
4008                            (UniqueValueStore) fIdentityConstraint2ValueStoreMap.get(toHash);
4009                        if (uniqueValueStore == null) {
4010                            uniqueValueStore = new UniqueValueStore(unique);
4011                            fIdentityConstraint2ValueStoreMap.put(toHash, uniqueValueStore);
4012                        } else {
4013                            uniqueValueStore.clear();
4014                        }
4015                        fValueStores.addElement(uniqueValueStore);
4016                        activateSelectorFor(icArray[i]);
4017                        break;
4018                    case (IdentityConstraint.IC_KEY) :
4019                        // initialize value stores for key fields
4020
UniqueOrKey key = (UniqueOrKey) icArray[i];
4021                        toHash = new LocalIDKey(key, fElementDepth);
4022                        KeyValueStore keyValueStore =
4023                            (KeyValueStore) fIdentityConstraint2ValueStoreMap.get(toHash);
4024                        if (keyValueStore == null) {
4025                            keyValueStore = new KeyValueStore(key);
4026                            fIdentityConstraint2ValueStoreMap.put(toHash, keyValueStore);
4027                        } else {
4028                            keyValueStore.clear();
4029                        }
4030                        fValueStores.addElement(keyValueStore);
4031                        activateSelectorFor(icArray[i]);
4032                        break;
4033                    case (IdentityConstraint.IC_KEYREF) :
4034                        // initialize value stores for keyRef fields
4035
KeyRef keyRef = (KeyRef) icArray[i];
4036                        toHash = new LocalIDKey(keyRef, fElementDepth);
4037                        KeyRefValueStore keyRefValueStore =
4038                            (KeyRefValueStore) fIdentityConstraint2ValueStoreMap.get(toHash);
4039                        if (keyRefValueStore == null) {
4040                            keyRefValueStore = new KeyRefValueStore(keyRef, null);
4041                            fIdentityConstraint2ValueStoreMap.put(toHash, keyRefValueStore);
4042                        } else {
4043                            keyRefValueStore.clear();
4044                        }
4045                        fValueStores.addElement(keyRefValueStore);
4046                        activateSelectorFor(icArray[i]);
4047                        break;
4048                }
4049            }
4050        } // initValueStoresFor(XSElementDecl)
4051

4052        /** Returns the value store associated to the specified IdentityConstraint. */
4053        public ValueStoreBase getValueStoreFor(IdentityConstraint id, int initialDepth) {
4054            fLocalId.fDepth = initialDepth;
4055            fLocalId.fId = id;
4056            return (ValueStoreBase) fIdentityConstraint2ValueStoreMap.get(fLocalId);
4057        } // getValueStoreFor(IdentityConstraint, int):ValueStoreBase
4058

4059        /** Returns the global value store associated to the specified IdentityConstraint. */
4060        public ValueStoreBase getGlobalValueStoreFor(IdentityConstraint id) {
4061            return (ValueStoreBase) fGlobalIDConstraintMap.get(id);
4062        } // getValueStoreFor(IdentityConstraint):ValueStoreBase
4063

4064        // This method takes the contents of the (local) ValueStore
4065
// associated with id and moves them into the global
4066
// hashtable, if id is a <unique> or a <key>.
4067
// If it's a <keyRef>, then we leave it for later.
4068
public void transplant(IdentityConstraint id, int initialDepth) {
4069            fLocalId.fDepth = initialDepth;
4070            fLocalId.fId = id;
4071            ValueStoreBase newVals =
4072                (ValueStoreBase) fIdentityConstraint2ValueStoreMap.get(fLocalId);
4073            if (id.getCategory() == IdentityConstraint.IC_KEYREF)
4074                return;
4075            ValueStoreBase currVals = (ValueStoreBase) fGlobalIDConstraintMap.get(id);
4076            if (currVals != null) {
4077                currVals.append(newVals);
4078                fGlobalIDConstraintMap.put(id, currVals);
4079            } else
4080                fGlobalIDConstraintMap.put(id, newVals);
4081
4082        } // transplant(id)
4083

4084        /** Check identity constraints. */
4085        public void endDocument() {
4086
4087            int count = fValueStores.size();
4088            for (int i = 0; i < count; i++) {
4089                ValueStoreBase valueStore = (ValueStoreBase) fValueStores.elementAt(i);
4090                valueStore.endDocument();
4091            }
4092
4093        } // endDocument()
4094

4095        //
4096
// Object methods
4097
//
4098

4099        /** Returns a string representation of this object. */
4100        public String JavaDoc toString() {
4101            String JavaDoc s = super.toString();
4102            int index1 = s.lastIndexOf('$');
4103            if (index1 != -1) {
4104                return s.substring(index1 + 1);
4105            }
4106            int index2 = s.lastIndexOf('.');
4107            if (index2 != -1) {
4108                return s.substring(index2 + 1);
4109            }
4110            return s;
4111        } // toString():String
4112

4113    } // class ValueStoreCache
4114

4115    // the purpose of this class is to enable IdentityConstraint,int
4116
// pairs to be used easily as keys in Hashtables.
4117
protected class LocalIDKey {
4118
4119        public IdentityConstraint fId;
4120        public int fDepth;
4121
4122        public LocalIDKey() {
4123        }
4124
4125        public LocalIDKey(IdentityConstraint id, int depth) {
4126            fId = id;
4127            fDepth = depth;
4128        } // init(IdentityConstraint, int)
4129

4130        // object method
4131
public int hashCode() {
4132            return fId.hashCode() + fDepth;
4133        }
4134
4135        public boolean equals(Object JavaDoc localIDKey) {
4136            if (localIDKey instanceof LocalIDKey) {
4137                LocalIDKey lIDKey = (LocalIDKey) localIDKey;
4138                return (lIDKey.fId == fId && lIDKey.fDepth == fDepth);
4139            }
4140            return false;
4141        }
4142    } // class LocalIDKey
4143

4144    /**
4145     * A simple vector for <code>short</code>s.
4146     */

4147    protected static final class ShortVector {
4148        
4149        //
4150
// Data
4151
//
4152

4153        /** Current length. */
4154        private int fLength;
4155
4156        /** Data. */
4157        private short[] fData;
4158        
4159        //
4160
// Constructors
4161
//
4162

4163        public ShortVector() {}
4164        
4165        public ShortVector(int initialCapacity) {
4166            fData = new short[initialCapacity];
4167        }
4168
4169        //
4170
// Public methods
4171
//
4172

4173        /** Returns the length of the vector. */
4174        public int length() {
4175            return fLength;
4176        }
4177
4178        /** Adds the value to the vector. */
4179        public void add(short value) {
4180            ensureCapacity(fLength + 1);
4181            fData[fLength++] = value;
4182        }
4183
4184        /** Returns the short value at the specified position in the vector. */
4185        public short valueAt(int position) {
4186            return fData[position];
4187        }
4188
4189        /** Clears the vector. */
4190        public void clear() {
4191            fLength = 0;
4192        }
4193        
4194        /** Returns whether the short is contained in the vector. */
4195        public boolean contains(short value) {
4196            for (int i = 0; i < fLength; ++i) {
4197                if (fData[i] == value) {
4198                    return true;
4199                }
4200            }
4201            return false;
4202        }
4203
4204        //
4205
// Private methods
4206
//
4207

4208        /** Ensures capacity. */
4209        private void ensureCapacity(int size) {
4210            if (fData == null) {
4211                fData = new short[8];
4212            }
4213            else if (fData.length <= size) {
4214                short[] newdata = new short[fData.length * 2];
4215                System.arraycopy(fData, 0, newdata, 0, fData.length);
4216                fData = newdata;
4217            }
4218        }
4219    }
4220    
4221} // class SchemaValidator
4222
Popular Tags