KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xerces > internal > impl > xs > XMLSchemaValidator


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999-2004 The Apache Software Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package com.sun.org.apache.xerces.internal.impl.xs;
59
60 import java.io.IOException JavaDoc;
61 import java.util.Enumeration JavaDoc;
62 import java.util.Hashtable JavaDoc;
63 import java.util.HashMap JavaDoc;
64 import java.util.Stack JavaDoc;
65 import java.util.Vector JavaDoc;
66
67 import com.sun.org.apache.xerces.internal.impl.Constants;
68 import com.sun.org.apache.xerces.internal.impl.RevalidationHandler;
69 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
70 import com.sun.org.apache.xerces.internal.impl.dv.DatatypeException;
71 import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
72 import com.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo;
73 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
74 import com.sun.org.apache.xerces.internal.impl.dv.xs.XSSimpleTypeDecl;
75 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
76 import com.sun.org.apache.xerces.internal.impl.validation.ValidationState;
77 import com.sun.org.apache.xerces.internal.impl.xs.identity.Field;
78 import com.sun.org.apache.xerces.internal.impl.xs.identity.FieldActivator;
79 import com.sun.org.apache.xerces.internal.impl.xs.identity.IdentityConstraint;
80 import com.sun.org.apache.xerces.internal.impl.xs.identity.KeyRef;
81 import com.sun.org.apache.xerces.internal.impl.xs.identity.Selector;
82 import com.sun.org.apache.xerces.internal.impl.xs.identity.UniqueOrKey;
83 import com.sun.org.apache.xerces.internal.impl.xs.identity.ValueStore;
84 import com.sun.org.apache.xerces.internal.impl.xs.identity.XPathMatcher;
85 import com.sun.org.apache.xerces.internal.impl.xs.models.CMBuilder;
86 import com.sun.org.apache.xerces.internal.impl.xs.models.CMNodeFactory;
87 import com.sun.org.apache.xerces.internal.impl.xs.models.XSCMValidator;
88 import com.sun.org.apache.xerces.internal.xs.XSConstants;
89 import com.sun.org.apache.xerces.internal.xs.XSObjectList;
90 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
91 import com.sun.org.apache.xerces.internal.util.AugmentationsImpl;
92 import com.sun.org.apache.xerces.internal.util.IntStack;
93 import com.sun.org.apache.xerces.internal.util.SymbolTable;
94 import com.sun.org.apache.xerces.internal.util.XMLChar;
95 import com.sun.org.apache.xerces.internal.util.XMLResourceIdentifierImpl;
96 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
97 import com.sun.org.apache.xerces.internal.xni.Augmentations;
98 import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
99 import com.sun.org.apache.xerces.internal.xni.QName;
100 import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
101 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
102 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
103 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
104 import com.sun.org.apache.xerces.internal.xni.XMLString;
105 import com.sun.org.apache.xerces.internal.xni.XNIException;
106 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
107 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
108 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
109 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
110 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
111 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentFilter;
112 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
113 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
114 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
115 import com.sun.org.apache.xerces.internal.xs.AttributePSVI;
116 import com.sun.org.apache.xerces.internal.xs.ElementPSVI;
117 import com.sun.org.apache.xerces.internal.xs.XSComplexTypeDefinition;
118
119 /**
120  * The XML Schema validator. The validator implements a document
121  * filter: receiving document events from the scanner; validating
122  * the content and structure; augmenting the InfoSet, if applicable;
123  * and notifying the parser of the information resulting from the
124  * validation process.
125  * <p>
126  * This component requires the following features and properties from the
127  * component manager that uses it:
128  * <ul>
129  * <li>http://xml.org/sax/features/validation</li>
130  * <li>http://apache.org/xml/properties/internal/symbol-table</li>
131  * <li>http://apache.org/xml/properties/internal/error-reporter</li>
132  * <li>http://apache.org/xml/properties/internal/entity-resolver</li>
133  * </ul>
134  *
135  * @author Sandy Gao IBM
136  * @author Elena Litani IBM
137  * @author Andy Clark IBM
138  * @author Neeraj Bajaj, Sun Microsystems, inc.
139  * @version $Id: XMLSchemaValidator.java,v 1.155 2004/03/25 04:03:23 mrglavas Exp $
140  */

141 public class XMLSchemaValidator
142 implements XMLComponent, XMLDocumentFilter, FieldActivator, RevalidationHandler {
143     
144     //
145
// Constants
146
//
147
private static final boolean DEBUG = false;
148     
149     // feature identifiers
150

151     /** Feature identifier: validation. */
152     protected static final String JavaDoc VALIDATION =
153     Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
154     
155     /** Feature identifier: validation. */
156     protected static final String JavaDoc SCHEMA_VALIDATION =
157     Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
158     
159     /** Feature identifier: schema full checking*/
160     protected static final String JavaDoc SCHEMA_FULL_CHECKING =
161     Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING;
162     
163     /** Feature identifier: dynamic validation. */
164     protected static final String JavaDoc DYNAMIC_VALIDATION =
165     Constants.XERCES_FEATURE_PREFIX + Constants.DYNAMIC_VALIDATION_FEATURE;
166     
167     /** Feature identifier: expose schema normalized value */
168     protected static final String JavaDoc NORMALIZE_DATA =
169     Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE;
170     
171     /** Feature identifier: send element default value via characters() */
172     protected static final String JavaDoc SCHEMA_ELEMENT_DEFAULT =
173     Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_ELEMENT_DEFAULT;
174     
175     /** Feature identifier: augment PSVI */
176     protected static final String JavaDoc SCHEMA_AUGMENT_PSVI =
177     Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_AUGMENT_PSVI;
178     
179     /** Feature identifier: whether to recognize java encoding names */
180     protected static final String JavaDoc ALLOW_JAVA_ENCODINGS =
181     Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
182     
183     /** Feature identifier: standard uri conformant feature. */
184     protected static final String JavaDoc STANDARD_URI_CONFORMANT_FEATURE =
185     Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE;
186     
187     /** Feature identifier: whether to continue parsing a schema after a fatal error is encountered */
188     protected static final String JavaDoc CONTINUE_AFTER_FATAL_ERROR =
189     Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
190     
191     /** Feature identifier: ignore xsi:schemaLocation and xsi:noNamespaceSchemaLocation */
192     protected static final String JavaDoc IGNORE_SCHEMA_LOCATION_HINTS =
193     Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_SCHEMA_LOCATION_HINTS;
194     
195     protected static final String JavaDoc CHANGE_IGNORABLE_CHARACTERS_INTO_IGNORABLE_WHITESPACES =
196     Constants.XERCES_FEATURE_PREFIX + Constants.CHANGE_IGNORABLE_CHARACTERS_INTO_IGNORABLE_WHITESPACES;
197     
198     protected static final String JavaDoc PARSER_SETTINGS =
199     Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
200     
201     // property identifiers
202

203     /** Property identifier: symbol table. */
204     public static final String JavaDoc SYMBOL_TABLE =
205     Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
206     
207     /** Property identifier: error reporter. */
208     public static final String JavaDoc ERROR_REPORTER =
209     Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
210     
211     /** Property identifier: entity resolver. */
212     public static final String JavaDoc ENTITY_RESOLVER =
213     Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
214     
215     /** Property identifier: grammar pool. */
216     public static final String JavaDoc XMLGRAMMAR_POOL =
217     Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
218     
219     protected static final String JavaDoc VALIDATION_MANAGER =
220     Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
221     
222     protected static final String JavaDoc ENTITY_MANAGER =
223     Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
224     
225     /** Property identifier: schema location. */
226     protected static final String JavaDoc SCHEMA_LOCATION =
227     Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_LOCATION;
228     
229     /** Property identifier: no namespace schema location. */
230     protected static final String JavaDoc SCHEMA_NONS_LOCATION =
231     Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_NONS_LOCATION;
232     
233     /** Property identifier: JAXP schema source. */
234     protected static final String JavaDoc JAXP_SCHEMA_SOURCE =
235     Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
236     
237     /** Property identifier: JAXP schema language. */
238     protected static final String JavaDoc JAXP_SCHEMA_LANGUAGE =
239     Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE;
240     
241     // recognized features and properties
242

243     /** Recognized features. */
244     private static final String JavaDoc[] RECOGNIZED_FEATURES = {
245         VALIDATION,
246         SCHEMA_VALIDATION,
247         DYNAMIC_VALIDATION,
248         SCHEMA_FULL_CHECKING,
249         ALLOW_JAVA_ENCODINGS,
250         CONTINUE_AFTER_FATAL_ERROR,
251         STANDARD_URI_CONFORMANT_FEATURE,
252         IGNORE_SCHEMA_LOCATION_HINTS,
253         CHANGE_IGNORABLE_CHARACTERS_INTO_IGNORABLE_WHITESPACES };
254         
255         /** Feature defaults. */
256         private static final Boolean JavaDoc[] FEATURE_DEFAULTS = { null,
257         // NOTE: The following defaults are nulled out on purpose.
258
// If they are set, then when the XML Schema validator
259
// is constructed dynamically, these values may override
260
// those set by the application. This goes against the
261
// whole purpose of XMLComponent#getFeatureDefault but
262
// it can't be helped in this case. -Ac
263
null, //Boolean.FALSE,
264
null, //Boolean.FALSE,
265
null, //Boolean.FALSE,
266
null, //Boolean.FALSE,
267
null, //Boolean.FALSE,
268
null, //Boolean.FALSE,
269
null, //Boolean.FALSE,
270
null };
271         
272         /** Recognized properties. */
273         private static final String JavaDoc[] RECOGNIZED_PROPERTIES = {
274             SYMBOL_TABLE,
275             ERROR_REPORTER,
276             ENTITY_RESOLVER,
277             VALIDATION_MANAGER,
278             SCHEMA_LOCATION,
279             SCHEMA_NONS_LOCATION,
280             JAXP_SCHEMA_SOURCE,
281             JAXP_SCHEMA_LANGUAGE,
282         };
283         
284         /** Property defaults. */
285         private static final Object JavaDoc[] PROPERTY_DEFAULTS =
286         { null, null, null, null, null, null, null, null, };
287         
288         // this is the number of valuestores of each kind
289
// we expect an element to have. It's almost
290
// never > 1; so leave it at that.
291
protected static final int ID_CONSTRAINT_NUM = 1;
292         
293         //
294
// Data
295
//
296

297         /** current PSVI element info */
298         protected ElementPSVImpl fCurrentPSVI = new ElementPSVImpl();
299         
300         // since it is the responsibility of each component to an
301
// Augmentations parameter if one is null, to save ourselves from
302
// having to create this object continually, it is created here.
303
// If it is not present in calls that we're passing on, we *must*
304
// clear this before we introduce it into the pipeline.
305
protected final AugmentationsImpl fAugmentations = new AugmentationsImpl();
306         
307         /**
308          * Map which is used to catch instance documents that try
309          * and match a field several times in the same scope.
310          */

311         protected final HashMap JavaDoc fMayMatchFieldMap = new HashMap JavaDoc();
312         
313         // this is included for the convenience of handleEndElement
314
protected XMLString fDefaultValue;
315         
316         // Validation features
317
protected boolean fDynamicValidation = false;
318         protected boolean fSchemaDynamicValidation = false;
319         protected boolean fDoValidation = false;
320         protected boolean fFullChecking = false;
321         protected boolean fNormalizeData = true;
322         protected boolean fSchemaElementDefault = true;
323         protected boolean fAugPSVI = true;
324         protected boolean fIdConstraint = false;
325         protected boolean fIgnoreXsiSchemaLocationHints = false;
326         protected boolean fTurnIgnorableCharactersIntoIgnorableWhitespaces = false;
327         /** Schema type: None, DTD, Schema */
328         private String JavaDoc fSchemaType = null;
329         
330         // to indicate whether we are in the scope of entity reference or CData
331
protected boolean fEntityRef = false;
332         protected boolean fInCDATA = false;
333         
334         // properties
335

336         /** Symbol table. */
337         protected SymbolTable fSymbolTable;
338         
339         /**
340          * While parsing a document, keep the location of the document.
341          */

342         private XMLLocator fLocator;
343         
344         /**
345          * A wrapper of the standard error reporter. We'll store all schema errors
346          * in this wrapper object, so that we can get all errors (error codes) of
347          * a specific element. This is useful for PSVI.
348          */

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

433             public void reportError(
434             XMLLocator location,
435             String JavaDoc domain,
436             String JavaDoc key,
437             Object JavaDoc[] arguments,
438             short severity)
439             throws XNIException {
440                 fErrorReporter.reportError(location, domain, key, arguments, severity);
441                 fErrors.addElement(key);
442             } // reportError(XMLLocator,String,String,Object[],short)
443
}
444         
445         /** Error reporter. */
446         protected final XSIErrorReporter fXSIErrorReporter = new XSIErrorReporter();
447         
448         /** Entity resolver */
449         protected XMLEntityResolver fEntityResolver;
450         
451         // updated during reset
452
protected ValidationManager fValidationManager = null;
453         protected ValidationState fValidationState = new ValidationState();
454         protected XMLGrammarPool fGrammarPool;
455         
456         // schema location property values
457
protected String JavaDoc fExternalSchemas = null;
458         protected String JavaDoc fExternalNoNamespaceSchema = null;
459         
460         //JAXP Schema Source property
461
protected Object JavaDoc fJaxpSchemaSource = null;
462         
463         //ResourceIdentifier for use in calling EntityResolver
464
final XMLResourceIdentifierImpl fResourceIdentifier = new XMLResourceIdentifierImpl();
465         
466         /** Schema Grammar Description passed, to give a chance to application to supply the Grammar */
467         protected final XSDDescription fXSDDescription = new XSDDescription();
468         protected final Hashtable JavaDoc fLocationPairs = new Hashtable JavaDoc();
469         
470         
471         
472         
473         // handlers
474

475         /** Document handler. */
476         protected XMLDocumentHandler fDocumentHandler;
477         
478         protected XMLDocumentSource fDocumentSource;
479         
480         //
481
// XMLComponent methods
482
//
483

484         /**
485          * Returns a list of feature identifiers that are recognized by
486          * this component. This method may return null if no features
487          * are recognized by this component.
488          */

489         public String JavaDoc[] getRecognizedFeatures() {
490             return (String JavaDoc[]) (RECOGNIZED_FEATURES.clone());
491         } // getRecognizedFeatures():String[]
492

493         /**
494          * Sets the state of a feature. This method is called by the component
495          * manager any time after reset when a feature changes state.
496          * <p>
497          * <strong>Note:</strong> Components should silently ignore features
498          * that do not affect the operation of the component.
499          *
500          * @param featureId The feature identifier.
501          * @param state The state of the feature.
502          *
503          * @throws SAXNotRecognizedException The component should not throw
504          * this exception.
505          * @throws SAXNotSupportedException The component should not throw
506          * this exception.
507          */

508         public void setFeature(String JavaDoc featureId, boolean state) throws XMLConfigurationException {
509         } // setFeature(String,boolean)
510

511         /**
512          * Returns a list of property identifiers that are recognized by
513          * this component. This method may return null if no properties
514          * are recognized by this component.
515          */

516         public String JavaDoc[] getRecognizedProperties() {
517             return (String JavaDoc[])(RECOGNIZED_PROPERTIES.clone());
518         } // getRecognizedProperties():String[]
519

520         /**
521          * Sets the value of a property. This method is called by the component
522          * manager any time after reset when a property changes value.
523          * <p>
524          * <strong>Note:</strong> Components should silently ignore properties
525          * that do not affect the operation of the component.
526          *
527          * @param propertyId The property identifier.
528          * @param value The value of the property.
529          *
530          * @throws SAXNotRecognizedException The component should not throw
531          * this exception.
532          * @throws SAXNotSupportedException The component should not throw
533          * this exception.
534          */

535         public void setProperty(String JavaDoc propertyId, Object JavaDoc value) throws XMLConfigurationException {
536         } // setProperty(String,Object)
537

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

547         public Boolean JavaDoc getFeatureDefault(String JavaDoc featureId) {
548             for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
549                 if (RECOGNIZED_FEATURES[i].equals(featureId)) {
550                     return FEATURE_DEFAULTS[i];
551                 }
552             }
553             return null;
554         } // getFeatureDefault(String):Boolean
555

556         /**
557          * Returns the default state for a property, or null if this
558          * component does not want to report a default value for this
559          * property.
560          *
561          * @param propertyId The property identifier.
562          *
563          * @since Xerces 2.2.0
564          */

565         public Object JavaDoc getPropertyDefault(String JavaDoc propertyId) {
566             for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
567                 if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
568                     return PROPERTY_DEFAULTS[i];
569                 }
570             }
571             return null;
572         } // getPropertyDefault(String):Object
573

574         //
575
// XMLDocumentSource methods
576
//
577

578         /** Sets the document handler to receive information about the document. */
579         public void setDocumentHandler(XMLDocumentHandler documentHandler) {
580             fDocumentHandler = documentHandler;
581         } // setDocumentHandler(XMLDocumentHandler)
582

583         /** Returns the document handler */
584         public XMLDocumentHandler getDocumentHandler() {
585             return fDocumentHandler;
586         } // setDocumentHandler(XMLDocumentHandler)
587

588         //
589
// XMLDocumentHandler methods
590
//
591

592         /** Sets the document source */
593         public void setDocumentSource(XMLDocumentSource source){
594             fDocumentSource = source;
595         } // setDocumentSource
596

597         /** Returns the document source */
598         public XMLDocumentSource getDocumentSource(){
599             return fDocumentSource;
600         } // getDocumentSource
601

602         /**
603          * The start of the document.
604          *
605          * @param locator The system identifier of the entity if the entity
606          * is external, null otherwise.
607          * @param encoding The auto-detected IANA encoding name of the entity
608          * stream. This value will be null in those situations
609          * where the entity encoding is not auto-detected (e.g.
610          * internal entities or a document entity that is
611          * parsed from a java.io.Reader).
612          * @param namespaceContext
613          * The namespace context in effect at the
614          * start of this document.
615          * This object represents the current context.
616          * Implementors of this class are responsible
617          * for copying the namespace bindings from the
618          * the current context (and its parent contexts)
619          * if that information is important.
620          * @param augs Additional information that may include infoset augmentations
621          *
622          * @throws XNIException Thrown by handler to signal an error.
623          */

624         public void startDocument(
625         XMLLocator locator,
626         String JavaDoc encoding,
627         NamespaceContext namespaceContext,
628         Augmentations augs)
629         throws XNIException {
630             
631             fValidationState.setNamespaceSupport(namespaceContext);
632             fState4XsiType.setNamespaceSupport(namespaceContext);
633             fState4ApplyDefault.setNamespaceSupport(namespaceContext);
634             fLocator = locator;
635             
636             handleStartDocument(locator, encoding);
637             // call handlers
638
if (fDocumentHandler != null) {
639                 fDocumentHandler.startDocument(locator, encoding, namespaceContext, augs);
640             }
641             
642         } // startDocument(XMLLocator,String)
643

644         /**
645          * Notifies of the presence of an XMLDecl line in the document. If
646          * present, this method will be called immediately following the
647          * startDocument call.
648          *
649          * @param version The XML version.
650          * @param encoding The IANA encoding name of the document, or null if
651          * not specified.
652          * @param standalone The standalone value, or null if not specified.
653          * @param augs Additional information that may include infoset augmentations
654          *
655          * @throws XNIException Thrown by handler to signal an error.
656          */

657         public void xmlDecl(String JavaDoc version, String JavaDoc encoding, String JavaDoc standalone, Augmentations augs)
658         throws XNIException {
659             
660             // call handlers
661
if (fDocumentHandler != null) {
662                 fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
663             }
664             
665         } // xmlDecl(String,String,String)
666

667         /**
668          * Notifies of the presence of the DOCTYPE line in the document.
669          *
670          * @param rootElement The name of the root element.
671          * @param publicId The public identifier if an external DTD or null
672          * if the external DTD is specified using SYSTEM.
673          * @param systemId The system identifier if an external DTD, null
674          * otherwise.
675          * @param augs Additional information that may include infoset augmentations
676          *
677          * @throws XNIException Thrown by handler to signal an error.
678          */

679         public void doctypeDecl(
680         String JavaDoc rootElement,
681         String JavaDoc publicId,
682         String JavaDoc systemId,
683         Augmentations augs)
684         throws XNIException {
685             
686             // call handlers
687
if (fDocumentHandler != null) {
688                 fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
689             }
690             
691         } // doctypeDecl(String,String,String)
692

693         /**
694          * The start of an 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 startElement(QName element, XMLAttributes attributes, Augmentations augs)
703         throws XNIException {
704             
705             Augmentations modifiedAugs = handleStartElement(element, attributes, augs);
706             // call handlers
707
if (fDocumentHandler != null) {
708                 fDocumentHandler.startElement(element, attributes, modifiedAugs );
709             }
710             
711         } // startElement(QName,XMLAttributes, Augmentations)
712

713         /**
714          * An empty element.
715          *
716          * @param element The name of the element.
717          * @param attributes The element attributes.
718          * @param augs Additional information that may include infoset augmentations
719          *
720          * @throws XNIException Thrown by handler to signal an error.
721          */

722         public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
723         throws XNIException {
724             
725             Augmentations modifiedAugs = handleStartElement(element, attributes, augs);
726             
727             // in the case where there is a {value constraint}, and the element
728
// doesn't have any text content, change emptyElement call to
729
// start + characters + end
730
fDefaultValue = null;
731             // fElementDepth == -2 indicates that the schema validator was removed
732
// from the pipeline. then we don't need to call handleEndElement.
733
if (fElementDepth != -2)
734                 modifiedAugs = handleEndElement(element, modifiedAugs);
735             
736             // call handlers
737
if (fDocumentHandler != null) {
738                 if (!fSchemaElementDefault || fDefaultValue == null) {
739                     fDocumentHandler.emptyElement(element, attributes, modifiedAugs);
740                 } else {
741                     fDocumentHandler.startElement(element, attributes, modifiedAugs);
742                     fDocumentHandler.characters(fDefaultValue, null);
743                     fDocumentHandler.endElement(element, modifiedAugs);
744                 }
745             }
746         } // emptyElement(QName,XMLAttributes, Augmentations)
747

748         /**
749          * Character content.
750          *
751          * @param text The content.
752          * @param augs Additional information that may include infoset augmentations
753          *
754          * @throws XNIException Thrown by handler to signal an error.
755          */

756         public void characters(XMLString text, Augmentations augs) throws XNIException {
757             
758             text = handleCharacters(text);
759             // call handlers
760
if (fDocumentHandler != null) {
761                 if (fNormalizeData && fUnionType) {
762                     // for union types we can't normalize data
763
// thus we only need to send augs information if any;
764
// the normalized data for union will be send
765
// after normalization is performed (at the endElement())
766
if (augs != null)
767                         fDocumentHandler.characters(fEmptyXMLStr, augs);
768                 } else {
769                     if( fTurnIgnorableCharactersIntoIgnorableWhitespaces && isElementOnlyContent() )
770                         fDocumentHandler.ignorableWhitespace(text, augs);
771                     else
772                         fDocumentHandler.characters(text, augs);
773                 }
774             }
775             
776         } // characters(XMLString)
777

778         /**
779          * Ignorable whitespace. For this method to be called, the document
780          * source must have some way of determining that the text containing
781          * only whitespace characters should be considered ignorable. For
782          * example, the validator can determine if a length of whitespace
783          * characters in the document are ignorable based on the element
784          * content model.
785          *
786          * @param text The ignorable whitespace.
787          * @param augs Additional information that may include infoset augmentations
788          *
789          * @throws XNIException Thrown by handler to signal an error.
790          */

791         public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
792             
793             handleIgnorableWhitespace(text);
794             // call handlers
795
if (fDocumentHandler != null) {
796                 fDocumentHandler.ignorableWhitespace(text, augs);
797             }
798             
799         } // ignorableWhitespace(XMLString)
800

801         /**
802          * The end of an element.
803          *
804          * @param element The name of the element.
805          * @param augs Additional information that may include infoset augmentations
806          *
807          * @throws XNIException Thrown by handler to signal an error.
808          */

809         public void endElement(QName element, Augmentations augs) throws XNIException {
810             
811             // in the case where there is a {value constraint}, and the element
812
// doesn't have any text content, add a characters call.
813
fDefaultValue = null;
814             Augmentations modifiedAugs = handleEndElement(element, augs);
815             // call handlers
816
if (fDocumentHandler != null) {
817                 if (!fSchemaElementDefault || fDefaultValue == null) {
818                     fDocumentHandler.endElement(element, modifiedAugs);
819                 } else {
820                     fDocumentHandler.characters(fDefaultValue, null);
821                     fDocumentHandler.endElement(element, modifiedAugs);
822                 }
823             }
824         } // endElement(QName, Augmentations)
825

826         /**
827          * The start of a CDATA section.
828          *
829          * @param augs Additional information that may include infoset augmentations
830          *
831          * @throws XNIException Thrown by handler to signal an error.
832          */

833         public void startCDATA(Augmentations augs) throws XNIException {
834             
835             // REVISIT: what should we do here if schema normalization is on??
836
fInCDATA = true;
837             // call handlers
838
if (fDocumentHandler != null) {
839                 fDocumentHandler.startCDATA(augs);
840             }
841             
842         } // startCDATA()
843

844         /**
845          * The end of a CDATA section.
846          *
847          * @param augs Additional information that may include infoset augmentations
848          *
849          * @throws XNIException Thrown by handler to signal an error.
850          */

851         public void endCDATA(Augmentations augs) throws XNIException {
852             
853             // call handlers
854
fInCDATA = false;
855             if (fDocumentHandler != null) {
856                 fDocumentHandler.endCDATA(augs);
857             }
858             
859         } // endCDATA()
860

861         /**
862          * The end of the document.
863          *
864          * @param augs Additional information that may include infoset augmentations
865          *
866          * @throws XNIException Thrown by handler to signal an error.
867          */

868         public void endDocument(Augmentations augs) throws XNIException {
869             
870             handleEndDocument();
871             
872             // call handlers
873
if (fDocumentHandler != null) {
874                 fDocumentHandler.endDocument(augs);
875             }
876             fLocator = null;
877             
878         } // endDocument(Augmentations)
879

880         //
881
// DOMRevalidationHandler methods
882
//
883

884         
885         
886         
887         
888         public boolean characterData(String JavaDoc data, Augmentations augs) {
889             
890             fSawText = fSawText || data.length() > 0;
891             
892             // REVISIT: this methods basically duplicates implementation of
893
// handleCharacters(). We should be able to reuse some code
894

895             // if whitespace == -1 skip normalization, because it is a complexType
896
// or a union type.
897
if (fNormalizeData && fWhiteSpace != -1 && fWhiteSpace != XSSimpleType.WS_PRESERVE) {
898                 // normalize data
899
normalizeWhitespace(data, fWhiteSpace == XSSimpleType.WS_COLLAPSE);
900                 fBuffer.append(fNormalizedStr.ch, fNormalizedStr.offset, fNormalizedStr.length);
901             } else {
902                 if (fAppendBuffer)
903                     fBuffer.append(data);
904             }
905             
906             // When it's a complex type with element-only content, we need to
907
// find out whether the content contains any non-whitespace character.
908
boolean allWhiteSpace = true;
909             if (fCurrentType != null
910             && fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
911                 XSComplexTypeDecl ctype = (XSComplexTypeDecl)fCurrentType;
912                 if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
913                     // data outside of element content
914
for (int i=0; i< data.length(); i++) {
915                         if (!XMLChar.isSpace(data.charAt(i))) {
916                             allWhiteSpace = false;
917                             fSawCharacters = true;
918                             break;
919                         }
920                     }
921                 }
922             }
923             
924             return allWhiteSpace;
925         }
926         
927         public void elementDefault(String JavaDoc data){
928             // no-op
929
}
930         
931         //
932
// XMLDocumentHandler and XMLDTDHandler methods
933
//
934

935         /**
936          * This method notifies the start of a general entity.
937          * <p>
938          * <strong>Note:</strong> This method is not called for entity references
939          * appearing as part of attribute values.
940          *
941          * @param name The name of the general entity.
942          * @param identifier The resource identifier.
943          * @param encoding The auto-detected IANA encoding name of the entity
944          * stream. This value will be null in those situations
945          * where the entity encoding is not auto-detected (e.g.
946          * internal entities or a document entity that is
947          * parsed from a java.io.Reader).
948          * @param augs Additional information that may include infoset augmentations
949          *
950          * @exception XNIException Thrown by handler to signal an error.
951          */

952         public void startGeneralEntity(
953         String JavaDoc name,
954         XMLResourceIdentifier identifier,
955         String JavaDoc encoding,
956         Augmentations augs)
957         throws XNIException {
958             
959             // REVISIT: what should happen if normalize_data_ is on??
960
fEntityRef = true;
961             // call handlers
962
if (fDocumentHandler != null) {
963                 fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
964             }
965             
966         } // startEntity(String,String,String,String,String)
967

968         /**
969          * Notifies of the presence of a TextDecl line in an entity. If present,
970          * this method will be called immediately following the startEntity call.
971          * <p>
972          * <strong>Note:</strong> This method will never be called for the
973          * document entity; it is only called for external general entities
974          * referenced in document content.
975          * <p>
976          * <strong>Note:</strong> This method is not called for entity references
977          * appearing as part of attribute values.
978          *
979          * @param version The XML version, or null if not specified.
980          * @param encoding The IANA encoding name of the entity.
981          * @param augs Additional information that may include infoset augmentations
982          *
983          * @throws XNIException Thrown by handler to signal an error.
984          */

985         public void textDecl(String JavaDoc version, String JavaDoc encoding, Augmentations augs) throws XNIException {
986             
987             // call handlers
988
if (fDocumentHandler != null) {
989                 fDocumentHandler.textDecl(version, encoding, augs);
990             }
991             
992         } // textDecl(String,String)
993

994         /**
995          * A comment.
996          *
997          * @param text The text in the comment.
998          * @param augs Additional information that may include infoset augmentations
999          *
1000         * @throws XNIException Thrown by application to signal an error.
1001         */

1002        public void comment(XMLString text, Augmentations augs) throws XNIException {
1003            
1004            // record the fact that there is a comment child.
1005
fSawChildren = true;
1006            
1007            // call handlers
1008
if (fDocumentHandler != null) {
1009                fDocumentHandler.comment(text, augs);
1010            }
1011            
1012        } // comment(XMLString)
1013

1014        /**
1015         * A processing instruction. Processing instructions consist of a
1016         * target name and, optionally, text data. The data is only meaningful
1017         * to the application.
1018         * <p>
1019         * Typically, a processing instruction's data will contain a series
1020         * of pseudo-attributes. These pseudo-attributes follow the form of
1021         * element attributes but are <strong>not</strong> parsed or presented
1022         * to the application as anything other than text. The application is
1023         * responsible for parsing the data.
1024         *
1025         * @param target The target.
1026         * @param data The data or null if none specified.
1027         * @param augs Additional information that may include infoset augmentations
1028         *
1029         * @throws XNIException Thrown by handler to signal an error.
1030         */

1031        public void processingInstruction(String JavaDoc target, XMLString data, Augmentations augs)
1032        throws XNIException {
1033            
1034            // record the fact that there is a PI child.
1035
fSawChildren = true;
1036            
1037            // call handlers
1038
if (fDocumentHandler != null) {
1039                fDocumentHandler.processingInstruction(target, data, augs);
1040            }
1041            
1042        } // processingInstruction(String,XMLString)
1043

1044        /**
1045         * This method notifies the end of a general entity.
1046         * <p>
1047         * <strong>Note:</strong> This method is not called for entity references
1048         * appearing as part of attribute values.
1049         *
1050         * @param name The name of the entity.
1051         * @param augs Additional information that may include infoset augmentations
1052         *
1053         * @exception XNIException
1054         * Thrown by handler to signal an error.
1055         */

1056        public void endGeneralEntity(String JavaDoc name, Augmentations augs) throws XNIException {
1057            
1058            // call handlers
1059
fEntityRef = false;
1060            if (fDocumentHandler != null) {
1061                fDocumentHandler.endGeneralEntity(name, augs);
1062            }
1063            
1064        } // endEntity(String)
1065

1066        // constants
1067

1068        static final int INITIAL_STACK_SIZE = 8;
1069        static final int INC_STACK_SIZE = 8;
1070        
1071        //
1072
// Data
1073
//
1074

1075        // Schema Normalization
1076

1077        private static final boolean DEBUG_NORMALIZATION = false;
1078        // temporary empty string buffer.
1079
private final XMLString fEmptyXMLStr = new XMLString(null, 0, -1);
1080        // temporary character buffer, and empty string buffer.
1081
private static final int BUFFER_SIZE = 20;
1082        private final XMLString fNormalizedStr = new XMLString();
1083        private boolean fFirstChunk = true;
1084        // got first chunk in characters() (SAX)
1085
private boolean fTrailing = false; // Previous chunk had a trailing space
1086
private short fWhiteSpace = -1; //whiteSpace: preserve/replace/collapse
1087
private boolean fUnionType = false;
1088        
1089        /** Schema grammar resolver. */
1090        final XSGrammarBucket fGrammarBucket;
1091        final SubstitutionGroupHandler fSubGroupHandler;
1092        
1093        // Schema grammar loader
1094
final XMLSchemaLoader fSchemaLoader;
1095        
1096        /** the DV usd to convert xsi:type to a QName */
1097        // REVISIT: in new simple type design, make things in DVs static,
1098
// so that we can QNameDV.getCompiledForm()
1099
final XSSimpleType fQNameDV =
1100        (XSSimpleType) SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(SchemaSymbols.ATTVAL_QNAME);
1101        
1102        final CMNodeFactory nodeFactory = new CMNodeFactory();
1103        /** used to build content models */
1104        // REVISIT: create decl pool, and pass it to each traversers
1105
final CMBuilder fCMBuilder = new CMBuilder(nodeFactory);
1106        
1107        // state
1108

1109        /** String representation of the validation root. */
1110        // REVISIT: what do we store here? QName, XPATH, some ID? use rawname now.
1111
String JavaDoc fValidationRoot;
1112        
1113        /** Skip validation: anything below this level should be skipped */
1114        int fSkipValidationDepth;
1115        
1116        /** anything above this level has validation_attempted != full */
1117        int fNFullValidationDepth;
1118        
1119        /** anything above this level has validation_attempted != none */
1120        int fNNoneValidationDepth;
1121        
1122        /** Element depth: -2: validator not in pipeline; >= -1 current depth. */
1123        int fElementDepth;
1124        
1125        /** Seen sub elements. */
1126        boolean fSubElement;
1127        
1128        /** Seen sub elements stack. */
1129        boolean[] fSubElementStack = new boolean[INITIAL_STACK_SIZE];
1130        
1131        /** Current element declaration. */
1132        XSElementDecl fCurrentElemDecl;
1133        
1134        /** Element decl stack. */
1135        XSElementDecl[] fElemDeclStack = new XSElementDecl[INITIAL_STACK_SIZE];
1136        
1137        /** nil value of the current element */
1138        boolean fNil;
1139        
1140        /** nil value stack */
1141        boolean[] fNilStack = new boolean[INITIAL_STACK_SIZE];
1142        
1143        /** notation value of the current element */
1144        XSNotationDecl fNotation;
1145        
1146        /** notation stack */
1147        XSNotationDecl[] fNotationStack = new XSNotationDecl[INITIAL_STACK_SIZE];
1148        
1149        /** Current type. */
1150        XSTypeDefinition fCurrentType;
1151        
1152        /** type stack. */
1153        XSTypeDefinition[] fTypeStack = new XSTypeDefinition[INITIAL_STACK_SIZE];
1154        
1155        /** Current content model. */
1156        XSCMValidator fCurrentCM;
1157        
1158        /** Content model stack. */
1159        XSCMValidator[] fCMStack = new XSCMValidator[INITIAL_STACK_SIZE];
1160        
1161        /** the current state of the current content model */
1162        int[] fCurrCMState;
1163        
1164        /** stack to hold content model states */
1165        int[][] fCMStateStack = new int[INITIAL_STACK_SIZE][];
1166        
1167        /** whether the curret element is strictly assessed */
1168        boolean fStrictAssess = true;
1169        
1170        /** strict assess stack */
1171        boolean[] fStrictAssessStack = new boolean[INITIAL_STACK_SIZE];
1172        
1173        /** Temporary string buffers. */
1174        final StringBuffer JavaDoc fBuffer = new StringBuffer JavaDoc();
1175        
1176        /** Whether need to append characters to fBuffer */
1177        boolean fAppendBuffer = true;
1178        
1179        /** Did we see any character data? */
1180        boolean fSawText = false;
1181        
1182        /** stack to record if we saw character data */
1183        boolean[] fSawTextStack = new boolean[INITIAL_STACK_SIZE];
1184        
1185        /** Did we see non-whitespace character data? */
1186        boolean fSawCharacters = false;
1187        
1188        /** Stack to record if we saw character data outside of element content*/
1189        boolean[] fStringContent = new boolean[INITIAL_STACK_SIZE];
1190        
1191        /** Did we see children that are neither characters nor elements? */
1192        boolean fSawChildren = false;
1193        
1194        /** Stack to record if we other children that character or elements */
1195        boolean[] fSawChildrenStack = new boolean[INITIAL_STACK_SIZE];
1196        
1197        /** temprory qname */
1198        final QName fTempQName = new QName();
1199        
1200        /** temprory validated info */
1201        ValidatedInfo fValidatedInfo = new ValidatedInfo();
1202        
1203        // used to validate default/fixed values against xsi:type
1204
// only need to check facets, so we set extraChecking to false (in reset)
1205
private ValidationState fState4XsiType = new ValidationState();
1206        
1207        // used to apply default/fixed values
1208
// only need to check id/idref/entity, so we set checkFacets to false
1209
private ValidationState fState4ApplyDefault = new ValidationState();
1210        
1211        // identity constraint information
1212

1213        /**
1214         * Stack of active XPath matchers for identity constraints. All
1215         * active XPath matchers are notified of startElement
1216         * and endElement callbacks in order to perform their matches.
1217         * <p>
1218         * For each element with identity constraints, the selector of
1219         * each identity constraint is activated. When the selector matches
1220         * its XPath, then all the fields of the identity constraint are
1221         * activated.
1222         * <p>
1223         * <strong>Note:</strong> Once the activation scope is left, the
1224         * XPath matchers are automatically removed from the stack of
1225         * active matchers and no longer receive callbacks.
1226         */

1227        protected XPathMatcherStack fMatcherStack = new XPathMatcherStack();
1228        
1229        /** Cache of value stores for identity constraint fields. */
1230        protected ValueStoreCache fValueStoreCache = new ValueStoreCache();
1231        
1232        //
1233
// Constructors
1234
//
1235

1236        /** Default constructor. */
1237        public XMLSchemaValidator() {
1238            fGrammarBucket = new XSGrammarBucket();
1239            fSubGroupHandler = new SubstitutionGroupHandler(fGrammarBucket);
1240            // initialize the schema loader
1241
fSchemaLoader =
1242            new XMLSchemaLoader(
1243            fXSIErrorReporter.fErrorReporter,
1244            fGrammarBucket,
1245            fSubGroupHandler,
1246            fCMBuilder);
1247            
1248            fState4XsiType.setExtraChecking(false);
1249            fState4ApplyDefault.setFacetChecking(false);
1250            
1251        } // <init>()
1252

1253    /*
1254     * Resets the component. The component can query the component manager
1255     * about any features and properties that affect the operation of the
1256     * component.
1257     *
1258     * @param componentManager The component manager.
1259     *
1260     * @throws SAXException Thrown by component on finitialization error.
1261     * For example, if a feature or property is
1262     * required for the operation of the component, the
1263     * component manager may throw a
1264     * SAXNotRecognizedException or a
1265     * SAXNotSupportedException.
1266     */

1267        public void reset(XMLComponentManager componentManager) throws XMLConfigurationException {
1268            
1269            
1270            fIdConstraint = false;
1271            //reset XSDDescription
1272
fLocationPairs.clear();
1273            
1274            // cleanup id table
1275
fValidationState.resetIDTables();
1276            
1277            //pass the component manager to the factory..
1278
nodeFactory.reset(componentManager);
1279            
1280            // reset schema loader
1281
fSchemaLoader.reset(componentManager);
1282            
1283            // initialize state
1284
fCurrentElemDecl = null;
1285            fCurrentCM = null;
1286            fCurrCMState = null;
1287            fSkipValidationDepth = -1;
1288            fNFullValidationDepth = -1;
1289            fNNoneValidationDepth = -1;
1290            fElementDepth = -1;
1291            fSubElement = false;
1292            fSchemaDynamicValidation = false;
1293            
1294            // datatype normalization
1295
fEntityRef = false;
1296            fInCDATA = false;
1297            
1298            fMatcherStack.clear();
1299            
1300            
1301            if (!fMayMatchFieldMap.isEmpty()) {
1302                // should only clear this if the last schema had identity constraints.
1303
fMayMatchFieldMap.clear();
1304            }
1305            
1306            // get error reporter
1307
fXSIErrorReporter.reset((XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER));
1308            
1309            boolean parser_settings;
1310            try {
1311                parser_settings = componentManager.getFeature(PARSER_SETTINGS);
1312            }
1313            catch (XMLConfigurationException e){
1314                parser_settings = true;
1315            }
1316            
1317            if (!parser_settings){
1318                // parser settings have not been changed
1319
fValidationManager.addValidationState(fValidationState);
1320                return;
1321            }
1322            
1323            
1324            
1325            // get symbol table. if it's a new one, add symbols to it.
1326
SymbolTable symbolTable = (SymbolTable)componentManager.getProperty(SYMBOL_TABLE);
1327            if (symbolTable != fSymbolTable) {
1328                fSymbolTable = symbolTable;
1329            }
1330            
1331            try {
1332                fDynamicValidation = componentManager.getFeature(DYNAMIC_VALIDATION);
1333            } catch (XMLConfigurationException e) {
1334                fDynamicValidation = false;
1335            }
1336            
1337            if (fDynamicValidation) {
1338                fDoValidation = true;
1339            } else {
1340                try {
1341                    fDoValidation = componentManager.getFeature(VALIDATION);
1342                } catch (XMLConfigurationException e) {
1343                    fDoValidation = false;
1344                }
1345            }
1346            
1347            if (fDoValidation) {
1348                try {
1349                    fDoValidation = componentManager.getFeature(XMLSchemaValidator.SCHEMA_VALIDATION);
1350                } catch (XMLConfigurationException e) {
1351                }
1352            }
1353            
1354            try {
1355                fFullChecking = componentManager.getFeature(SCHEMA_FULL_CHECKING);
1356            } catch (XMLConfigurationException e) {
1357                fFullChecking = false;
1358            }
1359            
1360            try {
1361                fNormalizeData = componentManager.getFeature(NORMALIZE_DATA);
1362            } catch (XMLConfigurationException e) {
1363                fNormalizeData = false;
1364            }
1365            
1366            try {
1367                fSchemaElementDefault = componentManager.getFeature(SCHEMA_ELEMENT_DEFAULT);
1368            } catch (XMLConfigurationException e) {
1369                fSchemaElementDefault = false;
1370            }
1371            
1372            try {
1373                fAugPSVI = componentManager.getFeature(SCHEMA_AUGMENT_PSVI);
1374            } catch (XMLConfigurationException e) {
1375                fAugPSVI = true;
1376            }
1377            try {
1378                fSchemaType =
1379                (String JavaDoc)componentManager.getProperty(Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE);
1380            } catch (XMLConfigurationException e) {
1381                fSchemaType = null;
1382            }
1383            
1384            try {
1385                fIgnoreXsiSchemaLocationHints = componentManager.getFeature(IGNORE_SCHEMA_LOCATION_HINTS);
1386            } catch( XMLConfigurationException e) {
1387                fIgnoreXsiSchemaLocationHints = false;
1388            }
1389            
1390            try {
1391                fTurnIgnorableCharactersIntoIgnorableWhitespaces = componentManager.getFeature(CHANGE_IGNORABLE_CHARACTERS_INTO_IGNORABLE_WHITESPACES);
1392            } catch( XMLConfigurationException e) {
1393                fTurnIgnorableCharactersIntoIgnorableWhitespaces = false;
1394            }
1395            
1396            fEntityResolver = (XMLEntityResolver)componentManager.getProperty(ENTITY_MANAGER);
1397            
1398            fValidationManager = (ValidationManager)componentManager.getProperty(VALIDATION_MANAGER);
1399            fValidationManager.addValidationState(fValidationState);
1400            fValidationState.setSymbolTable(fSymbolTable);
1401            
1402            // get schema location properties
1403
try {
1404                fExternalSchemas = (String JavaDoc)componentManager.getProperty(SCHEMA_LOCATION);
1405                fExternalNoNamespaceSchema = (String JavaDoc)componentManager.getProperty(SCHEMA_NONS_LOCATION);
1406            } catch (XMLConfigurationException e) {
1407                fExternalSchemas = null;
1408                fExternalNoNamespaceSchema = null;
1409            }
1410            
1411            // store the external schema locations. they are set when reset is called,
1412
// so any other schemaLocation declaration for the same namespace will be
1413
// effectively ignored. becuase we choose to take first location hint
1414
// available for a particular namespace.
1415
XMLSchemaLoader.processExternalHints(fExternalSchemas, fExternalNoNamespaceSchema,
1416            fLocationPairs, fXSIErrorReporter.fErrorReporter);
1417            
1418            try {
1419                fJaxpSchemaSource = componentManager.getProperty(JAXP_SCHEMA_SOURCE);
1420            } catch (XMLConfigurationException e){
1421                fJaxpSchemaSource = null;
1422            }
1423            fResourceIdentifier.clear();
1424            
1425            // clear grammars, and put the one for schema namespace there
1426
try {
1427                fGrammarPool = (XMLGrammarPool)componentManager.getProperty(XMLGRAMMAR_POOL);
1428            } catch (XMLConfigurationException e){
1429                fGrammarPool = null;
1430            }
1431            fSchemaLoader.setProperty(XMLGRAMMAR_POOL, fGrammarPool);
1432            
1433            fState4XsiType.setSymbolTable(symbolTable);
1434            fState4ApplyDefault.setSymbolTable(symbolTable);
1435            
1436        } // reset(XMLComponentManager)
1437

1438        //
1439
// FieldActivator methods
1440
//
1441

1442        /**
1443         * Start the value scope for the specified identity constraint. This
1444         * method is called when the selector matches in order to initialize
1445         * the value store.
1446         *
1447         * @param identityConstraint The identity constraint.
1448         */

1449        public void startValueScopeFor(IdentityConstraint identityConstraint, int initialDepth) {
1450            
1451            ValueStoreBase valueStore =
1452            fValueStoreCache.getValueStoreFor(identityConstraint, initialDepth);
1453            valueStore.startValueScope();
1454            
1455        } // startValueScopeFor(IdentityConstraint identityConstraint)
1456

1457        /**
1458         * Request to activate the specified field. This method returns the
1459         * matcher for the field.
1460         *
1461         * @param field The field to activate.
1462         */

1463        public XPathMatcher activateField(Field field, int initialDepth) {
1464            ValueStore valueStore =
1465            fValueStoreCache.getValueStoreFor(field.getIdentityConstraint(), initialDepth);
1466            setMayMatch(field, Boolean.TRUE);
1467            XPathMatcher matcher = field.createMatcher(this, valueStore);
1468            fMatcherStack.addMatcher(matcher);
1469            matcher.startDocumentFragment();
1470            return matcher;
1471        } // activateField(Field):XPathMatcher
1472

1473        /**
1474         * Ends the value scope for the specified identity constraint.
1475         *
1476         * @param identityConstraint The identity constraint.
1477         */

1478        public void endValueScopeFor(IdentityConstraint identityConstraint, int initialDepth) {
1479            
1480            ValueStoreBase valueStore =
1481            fValueStoreCache.getValueStoreFor(identityConstraint, initialDepth);
1482            valueStore.endValueScope();
1483            
1484        } // endValueScopeFor(IdentityConstraint)
1485

1486        /**
1487         * Sets whether the given field is permitted to match a value.
1488         * This should be used to catch instance documents that try
1489         * and match a field several times in the same scope.
1490         *
1491         * @param field The field that may be permitted to be matched.
1492         * @param state Boolean indiciating whether the field may be matched.
1493         */

1494        public void setMayMatch(Field field, Boolean JavaDoc state) {
1495            fMayMatchFieldMap.put(field, state);
1496        } // setMayMatch(Field, Boolean)
1497

1498        /**
1499         * Returns whether the given field is permitted to match a value.
1500         *
1501         * @param field The field that may be permitted to be matched.
1502         * @return Boolean indicating whether the field may be matched.
1503         */

1504        public Boolean JavaDoc mayMatch(Field field) {
1505            return (Boolean JavaDoc) fMayMatchFieldMap.get(field);
1506        } // mayMatch(Field):Boolean
1507

1508        // a utility method for Identity constraints
1509
private void activateSelectorFor(IdentityConstraint ic) {
1510            Selector selector = ic.getSelector();
1511            FieldActivator activator = this;
1512            if (selector == null)
1513                return;
1514            XPathMatcher matcher = selector.createMatcher(activator, fElementDepth);
1515            fMatcherStack.addMatcher(matcher);
1516            matcher.startDocumentFragment();
1517        }
1518        
1519        
1520        //
1521
// Protected methods
1522
//
1523

1524        /** ensure element stack capacity */
1525        void ensureStackCapacity() {
1526            
1527            if (fElementDepth == fElemDeclStack.length) {
1528                int newSize = fElementDepth + INC_STACK_SIZE;
1529                boolean[] newArrayB = new boolean[newSize];
1530                System.arraycopy(fSubElementStack, 0, newArrayB, 0, fElementDepth);
1531                fSubElementStack = newArrayB;
1532                
1533                XSElementDecl[] newArrayE = new XSElementDecl[newSize];
1534                System.arraycopy(fElemDeclStack, 0, newArrayE, 0, fElementDepth);
1535                fElemDeclStack = newArrayE;
1536                
1537                newArrayB = new boolean[newSize];
1538                System.arraycopy(fNilStack, 0, newArrayB, 0, fElementDepth);
1539                fNilStack = newArrayB;
1540                
1541                XSNotationDecl[] newArrayN = new XSNotationDecl[newSize];
1542                System.arraycopy(fNotationStack, 0, newArrayN, 0, fElementDepth);
1543                fNotationStack = newArrayN;
1544                
1545                XSTypeDefinition[] newArrayT = new XSTypeDefinition[newSize];
1546                System.arraycopy(fTypeStack, 0, newArrayT, 0, fElementDepth);
1547                fTypeStack = newArrayT;
1548                
1549                XSCMValidator[] newArrayC = new XSCMValidator[newSize];
1550                System.arraycopy(fCMStack, 0, newArrayC, 0, fElementDepth);
1551                fCMStack = newArrayC;
1552                
1553                newArrayB = new boolean[newSize];
1554                System.arraycopy(fSawTextStack, 0, newArrayB, 0, fElementDepth);
1555                fSawTextStack = newArrayB;
1556                
1557                newArrayB = new boolean[newSize];
1558                System.arraycopy(fStringContent, 0, newArrayB, 0, fElementDepth);
1559                fStringContent = newArrayB;
1560                
1561                newArrayB = new boolean[newSize];
1562                System.arraycopy(fSawChildrenStack, 0, newArrayB, 0, fElementDepth);
1563                fSawChildrenStack = newArrayB;
1564                
1565                newArrayB = new boolean[newSize];
1566                System.arraycopy(fStrictAssessStack, 0, newArrayB, 0, fElementDepth);
1567                fStrictAssessStack = newArrayB;
1568                
1569                int[][] newArrayIA = new int[newSize][];
1570                System.arraycopy(fCMStateStack, 0, newArrayIA, 0, fElementDepth);
1571                fCMStateStack = newArrayIA;
1572            }
1573            
1574        } // ensureStackCapacity
1575

1576        // handle start document
1577
void handleStartDocument(XMLLocator locator, String JavaDoc encoding) {
1578            fValueStoreCache.startDocument();
1579        } // handleStartDocument(XMLLocator,String)
1580

1581        void handleEndDocument() {
1582            fValueStoreCache.endDocument();
1583        } // handleEndDocument()
1584

1585        // handle character contents
1586
// returns the normalized string if possible, otherwise the original string
1587
XMLString handleCharacters(XMLString text) {
1588            
1589            if (fSkipValidationDepth >= 0)
1590                return text;
1591            
1592            fSawText = fSawText || text.length > 0;
1593            
1594            // Note: data in EntityRef and CDATA is normalized as well
1595
// if whitespace == -1 skip normalization, because it is a complexType
1596
// or a union type.
1597
if (fNormalizeData && fWhiteSpace != -1 && fWhiteSpace != XSSimpleType.WS_PRESERVE) {
1598                // normalize data
1599
normalizeWhitespace(text, fWhiteSpace == XSSimpleType.WS_COLLAPSE);
1600                text = fNormalizedStr;
1601            }
1602            if (fAppendBuffer)
1603                fBuffer.append(text.ch, text.offset, text.length);
1604            
1605            // When it's a complex type with element-only content, we need to
1606
// find out whether the content contains any non-whitespace character.
1607
if (fCurrentType != null
1608            && fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
1609                XSComplexTypeDecl ctype = (XSComplexTypeDecl)fCurrentType;
1610                if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
1611                    // data outside of element content
1612
for (int i=text.offset; i< text.offset+text.length; i++) {
1613                        if (!XMLChar.isSpace(text.ch[i])) {
1614                            fSawCharacters = true;
1615                            break;
1616                        }
1617                    }
1618                }
1619            }
1620            
1621            return text;
1622        } // handleCharacters(XMLString)
1623

1624        /**
1625         * Returns true if the current element is expecting only
1626         * ignorable whitespaces as characters.
1627         */

1628        public final boolean isElementOnlyContent() {
1629            if (fCurrentType == null
1630            || fCurrentType.getTypeCategory() != XSTypeDefinition.COMPLEX_TYPE)
1631                return false;
1632            
1633            XSComplexTypeDecl ctype = (XSComplexTypeDecl)fCurrentType;
1634            if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT
1635            || ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_EMPTY )
1636                return !fSawCharacters;
1637            
1638            return false;
1639        }
1640        
1641        /**
1642         * Normalize whitespace in an XMLString according to the rules defined
1643         * in XML Schema specifications.
1644         * @param value The string to normalize.
1645         * @param collapse replace or collapse
1646         */

1647        private void normalizeWhitespace( XMLString value, boolean collapse) {
1648            boolean skipSpace = collapse;
1649            boolean sawNonWS = false;
1650            boolean leading = false;
1651            boolean trailing = false;
1652            char c;
1653            int size = value.offset+value.length;
1654            
1655            // ensure the ch array is big enough
1656
if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < value.length+1) {
1657                fNormalizedStr.ch = new char[value.length+1];
1658            }
1659            // don't include the leading ' ' for now. might include it later.
1660
fNormalizedStr.offset = 1;
1661            fNormalizedStr.length = 1;
1662            
1663            for (int i = value.offset; i < size; i++) {
1664                c = value.ch[i];
1665                if (XMLChar.isSpace(c)) {
1666                    if (!skipSpace) {
1667                        // take the first whitespace as a space and skip the others
1668
fNormalizedStr.ch[fNormalizedStr.length++] = ' ';
1669                        skipSpace = collapse;
1670                    }
1671                    if (!sawNonWS) {
1672                        // this is a leading whitespace, record it
1673
leading = true;
1674                    }
1675                } else {
1676                    fNormalizedStr.ch[fNormalizedStr.length++] = c;
1677                    skipSpace = false;
1678                    sawNonWS = true;
1679                }
1680            }
1681            if (skipSpace) {
1682                if ( fNormalizedStr.length > 1) {
1683                    // if we finished on a space trim it but also record it
1684
fNormalizedStr.length--;
1685                    trailing = true;
1686                } else if (leading && !fFirstChunk) {
1687                    // if all we had was whitespace we skipped record it as
1688
// trailing whitespace as well
1689
trailing = true;
1690                }
1691            }
1692            
1693            if (fNormalizedStr.length > 1) {
1694                if (!fFirstChunk && (fWhiteSpace==XSSimpleType.WS_COLLAPSE) ) {
1695                    if (fTrailing) {
1696                        // previous chunk ended on whitespace
1697
// insert whitespace
1698
fNormalizedStr.offset = 0;
1699                        fNormalizedStr.ch[0] = ' ';
1700                    } else if (leading) {
1701                        // previous chunk ended on character,
1702
// this chunk starts with whitespace
1703
fNormalizedStr.offset = 0;
1704                        fNormalizedStr.ch[0] = ' ';
1705                    }
1706                }
1707            }
1708            
1709            // The length includes the leading ' '. Now removing it.
1710
fNormalizedStr.length -= fNormalizedStr.offset;
1711            
1712            fTrailing = trailing;
1713            
1714            if (trailing || sawNonWS)
1715                fFirstChunk = false;
1716        }
1717        
1718        private void normalizeWhitespace( String JavaDoc value, boolean collapse) {
1719            boolean skipSpace = collapse;
1720            char c;
1721            int size = value.length();
1722            
1723            // ensure the ch array is big enough
1724
if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < size) {
1725                fNormalizedStr.ch = new char[size];
1726            }
1727            fNormalizedStr.offset = 0;
1728            fNormalizedStr.length = 0;
1729            
1730            for (int i = 0; i < size; i++) {
1731                c = value.charAt(i);
1732                if (XMLChar.isSpace(c)) {
1733                    if (!skipSpace) {
1734                        // take the first whitespace as a space and skip the others
1735
fNormalizedStr.ch[fNormalizedStr.length++] = ' ';
1736                        skipSpace = collapse;
1737                    }
1738                } else {
1739                    fNormalizedStr.ch[fNormalizedStr.length++] = c;
1740                    skipSpace = false;
1741                }
1742            }
1743            if (skipSpace) {
1744                if (fNormalizedStr.length != 0)
1745                    // if we finished on a space trim it but also record it
1746
fNormalizedStr.length--;
1747            }
1748        }
1749        
1750        // handle ignorable whitespace
1751
void handleIgnorableWhitespace(XMLString text) {
1752            
1753            if (fSkipValidationDepth >= 0)
1754                return;
1755            
1756            // REVISIT: the same process needs to be performed as handleCharacters.
1757
// only it's simpler here: we know all characters are whitespaces.
1758

1759        } // handleIgnorableWhitespace(XMLString)
1760

1761        /** Handle element. */
1762        Augmentations handleStartElement(QName element, XMLAttributes attributes, Augmentations augs) {
1763            
1764            if (DEBUG) {
1765                System.out.println("==>handleStartElement: " +element);
1766            }
1767            
1768            // root element
1769
if (fElementDepth == -1 && fValidationManager.isGrammarFound()) {
1770                if (fSchemaType == null) {
1771                    // schemaType is not specified
1772
// if a DTD grammar is found, we do the same thing as Dynamic:
1773
// if a schema grammar is found, validation is performed;
1774
// otherwise, skip the whole document.
1775
fSchemaDynamicValidation = true;
1776                } else {
1777                    // [1] Either schemaType is DTD, and in this case validate/schema is turned off
1778
// [2] Validating against XML Schemas only
1779
// [a] dynamic validation is false: report error if SchemaGrammar is not found
1780
// [b] dynamic validation is true: if grammar is not found ignore.
1781
}
1782                
1783            }
1784            
1785            // get xsi:schemaLocation and xsi:noNamespaceSchemaLocation attributes,
1786
// parse them to get the grammars
1787

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

2125        /**
2126         * Handle end element. If there is not text content, and there is a
2127         * {value constraint} on the corresponding element decl, then
2128         * set the fDefaultValue XMLString representing the default value.
2129         */

2130        Augmentations handleEndElement(QName element, Augmentations augs) {
2131            
2132            if (DEBUG) {
2133                System.out.println("==>handleEndElement:" +element);
2134            }
2135            // if we are skipping, return
2136
if (fSkipValidationDepth >= 0) {
2137                // but if this is the top element that we are skipping,
2138
// restore the states.
2139
if (fSkipValidationDepth == fElementDepth && fSkipValidationDepth > 0) {
2140                    // set the partial validation depth to the depth of parent
2141
fNFullValidationDepth = fSkipValidationDepth-1;
2142                    fSkipValidationDepth = -1;
2143                    fElementDepth--;
2144                    fSubElement = fSubElementStack[fElementDepth];
2145                    fCurrentElemDecl = fElemDeclStack[fElementDepth];
2146                    fNil = fNilStack[fElementDepth];
2147                    fNotation = fNotationStack[fElementDepth];
2148                    fCurrentType = fTypeStack[fElementDepth];
2149                    fCurrentCM = fCMStack[fElementDepth];
2150                    fStrictAssess = fStrictAssessStack[fElementDepth];
2151                    fCurrCMState = fCMStateStack[fElementDepth];
2152                    fSawText = fSawTextStack[fElementDepth];
2153                    fSawCharacters = fStringContent[fElementDepth];
2154                    fSawChildren = fSawChildrenStack[fElementDepth];
2155                } else {
2156                    fElementDepth--;
2157                }
2158                
2159                // PSVI: validation attempted:
2160
// use default values in psvi item for
2161
// validation attempted, validity, and error codes
2162

2163                // check extra schema constraints on root element
2164
if (fElementDepth == -1 && fFullChecking) {
2165                    XSConstraints.fullSchemaChecking(
2166                    fGrammarBucket,
2167                    fSubGroupHandler,
2168                    fCMBuilder,
2169                    fXSIErrorReporter.fErrorReporter);
2170                }
2171                
2172                if (fAugPSVI)
2173                    augs = getEmptyAugs(augs);
2174                return augs;
2175            }
2176            
2177            // now validate the content of the element
2178
processElementContent(element);
2179            
2180            // Element Locally Valid (Element)
2181
// 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).
2182

2183            // call matchers and de-activate context
2184
int oldCount = fMatcherStack.getMatcherCount();
2185            for (int i = oldCount - 1; i >= 0; i--) {
2186                XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
2187                if (fCurrentElemDecl == null)
2188                    matcher.endElement(element, null, false, fValidatedInfo.actualValue);
2189                
2190                else
2191                    matcher.endElement(
2192                    element,
2193                    fCurrentType,
2194                    fCurrentElemDecl.getNillable(),
2195                    fDefaultValue == null
2196                    ? fValidatedInfo.actualValue
2197                    : fCurrentElemDecl.fDefault.actualValue);
2198            }
2199            
2200            if (fMatcherStack.size() > 0) {
2201                fMatcherStack.popContext();
2202            }
2203            
2204            int newCount = fMatcherStack.getMatcherCount();
2205            // handle everything *but* keyref's.
2206
for (int i = oldCount - 1; i >= newCount; i--) {
2207                XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
2208                if(matcher instanceof Selector.Matcher) {
2209                    Selector.Matcher selMatcher = (Selector.Matcher)matcher;
2210                    IdentityConstraint id;
2211                    if ((id = selMatcher.getIdentityConstraint()) != null
2212                    && id.getCategory() != IdentityConstraint.IC_KEYREF) {
2213                        fValueStoreCache.transplant(id, selMatcher.getInitialDepth());
2214                    }
2215                }
2216            }
2217            
2218            // now handle keyref's/...
2219
for (int i = oldCount - 1; i >= newCount; i--) {
2220                XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
2221                if(matcher instanceof Selector.Matcher) {
2222                    Selector.Matcher selMatcher = (Selector.Matcher)matcher;
2223                    IdentityConstraint id;
2224                    if ((id = selMatcher.getIdentityConstraint()) != null
2225                    && id.getCategory() == IdentityConstraint.IC_KEYREF) {
2226                        ValueStoreBase values =
2227                        fValueStoreCache.getValueStoreFor(id, selMatcher.getInitialDepth());
2228                        if (values != null) // nothing to do if nothing matched!
2229
values.endDocumentFragment();
2230                    }
2231                }
2232            }
2233            fValueStoreCache.endElement();
2234            
2235            SchemaGrammar[] grammars = null;
2236            // have we reached the end tag of the validation root?
2237
if (fElementDepth == 0) {
2238                // 7 If the element information item is the validation root, it must be valid per Validation Root Valid (ID/IDREF) (3.3.4).
2239
String JavaDoc invIdRef = fValidationState.checkIDRefID();
2240                fValidationState.resetIDTables();
2241                if (invIdRef != null) {
2242                    reportSchemaError("cvc-id.1", new Object JavaDoc[] { invIdRef });
2243                }
2244                // check extra schema constraints
2245
if (fFullChecking) {
2246                    XSConstraints.fullSchemaChecking(
2247                    fGrammarBucket,
2248                    fSubGroupHandler,
2249                    fCMBuilder,
2250                    fXSIErrorReporter.fErrorReporter);
2251                }
2252                
2253                grammars = fGrammarBucket.getGrammars();
2254                // return the final set of grammars validator ended up with
2255
if (fGrammarPool != null) {
2256                    fGrammarPool.cacheGrammars(XMLGrammarDescription.XML_SCHEMA, grammars);
2257                }
2258                augs = endElementPSVI(true, grammars, augs);
2259            } else {
2260                augs = endElementPSVI(false, grammars, augs);
2261                
2262                // decrease element depth and restore states
2263
fElementDepth--;
2264                
2265                // get the states for the parent element.
2266
fSubElement = fSubElementStack[fElementDepth];
2267                fCurrentElemDecl = fElemDeclStack[fElementDepth];
2268                fNil = fNilStack[fElementDepth];
2269                fNotation = fNotationStack[fElementDepth];
2270                fCurrentType = fTypeStack[fElementDepth];
2271                fCurrentCM = fCMStack[fElementDepth];
2272                fStrictAssess = fStrictAssessStack[fElementDepth];
2273                fCurrCMState = fCMStateStack[fElementDepth];
2274                fSawText = fSawTextStack[fElementDepth];
2275                fSawCharacters = fStringContent[fElementDepth];
2276                fSawChildren = fSawChildrenStack[fElementDepth];
2277                
2278                // We should have a stack for whitespace value, and pop it up here.
2279
// But when fWhiteSpace != -1, and we see a sub-element, it must be
2280
// an error (at least for Schema 1.0). So for valid documents, the
2281
// only value we are going to push/pop in the stack is -1.
2282
// Here we just mimic the effect of popping -1. -SG
2283
fWhiteSpace = -1;
2284                // Same for append buffer. Simple types and elements with fixed
2285
// value constraint don't allow sub-elements. -SG
2286
fAppendBuffer = false;
2287                // same here.
2288
fUnionType = false;
2289            }
2290            
2291            return augs;
2292        } // handleEndElement(QName,boolean)*/
2293

2294        final Augmentations endElementPSVI(
2295        boolean root,
2296        SchemaGrammar[] grammars,
2297        Augmentations augs){
2298            
2299            if (fAugPSVI) {
2300                augs = getEmptyAugs(augs);
2301                
2302                // the 4 properties sent on startElement calls
2303
fCurrentPSVI.fDeclaration = this.fCurrentElemDecl;
2304                fCurrentPSVI.fTypeDecl = this.fCurrentType;
2305                fCurrentPSVI.fNotation = this.fNotation;
2306                fCurrentPSVI.fValidationContext = this.fValidationRoot;
2307                // PSVI: validation attempted
2308
// nothing below or at the same level has none or partial
2309
// (which means this level is strictly assessed, and all chidren
2310
// are full), so this one has full
2311
if (fElementDepth > fNFullValidationDepth) {
2312                    fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_FULL;
2313                }
2314                // nothing below or at the same level has full or partial
2315
// (which means this level is not strictly assessed, and all chidren
2316
// are none), so this one has none
2317
else if (fElementDepth > fNNoneValidationDepth) {
2318                    fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_NONE;
2319                }
2320                // otherwise partial, and anything above this level will be partial
2321
else {
2322                    fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_PARTIAL;
2323                    fNFullValidationDepth = fNNoneValidationDepth = fElementDepth - 1;
2324                }
2325                
2326                if (fDefaultValue != null)
2327                    fCurrentPSVI.fSpecified = true;
2328                fCurrentPSVI.fNil = fNil;
2329                fCurrentPSVI.fMemberType = fValidatedInfo.memberType;
2330                fCurrentPSVI.fNormalizedValue = fValidatedInfo.normalizedValue;
2331                fCurrentPSVI.fActualValue = fValidatedInfo.actualValue;
2332                fCurrentPSVI.fActualValueType = fValidatedInfo.actualValueType;
2333                fCurrentPSVI.fItemValueTypes = fValidatedInfo.itemValueTypes;
2334                
2335                if (fStrictAssess) {
2336                    // get all errors for the current element, its attribute,
2337
// and subelements (if they were strictly assessed).
2338
// any error would make this element invalid.
2339
// and we merge these errors to the parent element.
2340
String JavaDoc[] errors = fXSIErrorReporter.mergeContext();
2341                    
2342                    // PSVI: error codes
2343
fCurrentPSVI.fErrorCodes = errors;
2344                    // PSVI: validity
2345
fCurrentPSVI.fValidity =
2346                    (errors == null) ? ElementPSVI.VALIDITY_VALID : ElementPSVI.VALIDITY_INVALID;
2347                } else {
2348                    // PSVI: validity
2349
fCurrentPSVI.fValidity = ElementPSVI.VALIDITY_NOTKNOWN;
2350                    // Discard the current context: ignore any error happened within
2351
// the sub-elements/attributes of this element, because those
2352
// errors won't affect the validity of the parent elements.
2353
fXSIErrorReporter.popContext();
2354                }
2355                
2356                if (root) {
2357                    // store [schema information] in the PSVI
2358
fCurrentPSVI.fSchemaInformation = new XSModelImpl(grammars);
2359                }
2360            }
2361            
2362            return augs;
2363            
2364        }
2365        
2366        Augmentations getEmptyAugs(Augmentations augs) {
2367            if (augs == null) {
2368                augs = fAugmentations;
2369                augs.removeAllItems();
2370            }
2371            augs.putItem(Constants.ELEMENT_PSVI, fCurrentPSVI);
2372            fCurrentPSVI.reset();
2373            
2374            return augs;
2375        }
2376        
2377        void storeLocations(String JavaDoc sLocation, String JavaDoc nsLocation){
2378            if (sLocation != null) {
2379                if (!XMLSchemaLoader.tokenizeSchemaLocationStr(sLocation, fLocationPairs)) {
2380                    // error!
2381
fXSIErrorReporter.reportError(
2382                    XSMessageFormatter.SCHEMA_DOMAIN,
2383                    "SchemaLocation",
2384                    new Object JavaDoc[]{sLocation},
2385                    XMLErrorReporter.SEVERITY_WARNING);
2386                }
2387            }
2388            if (nsLocation != null) {
2389                XMLSchemaLoader.LocationArray la =
2390                ((XMLSchemaLoader.LocationArray) fLocationPairs.get(XMLSymbols.EMPTY_STRING));
2391                if(la == null) {
2392                    la = new XMLSchemaLoader.LocationArray();
2393                    fLocationPairs.put(XMLSymbols.EMPTY_STRING, la);
2394                }
2395                la.addLocation(nsLocation);
2396            }
2397            
2398        }//storeLocations
2399

2400        //this is the function where logic of retrieving grammar is written , parser first tries to get the grammar from
2401
//the local pool, if not in local pool, it gives chance to application to be able to retrieve the grammar, then it
2402
//tries to parse the grammar using location hints from the give namespace.
2403
SchemaGrammar findSchemaGrammar(
2404        short contextType,
2405        String JavaDoc namespace,
2406        QName enclosingElement,
2407        QName triggeringComponet,
2408        XMLAttributes attributes) {
2409            SchemaGrammar grammar = null;
2410            //get the grammar from local pool...
2411
grammar = fGrammarBucket.getGrammar(namespace);
2412            if (grammar == null) {
2413                fXSDDescription.reset();
2414                fXSDDescription.fContextType = contextType;
2415                fXSDDescription.setNamespace(namespace);
2416                fXSDDescription.fEnclosedElementName = enclosingElement;
2417                fXSDDescription.fTriggeringComponent = triggeringComponet;
2418                fXSDDescription.fAttributes = attributes;
2419                if (fLocator != null) {
2420                    fXSDDescription.setBaseSystemId(fLocator.getExpandedSystemId());
2421                }
2422                
2423                String JavaDoc[] temp = null ;
2424                Object JavaDoc locationArray =
2425                fLocationPairs.get(namespace == null ? XMLSymbols.EMPTY_STRING : namespace);
2426                if(locationArray != null)
2427                    temp = ((XMLSchemaLoader.LocationArray)locationArray).getLocationArray() ;
2428                if (temp != null && temp.length != 0) {
2429                    fXSDDescription.fLocationHints = new String JavaDoc [temp.length] ;
2430                    System.arraycopy(temp, 0 , fXSDDescription.fLocationHints, 0, temp.length );
2431                }
2432                
2433                // give a chance to application to be able to retreive the grammar.
2434
if (fGrammarPool != null){
2435                    grammar = (SchemaGrammar)fGrammarPool.retrieveGrammar(fXSDDescription);
2436                    if (grammar != null) {
2437                        // put this grammar into the bucket, along with grammars
2438
// imported by it (directly or indirectly)
2439
if (!fGrammarBucket.putGrammar(grammar, true)) {
2440                            // REVISIT: a conflict between new grammar(s) and grammars
2441
// in the bucket. What to do? A warning? An exception?
2442
fXSIErrorReporter.fErrorReporter.reportError(
2443                            XSMessageFormatter.SCHEMA_DOMAIN,
2444                            "GrammarConflict",
2445                            null,
2446                            XMLErrorReporter.SEVERITY_WARNING);
2447                            grammar = null;
2448                        }
2449                    }
2450                }
2451                if (grammar == null && !fIgnoreXsiSchemaLocationHints) {
2452                    // try to parse the grammar using location hints from that namespace..
2453
try {
2454                        XMLInputSource xis =
2455                        XMLSchemaLoader.resolveDocument(
2456                        fXSDDescription,
2457                        fLocationPairs,
2458                        fEntityResolver);
2459                        grammar = fSchemaLoader.loadSchema(fXSDDescription, xis.toSource(), fLocationPairs);
2460                    } catch (IOException JavaDoc ex) {
2461                        fXSIErrorReporter.fErrorReporter.reportError(
2462                        XSMessageFormatter.SCHEMA_DOMAIN,
2463                        "schema_reference.4",
2464                        new Object JavaDoc[]{fXSDDescription.getLocationHints()[0]},
2465                        XMLErrorReporter.SEVERITY_WARNING);
2466                    }
2467                }
2468            }
2469            
2470            return grammar ;
2471            
2472        }//findSchemaGrammar
2473

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

2478            // Element Locally Valid (Element)
2479
// 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:
2480
// 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);
2481
QName typeName = null;
2482            try {
2483                typeName = (QName)fQNameDV.validate(xsiType, fValidationState, null);
2484            } catch (InvalidDatatypeValueException e) {
2485                reportSchemaError(e.getKey(), e.getArgs());
2486                reportSchemaError(
2487                "cvc-elt.4.1",
2488                new Object JavaDoc[] {
2489                    element.rawname,
2490                    SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_TYPE,
2491                    xsiType });
2492                    return null;
2493            }
2494            
2495            // 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)
2496
XSTypeDefinition type = null;
2497            // if the namespace is schema namespace, first try built-in types
2498
if (typeName.uri == SchemaSymbols.URI_SCHEMAFORSCHEMA) {
2499                type = SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(typeName.localpart);
2500            }
2501            // if it's not schema built-in types, then try to get a grammar
2502
if (type == null) {
2503                //try to find schema grammar by different means....
2504
SchemaGrammar grammar =
2505                findSchemaGrammar(
2506                XSDDescription.CONTEXT_XSITYPE,
2507                typeName.uri,
2508                element,
2509                typeName,
2510                attributes);
2511                
2512                if (grammar != null)
2513                    type = grammar.getGlobalTypeDecl(typeName.localpart);
2514            }
2515            // still couldn't find the type, report an error
2516
if (type == null) {
2517                reportSchemaError("cvc-elt.4.2", new Object JavaDoc[]{element.rawname, xsiType});
2518                return null;
2519            }
2520            
2521            // if there is no current type, set this one as current.
2522
// and we don't need to do extra checking
2523
if (fCurrentType != null) {
2524                // 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).
2525
short block = fCurrentElemDecl.fBlock;
2526                if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE)
2527                    block |= ((XSComplexTypeDecl)fCurrentType).fBlock;
2528                if (!XSConstraints.checkTypeDerivationOk(type, fCurrentType, block))
2529                    reportSchemaError(
2530                    "cvc-elt.4.3",
2531                    new Object JavaDoc[] { element.rawname, xsiType, fCurrentType.getName()});
2532            }
2533            
2534            return type;
2535        }//getAndCheckXsiType
2536

2537        boolean getXsiNil(QName element, String JavaDoc xsiNil) {
2538            // Element Locally Valid (Element)
2539
// 3 The appropriate case among the following must be true:
2540
// 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.
2541
if (fCurrentElemDecl != null && !fCurrentElemDecl.getNillable()) {
2542                reportSchemaError(
2543                "cvc-elt.3.1",
2544                new Object JavaDoc[] {
2545                    element.rawname,
2546                    SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_NIL });
2547            }
2548            // 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:
2549
// 3.2.2 There must be no fixed {value constraint}.
2550
else {
2551                String JavaDoc value = xsiNil.trim();
2552                if (value.equals(SchemaSymbols.ATTVAL_TRUE)
2553                || value.equals(SchemaSymbols.ATTVAL_TRUE_1)) {
2554                    if (fCurrentElemDecl != null
2555                    && fCurrentElemDecl.getConstraintType() == XSConstants.VC_FIXED) {
2556                        reportSchemaError(
2557                        "cvc-elt.3.2.2",
2558                        new Object JavaDoc[] {
2559                            element.rawname,
2560                            SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_NIL });
2561                    }
2562                    return true;
2563                }
2564            }
2565            return false;
2566        }
2567        
2568        void processAttributes(QName element, XMLAttributes attributes, XSAttributeGroupDecl attrGrp) {
2569            
2570            if (DEBUG) {
2571                System.out.println("==>processAttributes: " +attributes.getLength());
2572            }
2573            
2574            // whether we have seen a Wildcard ID.
2575
String JavaDoc wildcardIDName = null;
2576            
2577            // for each present attribute
2578
int attCount = attributes.getLength();
2579            
2580            Augmentations augs = null;
2581            AttributePSVImpl attrPSVI = null;
2582            
2583            boolean isSimple =
2584            fCurrentType == null || fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE;
2585            
2586            XSObjectList attrUses = null;
2587            int useCount = 0;
2588            XSWildcardDecl attrWildcard = null;
2589            if (!isSimple) {
2590                attrUses = attrGrp.getAttributeUses();
2591                useCount = attrUses.getLength();
2592                attrWildcard = attrGrp.fAttributeWC;
2593            }
2594            
2595            // Element Locally Valid (Complex Type)
2596
// 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:
2597
// get the corresponding attribute decl
2598
for (int index = 0; index < attCount; index++) {
2599                
2600                attributes.getName(index, fTempQName);
2601                
2602                if (DEBUG) {
2603                    System.out.println("==>process attribute: "+fTempQName);
2604                }
2605                
2606                if (fAugPSVI || fIdConstraint) {
2607                    augs = attributes.getAugmentations(index);
2608                    attrPSVI = (AttributePSVImpl) augs.getItem(Constants.ATTRIBUTE_PSVI);
2609                    if (attrPSVI != null) {
2610                        attrPSVI.reset();
2611                    } else {
2612                        attrPSVI= new AttributePSVImpl();
2613                        augs.putItem(Constants.ATTRIBUTE_PSVI, attrPSVI);
2614                    }
2615                    // PSVI attribute: validation context
2616
attrPSVI.fValidationContext = fValidationRoot;
2617                }
2618                
2619                // Element Locally Valid (Type)
2620
// 3.1.1 The element information item's [attributes] must be empty, excepting those
2621
// whose [namespace name] is identical to http://www.w3.org/2001/XMLSchema-instance and
2622
// whose [local name] is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
2623

2624                // for the 4 xsi attributes, get appropriate decl, and validate
2625
if (fTempQName.uri == SchemaSymbols.URI_XSI) {
2626                    XSAttributeDecl attrDecl = null;
2627                    if (fTempQName.localpart == SchemaSymbols.XSI_SCHEMALOCATION)
2628                        attrDecl =
2629                        SchemaGrammar.SG_XSI.getGlobalAttributeDecl(
2630                        SchemaSymbols.XSI_SCHEMALOCATION);
2631                    else if (fTempQName.localpart == SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION)
2632                        attrDecl =
2633                        SchemaGrammar.SG_XSI.getGlobalAttributeDecl(
2634                        SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION);
2635                    else if (fTempQName.localpart == SchemaSymbols.XSI_NIL)
2636                        attrDecl = SchemaGrammar.SG_XSI.getGlobalAttributeDecl(SchemaSymbols.XSI_NIL);
2637                    else if (fTempQName.localpart == SchemaSymbols.XSI_TYPE)
2638                        attrDecl = SchemaGrammar.SG_XSI.getGlobalAttributeDecl(SchemaSymbols.XSI_TYPE);
2639                    if (attrDecl != null) {
2640                        processOneAttribute(element, attributes, index, attrDecl, null, attrPSVI);
2641                        continue;
2642                    }
2643                }
2644                
2645                // for namespace attributes, no_validation/unknow_validity
2646
if (fTempQName.rawname == XMLSymbols.PREFIX_XMLNS
2647                || fTempQName.rawname.startsWith("xmlns:")) {
2648                    continue;
2649                }
2650                
2651                // simple type doesn't allow any other attributes
2652
if (isSimple) {
2653                    reportSchemaError(
2654                    "cvc-type.3.1.1",
2655                    new Object JavaDoc[] { element.rawname, fTempQName.rawname });
2656                    continue;
2657                }
2658                
2659                // it's not xmlns, and not xsi, then we need to find a decl for it
2660
XSAttributeUseImpl currUse = null, oneUse;
2661                for (int i = 0; i < useCount; i++) {
2662                    oneUse = (XSAttributeUseImpl)attrUses.item(i);
2663                    if (oneUse.fAttrDecl.fName == fTempQName.localpart
2664                    && oneUse.fAttrDecl.fTargetNamespace == fTempQName.uri) {
2665                        currUse = oneUse;
2666                        break;
2667                    }
2668                }
2669                
2670                // 3.2 otherwise all of the following must be true:
2671
// 3.2.1 There must be an {attribute wildcard}.
2672
// 3.2.2 The attribute information item must be valid with respect to it as defined in Item Valid (Wildcard) (3.10.4).
2673

2674                // if failed, get it from wildcard
2675
if (currUse == null) {
2676                    //if (attrWildcard == null)
2677
// reportSchemaError("cvc-complex-type.3.2.1", new Object[]{element.rawname, fTempQName.rawname});
2678
if (attrWildcard == null || !attrWildcard.allowNamespace(fTempQName.uri)) {
2679                        // so this attribute is not allowed
2680
reportSchemaError(
2681                        "cvc-complex-type.3.2.2",
2682                        new Object JavaDoc[] { element.rawname, fTempQName.rawname });
2683                        continue;
2684                    }
2685                }
2686                
2687                XSAttributeDecl currDecl = null;
2688                if (currUse != null) {
2689                    currDecl = currUse.fAttrDecl;
2690                } else {
2691                    // which means it matches a wildcard
2692
// skip it if processContents is skip
2693
if (attrWildcard.fProcessContents == XSWildcardDecl.PC_SKIP)
2694                        continue;
2695                    
2696                    //try to find grammar by different means...
2697
SchemaGrammar grammar =
2698                    findSchemaGrammar(
2699                    XSDDescription.CONTEXT_ATTRIBUTE,
2700                    fTempQName.uri,
2701                    element,
2702                    fTempQName,
2703                    attributes);
2704                    
2705                    if (grammar != null){
2706                        currDecl = grammar.getGlobalAttributeDecl(fTempQName.localpart);
2707                    }
2708                    
2709                    // if can't find
2710
if (currDecl == null) {
2711                        // if strict, report error
2712
if (attrWildcard.fProcessContents == XSWildcardDecl.PC_STRICT){
2713                            reportSchemaError(
2714                            "cvc-complex-type.3.2.2",
2715                            new Object JavaDoc[] { element.rawname, fTempQName.rawname });
2716                        }
2717                        
2718                        // then continue to the next attribute
2719
continue;
2720                    } else {
2721                        // 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:
2722
// 5.1 There must be no more than one item in wild IDs.
2723
if (currDecl.fType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE
2724                        && ((XSSimpleType) currDecl.fType).isIDType()) {
2725                            if (wildcardIDName != null){
2726                                reportSchemaError(
2727                                "cvc-complex-type.5.1",
2728                                new Object JavaDoc[] { element.rawname, currDecl.fName, wildcardIDName });
2729                            } else
2730                                wildcardIDName = currDecl.fName;
2731                        }
2732                    }
2733                }
2734                
2735                processOneAttribute(element, attributes, index, currDecl, currUse, attrPSVI);
2736            } // end of for (all attributes)
2737

2738            // 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.
2739
if (!isSimple && attrGrp.fIDAttrName != null && wildcardIDName != null){
2740                reportSchemaError(
2741                "cvc-complex-type.5.2",
2742                new Object JavaDoc[] { element.rawname, wildcardIDName, attrGrp.fIDAttrName });
2743            }
2744            
2745        } //processAttributes
2746

2747        void processOneAttribute(
2748        QName element,
2749        XMLAttributes attributes,
2750        int index,
2751        XSAttributeDecl currDecl,
2752        XSAttributeUseImpl currUse,
2753        AttributePSVImpl attrPSVI) {
2754            
2755            String JavaDoc attrValue = attributes.getValue(index);
2756            fXSIErrorReporter.pushContext();
2757            
2758            // Attribute Locally Valid
2759
// For an attribute information item to be locally valid with respect to an attribute declaration all of the following must be true:
2760
// 1 The declaration must not be absent (see Missing Sub-components (5.3) for how this can fail to be the case).
2761
// 2 Its {type definition} must not be absent.
2762
// 3 The item's normalized value must be locally valid with respect to that {type definition} as per String Valid (3.14.4).
2763
// get simple type
2764
XSSimpleType attDV = currDecl.fType;
2765            
2766            Object JavaDoc actualValue = null;
2767            try {
2768                actualValue = attDV.validate(attrValue, fValidationState, fValidatedInfo);
2769                // store the normalized value
2770
if (fNormalizeData)
2771                    attributes.setValue(index, fValidatedInfo.normalizedValue);
2772                
2773                Augmentations augs = attributes.getAugmentations(index);
2774                
2775                XSSimpleType effectiveType = fValidatedInfo.memberType != null
2776                ? fValidatedInfo.memberType : attDV;
2777                
2778                augs.putItem(Constants.ID_ATTRIBUTE,
2779                effectiveType.isIDType()?Boolean.TRUE:Boolean.FALSE );
2780                augs.putItem(Constants.TYPEINFO, effectiveType );
2781                
2782                // PSVI: element notation
2783
if (attDV.getVariety() == XSSimpleType.VARIETY_ATOMIC &&
2784                attDV.getPrimitiveKind() == XSSimpleType.PRIMITIVE_NOTATION){
2785                    QName qName = (QName)actualValue;
2786                    SchemaGrammar grammar = fGrammarBucket.getGrammar(qName.uri);
2787                    
2788                    //REVISIT: is it possible for the notation to be in different namespace than the attribute
2789
//with which it is associated, CHECK !! <fof n1:att1 = "n2:notation1" ..>
2790
// should we give chance to the application to be able to retrieve a grammar - nb
2791
//REVISIT: what would be the triggering component here.. if it is attribute value that
2792
// triggered the loading of grammar ?? -nb
2793

2794                    if (grammar != null) {
2795                        fNotation = grammar.getGlobalNotationDecl(qName.localpart);
2796                    }
2797                }
2798            } catch (InvalidDatatypeValueException idve) {
2799                reportSchemaError(idve.getKey(), idve.getArgs());
2800                reportSchemaError(
2801                "cvc-attribute.3",
2802                new Object JavaDoc[] { element.rawname, fTempQName.rawname, attrValue, attDV.getName()});
2803            }
2804            
2805            // get the value constraint from use or decl
2806
// 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
2807
if (actualValue != null && currDecl.getConstraintType() == XSConstants.VC_FIXED) {
2808                if (!actualValue.equals(currDecl.fDefault.actualValue)){
2809                    reportSchemaError(
2810                    "cvc-attribute.4",
2811                    new Object JavaDoc[] {
2812                        element.rawname,
2813                        fTempQName.rawname,
2814                        attrValue,
2815                        currDecl.fDefault.stringValue()});
2816                }
2817            }
2818            
2819            // 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).
2820
if (actualValue != null
2821            && currUse != null
2822            && currUse.fConstraintType == XSConstants.VC_FIXED) {
2823                if (!actualValue.equals(currUse.fDefault.actualValue)){
2824                    reportSchemaError(
2825                    "cvc-complex-type.3.1",
2826                    new Object JavaDoc[] {
2827                        element.rawname,
2828                        fTempQName.rawname,
2829                        attrValue,
2830                        currUse.fDefault.stringValue()});
2831                }
2832            }
2833            if (fIdConstraint) {
2834                attrPSVI.fActualValue = actualValue;
2835            }
2836            
2837            if (fAugPSVI) {
2838                // PSVI: attribute declaration
2839
attrPSVI.fDeclaration = currDecl;
2840                // PSVI: attribute type
2841
attrPSVI.fTypeDecl = attDV;
2842                
2843                // PSVI: attribute memberType
2844
attrPSVI.fMemberType = fValidatedInfo.memberType;
2845                // PSVI: attribute normalized value
2846
// NOTE: we always store the normalized value, even if it's invlid,
2847
// because it might still be useful to the user. But when the it's
2848
// not valid, the normalized value is not trustable.
2849
attrPSVI.fNormalizedValue = fValidatedInfo.normalizedValue;
2850                attrPSVI.fActualValue = fValidatedInfo.actualValue;
2851                attrPSVI.fActualValueType = fValidatedInfo.actualValueType;
2852                attrPSVI.fItemValueTypes = fValidatedInfo.itemValueTypes;
2853                
2854                
2855                
2856                // PSVI: validation attempted:
2857
attrPSVI.fValidationAttempted = AttributePSVI.VALIDATION_FULL;
2858                
2859                String JavaDoc[] errors = fXSIErrorReporter.mergeContext();
2860                // PSVI: error codes
2861
attrPSVI.fErrorCodes = errors;
2862                // PSVI: validity
2863
attrPSVI.fValidity =
2864                (errors == null) ? AttributePSVI.VALIDITY_VALID : AttributePSVI.VALIDITY_INVALID;
2865            }
2866        }
2867        
2868        void addDefaultAttributes(
2869        QName element,
2870        XMLAttributes attributes,
2871        XSAttributeGroupDecl attrGrp) {
2872            // Check after all specified attrs are scanned
2873
// (1) report error for REQUIRED attrs that are missing (V_TAGc)
2874
// REVISIT: should we check prohibited attributes?
2875
// (2) report error for PROHIBITED attrs that are present (V_TAGc)
2876
// (3) add default attrs (FIXED and NOT_FIXED)
2877
//
2878
if (DEBUG) {
2879                System.out.println("==>addDefaultAttributes: " + element);
2880            }
2881            XSObjectList attrUses = attrGrp.getAttributeUses();
2882            int useCount = attrUses.getLength();
2883            XSAttributeUseImpl currUse;
2884            XSAttributeDecl currDecl;
2885            short constType;
2886            ValidatedInfo defaultValue;
2887            boolean isSpecified;
2888            QName attName;
2889            // for each attribute use
2890
for (int i = 0; i < useCount; i++) {
2891                
2892                currUse = (XSAttributeUseImpl)attrUses.item(i);
2893                currDecl = currUse.fAttrDecl;
2894                // get value constraint
2895
constType = currUse.fConstraintType;
2896                defaultValue = currUse.fDefault;
2897                if (constType == XSConstants.VC_NONE) {
2898                    constType = currDecl.getConstraintType();
2899                    defaultValue = currDecl.fDefault;
2900                }
2901                // whether this attribute is specified
2902
isSpecified = attributes.getValue(currDecl.fTargetNamespace, currDecl.fName) != null;
2903                
2904                // Element Locally Valid (Complex Type)
2905
// 4 The {attribute declaration} of each attribute use in the {attribute uses} whose
2906
// {required} is true matches one of the attribute information items in the element
2907
// information item's [attributes] as per clause 3.1 above.
2908
if (currUse.fUse == SchemaSymbols.USE_REQUIRED) {
2909                    if (!isSpecified)
2910                        reportSchemaError("cvc-complex-type.4", new Object JavaDoc[]{element.rawname, currDecl.fName});
2911                }
2912                // if the attribute is not specified, then apply the value constraint
2913
if (!isSpecified && constType != XSConstants.VC_NONE) {
2914                    attName = new QName(null, currDecl.fName, currDecl.fName, currDecl.fTargetNamespace);
2915                    String JavaDoc normalized = (defaultValue!=null)?defaultValue.stringValue():"";
2916                    int attrIndex = attributes.addAttribute(attName, "CDATA", normalized);
2917                    
2918                    Augmentations augs = attributes.getAugmentations(attrIndex);
2919                    
2920                    XSSimpleType effectiveType = defaultValue.memberType!=null
2921                    ? defaultValue.memberType : currDecl.fType;
2922                    
2923                    augs.putItem(Constants.ID_ATTRIBUTE,
2924                    effectiveType.isIDType()?Boolean.TRUE:Boolean.FALSE );
2925                    augs.putItem(Constants.TYPEINFO,effectiveType);
2926                    
2927                    if (fAugPSVI) {
2928                        
2929                        // PSVI: attribute is "schema" specified
2930
AttributePSVImpl attrPSVI = new AttributePSVImpl();
2931                        augs.putItem(Constants.ATTRIBUTE_PSVI, attrPSVI);
2932                        
2933                        attrPSVI.fDeclaration = currDecl;
2934                        attrPSVI.fTypeDecl = currDecl.fType;
2935                        attrPSVI.fMemberType = defaultValue.memberType;
2936                        attrPSVI.fNormalizedValue = normalized;
2937                        attrPSVI.fActualValue = defaultValue.actualValue;
2938                        attrPSVI.fActualValueType = defaultValue.actualValueType;
2939                        attrPSVI.fItemValueTypes = defaultValue.itemValueTypes;
2940                        attrPSVI.fValidationContext = fValidationRoot;
2941                        attrPSVI.fValidity = AttributePSVI.VALIDITY_VALID;
2942                        attrPSVI.fValidationAttempted = AttributePSVI.VALIDATION_FULL;
2943                        attrPSVI.fSpecified = true;
2944                    }
2945                }
2946                
2947            } // for
2948
} // addDefaultAttributes
2949

2950        /**
2951         * If there is not text content, and there is a
2952         * {value constraint} on the corresponding element decl, then return
2953         * an XMLString representing the default value.
2954         */

2955        void processElementContent(QName element) {
2956            // 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.
2957
if (fCurrentElemDecl != null
2958            && fCurrentElemDecl.fDefault != null
2959            && !fSawText
2960            && !fSubElement
2961            && !fNil) {
2962                
2963                String JavaDoc strv = fCurrentElemDecl.fDefault.stringValue();
2964                int bufLen = strv.length();
2965                if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < bufLen) {
2966                    fNormalizedStr.ch = new char[bufLen];
2967                }
2968                strv.getChars(0, bufLen, fNormalizedStr.ch, 0);
2969                fNormalizedStr.offset = 0;
2970                fNormalizedStr.length = bufLen;
2971                fDefaultValue = fNormalizedStr;
2972            }
2973            // fixed values are handled later, after xsi:type determined.
2974

2975            fValidatedInfo.normalizedValue = null;
2976            
2977            // Element Locally Valid (Element)
2978
// 3.2.1 The element information item must have no character or element information item [children].
2979
if (fNil) {
2980                if (fSubElement || fSawText){
2981                    reportSchemaError(
2982                    "cvc-elt.3.2.1",
2983                    new Object JavaDoc[] {
2984                        element.rawname,
2985                        SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_NIL });
2986                }
2987            }
2988            
2989            this.fValidatedInfo.reset();
2990            
2991            // 5 The appropriate case among the following must be true:
2992
// 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:
2993
if (fCurrentElemDecl != null
2994            && fCurrentElemDecl.getConstraintType() != XSConstants.VC_NONE
2995            && !fSubElement
2996            && !fSawText
2997            && !fNil) {
2998                // 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).
2999
if (fCurrentType != fCurrentElemDecl.fType) {
3000                    //REVISIT:we should pass ValidatedInfo here.
3001
if (XSConstraints
3002                    .ElementDefaultValidImmediate(
3003                    fCurrentType,
3004                    fCurrentElemDecl.fDefault.stringValue(),
3005                    fState4XsiType,
3006                    null)
3007                    == null)
3008                        reportSchemaError(
3009                        "cvc-elt.5.1.1",
3010                        new Object JavaDoc[] {
3011                            element.rawname,
3012                            fCurrentType.getName(),
3013                            fCurrentElemDecl.fDefault.stringValue()});
3014                }
3015                // 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).
3016
// REVISIT: don't use toString, but validateActualValue instead
3017
// use the fState4ApplyDefault
3018
elementLocallyValidType(element, fCurrentElemDecl.fDefault.stringValue());
3019            } else {
3020                // The following method call also deal with clause 1.2.2 of the constraint
3021
// Validation Rule: Schema-Validity Assessment (Element)
3022

3023                // 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:
3024
// 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).
3025
Object JavaDoc actualValue = elementLocallyValidType(element, fBuffer);
3026                // 5.2.2 If there is a fixed {value constraint} and clause 3.2 has not applied, all of the following must be true:
3027
if (fCurrentElemDecl != null
3028                && fCurrentElemDecl.getConstraintType() == XSConstants.VC_FIXED
3029                && !fNil) {
3030                    String JavaDoc content = fBuffer.toString();
3031                    // 5.2.2.1 The element information item must have no element information item [children].
3032
if (fSubElement)
3033                        reportSchemaError("cvc-elt.5.2.2.1", new Object JavaDoc[]{element.rawname});
3034                        // 5.2.2.2 The appropriate case among the following must be true:
3035
if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
3036                            XSComplexTypeDecl ctype = (XSComplexTypeDecl)fCurrentType;
3037                            // 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.
3038
if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
3039                                // REVISIT: how to get the initial value, does whiteSpace count?
3040
if (!fCurrentElemDecl.fDefault.normalizedValue.equals(content))
3041                                    reportSchemaError(
3042                                    "cvc-elt.5.2.2.2.1",
3043                                    new Object JavaDoc[] {
3044                                        element.rawname,
3045                                        content,
3046                                        fCurrentElemDecl.fDefault.normalizedValue });
3047                            }
3048                            // 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.
3049
else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
3050                                if (actualValue != null
3051                                && !actualValue.equals(fCurrentElemDecl.fDefault.actualValue))
3052                                    reportSchemaError(
3053                                    "cvc-elt.5.2.2.2.2",
3054                                    new Object JavaDoc[] {
3055                                        element.rawname,
3056                                        content,
3057                                        fCurrentElemDecl.fDefault.stringValue()});
3058                            }
3059                        } else if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
3060                            if (actualValue != null
3061                            && !actualValue.equals(fCurrentElemDecl.fDefault.actualValue))
3062                                // REVISIT: the spec didn't mention this case: fixed
3063
// value with simple type
3064
reportSchemaError(
3065                                "cvc-elt.5.2.2.2.2",
3066                                new Object JavaDoc[] {
3067                                    element.rawname,
3068                                    content,
3069                                    fCurrentElemDecl.fDefault.stringValue()});
3070                        }
3071                }
3072            }
3073            
3074            if (fDefaultValue == null && fNormalizeData && fDocumentHandler != null && fUnionType) {
3075                // for union types we need to send data because we delayed sending
3076
// this data when we received it in the characters() call.
3077
String JavaDoc content = fValidatedInfo.normalizedValue;
3078                if (content == null)
3079                    content = fBuffer.toString();
3080                
3081                int bufLen = content.length();
3082                if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < bufLen) {
3083                    fNormalizedStr.ch = new char[bufLen];
3084                }
3085                content.getChars(0, bufLen, fNormalizedStr.ch, 0);
3086                fNormalizedStr.offset = 0;
3087                fNormalizedStr.length = bufLen;
3088                fDocumentHandler.characters(fNormalizedStr, null);
3089            }
3090        } // processElementContent
3091

3092        Object JavaDoc elementLocallyValidType(QName element, Object JavaDoc textContent) {
3093            if (fCurrentType == null)
3094                return null;
3095            
3096            Object JavaDoc retValue = null;
3097            // Element Locally Valid (Type)
3098
// 3 The appropriate case among the following must be true:
3099
// 3.1 If the type definition is a simple type definition, then all of the following must be true:
3100
if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
3101                // 3.1.2 The element information item must have no element information item [children].
3102
if (fSubElement)
3103                    reportSchemaError("cvc-type.3.1.2", new Object JavaDoc[]{element.rawname});
3104                    // 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).
3105
if (!fNil) {
3106                        XSSimpleType dv = (XSSimpleType)fCurrentType;
3107                        try {
3108                            if (!fNormalizeData || fUnionType) {
3109                                fValidationState.setNormalizationRequired(true);
3110                            }
3111                            retValue = dv.validate(textContent, fValidationState, fValidatedInfo);
3112                        } catch (InvalidDatatypeValueException e) {
3113                            reportSchemaError(e.getKey(), e.getArgs());
3114                            reportSchemaError(
3115                            "cvc-type.3.1.3",
3116                            new Object JavaDoc[] { element.rawname, textContent });
3117                        }
3118                    }
3119            } else {
3120                // 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);
3121
retValue = elementLocallyValidComplexType(element, textContent);
3122            }
3123            
3124            return retValue;
3125        } // elementLocallyValidType
3126

3127        Object JavaDoc elementLocallyValidComplexType(QName element, Object JavaDoc textContent) {
3128            Object JavaDoc actualValue = null;
3129            XSComplexTypeDecl ctype = (XSComplexTypeDecl)fCurrentType;
3130            
3131            // Element Locally Valid (Complex Type)
3132
// For an element information item to be locally valid with respect to a complex type definition all of the following must be true:
3133
// 1 {abstract} is false.
3134
// 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:
3135
if (!fNil) {
3136                // 2.1 If the {content type} is empty, then the element information item has no character or element information item [children].
3137
if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_EMPTY
3138                && (fSubElement || fSawText || fSawChildren)) {
3139                    reportSchemaError("cvc-complex-type.2.1", new Object JavaDoc[]{element.rawname});
3140                }
3141                // 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).
3142
else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
3143                    if (fSubElement)
3144                        reportSchemaError("cvc-complex-type.2.2", new Object JavaDoc[]{element.rawname});
3145                        XSSimpleType dv = ctype.fXSSimpleType;
3146                        try {
3147                            if (!fNormalizeData || fUnionType) {
3148                                fValidationState.setNormalizationRequired(true);
3149                            }
3150                            actualValue = dv.validate(textContent, fValidationState, fValidatedInfo);
3151                        } catch (InvalidDatatypeValueException e) {
3152                            reportSchemaError(e.getKey(), e.getArgs());
3153                            reportSchemaError("cvc-complex-type.2.2", new Object JavaDoc[]{element.rawname});
3154                        }
3155                        // REVISIT: eventually, this method should return the same actualValue as elementLocallyValidType...
3156
// obviously it'll return null when the content is complex.
3157
}
3158                // 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)].
3159
else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
3160                    if (fSawCharacters) {
3161                        reportSchemaError("cvc-complex-type.2.3", new Object JavaDoc[]{element.rawname});
3162                    }
3163                }
3164                // 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).
3165
if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT
3166                || ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
3167                    // if the current state is a valid state, check whether
3168
// it's one of the final states.
3169
if (DEBUG) {
3170                        System.out.println(fCurrCMState);
3171                    }
3172                    if (fCurrCMState[0] >= 0 && !fCurrentCM.endContentModel(fCurrCMState)) {
3173                        String JavaDoc expected = expectedStr(fCurrentCM.whatCanGoHere(fCurrCMState));
3174                        reportSchemaError(
3175                        "cvc-complex-type.2.4.b",
3176                        new Object JavaDoc[] { element.rawname, expected });
3177                    }
3178                }
3179            }
3180            return actualValue;
3181        } // elementLocallyValidComplexType
3182

3183        public void reportSchemaError(String JavaDoc key, Object JavaDoc[] arguments) {
3184            if (fDoValidation)
3185                fXSIErrorReporter.reportError(
3186                XSMessageFormatter.SCHEMA_DOMAIN,
3187                key,
3188                arguments,
3189                XMLErrorReporter.SEVERITY_ERROR);
3190        }
3191        
3192        private String JavaDoc expectedStr(Vector JavaDoc expected) {
3193            StringBuffer JavaDoc ret = new StringBuffer JavaDoc("{");
3194            int size = expected.size();
3195            for (int i = 0; i < size; i++) {
3196                if (i > 0)
3197                    ret.append(", ");
3198                ret.append(expected.elementAt(i).toString());
3199            }
3200            ret.append('}');
3201            return ret.toString();
3202        }
3203        
3204        /**********************************/
3205        
3206        // xpath matcher information
3207

3208        /**
3209         * Stack of XPath matchers for identity constraints.
3210         *
3211         * @author Andy Clark, IBM
3212         */

3213        protected static class XPathMatcherStack {
3214            
3215            //
3216
// Data
3217
//
3218

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

3232            public XPathMatcherStack() {
3233            } // <init>()
3234

3235            //
3236
// Public methods
3237
//
3238

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

3248            /** Returns the size of the stack. */
3249            public int size() {
3250                return fContextStack.size();
3251            } // size():int
3252

3253            /** Returns the count of XPath matchers. */
3254            public int getMatcherCount() {
3255                return fMatchersCount;
3256            } // getMatcherCount():int
3257

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

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

3269            /** Pushes a new context onto the stack. */
3270            public void pushContext() {
3271                fContextStack.push(fMatchersCount);
3272            } // pushContext()
3273

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

3279            //
3280
// Private methods
3281
//
3282

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

3292        } // class XPathMatcherStack
3293

3294        // value store implementations
3295

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

3302        protected abstract class ValueStoreBase implements ValueStore {
3303            
3304            //
3305
// Data
3306
//
3307

3308            /** Identity constraint. */
3309            protected IdentityConstraint fIdentityConstraint;
3310            protected int fFieldCount = 0;
3311            protected Field[] fFields = null;
3312            /** current data */
3313            protected Object JavaDoc[] fLocalValues = null;
3314            protected Object JavaDoc[] fLocalValueTypes = null;
3315            
3316            /** Current data value count. */
3317            protected int fValuesCount;
3318            
3319            /** global data */
3320            public final Vector JavaDoc fValues = new Vector JavaDoc();
3321            public final Vector JavaDoc fValueTypes = new Vector JavaDoc();
3322            
3323            /** buffer for error messages */
3324            final StringBuffer JavaDoc fTempBuffer = new StringBuffer JavaDoc();
3325            
3326            //
3327
// Constructors
3328
//
3329

3330            /** Constructs a value store for the specified identity constraint. */
3331            protected ValueStoreBase(IdentityConstraint identityConstraint) {
3332                fIdentityConstraint = identityConstraint;
3333                fFieldCount = fIdentityConstraint.getFieldCount();
3334                fFields = new Field[fFieldCount];
3335                fLocalValues = new Object JavaDoc[fFieldCount];
3336                fLocalValueTypes = new Object JavaDoc[fFieldCount];
3337                for (int i = 0; i < fFieldCount; i++) {
3338                    fFields[i] = fIdentityConstraint.getFieldAt(i);
3339                }
3340            } // <init>(IdentityConstraint)
3341

3342            //
3343
// Public methods
3344
//
3345

3346            // destroys this ValueStore; useful when, for instance, a
3347
// locally-scoped ID constraint is involved.
3348
public void clear() {
3349                fValuesCount = 0;
3350                fValues.setSize(0);
3351                fValueTypes.setSize(0);
3352            } // end clear():void
3353

3354            // appends the contents of one ValueStore to those of us.
3355
public void append(ValueStoreBase newVal) {
3356                for (int i = 0; i < newVal.fValues.size(); i++) {
3357                    fValues.addElement(newVal.fValues.elementAt(i));
3358                    fValueTypes.addElement(newVal.fValueTypes.elementAt(i));
3359                }
3360            } // append(ValueStoreBase)
3361

3362            /** Start scope for value store. */
3363            public void startValueScope() {
3364                fValuesCount = 0;
3365                for (int i = 0; i < fFieldCount; i++) {
3366                    fLocalValues[i] = null;
3367                    fLocalValueTypes[i] = null;
3368                }
3369            } // startValueScope()
3370

3371            /** Ends scope for value store. */
3372            public void endValueScope() {
3373                
3374                if (fValuesCount == 0) {
3375                    if (fIdentityConstraint.getCategory() == IdentityConstraint.IC_KEY) {
3376                        String JavaDoc code = "AbsentKeyValue";
3377                        String JavaDoc eName = fIdentityConstraint.getElementName();
3378                        reportSchemaError(code, new Object JavaDoc[] { eName });
3379                    }
3380                    return;
3381                }
3382                
3383                // do we have enough values?
3384
if (fValuesCount != fFieldCount) {
3385                    switch (fIdentityConstraint.getCategory()) {
3386                        case IdentityConstraint.IC_UNIQUE : {
3387                            String JavaDoc code = "UniqueNotEnoughValues";
3388                            String JavaDoc ename = fIdentityConstraint.getElementName();
3389                            reportSchemaError(code, new Object JavaDoc[] { ename });
3390                            break;
3391                        }
3392                        case IdentityConstraint.IC_KEY : {
3393                            String JavaDoc code = "KeyNotEnoughValues";
3394                            UniqueOrKey key = (UniqueOrKey) fIdentityConstraint;
3395                            String JavaDoc ename = fIdentityConstraint.getElementName();
3396                            String JavaDoc kname = key.getIdentityConstraintName();
3397                            reportSchemaError(code, new Object JavaDoc[] { ename, kname });
3398                            break;
3399                        }
3400                        case IdentityConstraint.IC_KEYREF : {
3401                            String JavaDoc code = "KeyRefNotEnoughValues";
3402                            KeyRef keyref = (KeyRef) fIdentityConstraint;
3403                            String JavaDoc ename = fIdentityConstraint.getElementName();
3404                            String JavaDoc kname = (keyref.getKey()).getIdentityConstraintName();
3405                            reportSchemaError(code, new Object JavaDoc[] { ename, kname });
3406                            break;
3407                        }
3408                    }
3409                    return;
3410                }
3411                
3412            } // endValueScope()
3413

3414            // This is needed to allow keyref's to look for matched keys
3415
// in the correct scope. Unique and Key may also need to
3416
// override this method for purposes of their own.
3417
// This method is called whenever the DocumentFragment
3418
// of an ID Constraint goes out of scope.
3419
public void endDocumentFragment() {
3420            } // endDocumentFragment():void
3421

3422            /**
3423             * Signals the end of the document. This is where the specific
3424             * instances of value stores can verify the integrity of the
3425             * identity constraints.
3426             */

3427            public void endDocument() {
3428            } // endDocument()
3429

3430            //
3431
// ValueStore methods
3432
//
3433

3434        /* reports an error if an element is matched
3435         * has nillable true and is matched by a key.
3436         */

3437            
3438            public void reportError(String JavaDoc key, Object JavaDoc[] args) {
3439                reportSchemaError(key, args);
3440            } // reportError(String,Object[])
3441

3442            /**
3443             * Adds the specified value to the value store.
3444             *
3445             * @param value The value to add.
3446             * @param field The field associated to the value. This reference
3447             * is used to ensure that each field only adds a value
3448             * once within a selection scope.
3449             */

3450            public void addValue(Field field, Object JavaDoc actualValue) {
3451                addValue(field,actualValue,null);
3452            }
3453            
3454            public void addValue(Field field, Object JavaDoc actualValue,Object JavaDoc type) {
3455                int i;
3456                for (i = fFieldCount - 1; i > -1; i--) {
3457                    if (fFields[i] == field) {
3458                        break;
3459                    }
3460                }
3461                // do we even know this field?
3462
if (i == -1) {
3463                    String JavaDoc code = "UnknownField";
3464                    reportSchemaError(code, new Object JavaDoc[] { field.toString()});
3465                    return;
3466                }
3467                if (Boolean.TRUE != mayMatch(field)) {
3468                    String JavaDoc code = "FieldMultipleMatch";
3469                    reportSchemaError(code, new Object JavaDoc[] { field.toString()});
3470                } else {
3471                    fValuesCount++;
3472                }
3473                fLocalValues[i] = actualValue;
3474                fLocalValueTypes[i] = type;
3475                if (fValuesCount == fFieldCount) {
3476                    checkDuplicateValues();
3477                    // store values
3478
for (i = 0; i < fFieldCount; i++) {
3479                        fValues.addElement(fLocalValues[i]);
3480                        if(fLocalValueTypes[i] != null)
3481                            fValueTypes.addElement(fLocalValueTypes[i]);
3482                    }
3483                }
3484            } // addValue(String,Field)
3485

3486            /**
3487             * Returns true if this value store contains the locally scoped value stores
3488             */

3489            public boolean contains() {
3490                // REVISIT: we can improve performance by using hash codes, instead of
3491
// traversing global vector that could be quite large.
3492
int next = 0;
3493                LOOP : for (int i = 0; i < fValues.size(); i = next) {
3494                    next = i + fFieldCount;
3495                    for (int j = 0; j < fFieldCount; j++) {
3496                        Object JavaDoc value1 = fLocalValues[j];
3497                        Object JavaDoc value2 = fValues.elementAt(i++);
3498                        if (value1 == null || value2 == null || !(value1.equals(value2))) {
3499                            continue LOOP;
3500                        }
3501                    }
3502                    // found it
3503
return true;
3504                }
3505                // didn't find it
3506
return false;
3507            } // contains():boolean
3508

3509            /**
3510             * Returns true if this value store contains the specified
3511             * values.
3512             */

3513            public Object JavaDoc contains(Vector JavaDoc values) {
3514                for (int i = 0; i < values.size(); i++) {
3515                    if (!fValues.contains(values.elementAt(i)))
3516                        return values.elementAt(i);
3517                    
3518                }
3519                return null;
3520            } // contains(Vector):boolean
3521

3522            protected boolean isDerivedFromSamePrimitiveType(XSTypeDefinition typeOne , XSTypeDefinition typeTwo){
3523                if(typeOne == null || typeTwo == null)
3524                    return false;
3525                
3526                if(typeOne.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE &&
3527                ((XSComplexTypeDefinition) typeOne).getContentType() == XSComplexTypeDefinition.CONTENTTYPE_SIMPLE) {
3528                    typeOne = ((XSComplexTypeDefinition)typeOne).getSimpleType();
3529                    
3530                }
3531                if(typeTwo.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE && ((XSComplexTypeDefinition) typeTwo).getContentType() == XSComplexTypeDefinition.CONTENTTYPE_SIMPLE) {
3532                    typeTwo = ((XSComplexTypeDefinition)typeTwo).getSimpleType();
3533                }
3534                
3535                if(typeOne == null || typeTwo == null)
3536                    return false;
3537                
3538                if((typeOne.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) && (typeTwo.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE)){
3539                    try{
3540                        short s1 = ((XSSimpleTypeDecl)typeOne).getPrimitiveKind();
3541                        short s2 = ((XSSimpleTypeDecl)typeTwo).getPrimitiveKind();
3542                        if(s1 == s2)
3543                            return true;
3544                    }catch(Exception JavaDoc ex){
3545                        if(DEBUG)ex.printStackTrace();
3546                    }
3547                    
3548                }
3549                return false;
3550            }
3551            
3552            public Object JavaDoc contains(Vector JavaDoc values,Vector JavaDoc types) {
3553                for (int i = 0; i < values.size(); i++) {
3554                    if (fValues.contains(values.elementAt(i))){
3555                        int j = fValues.indexOf(values.elementAt(i));
3556                        try{
3557                            if(!isDerivedFromSamePrimitiveType((XSTypeDefinition)fValueTypes.elementAt(j),(XSTypeDefinition)types.elementAt(i)))
3558                                return values.elementAt(i);
3559                        }catch(Exception JavaDoc ex){
3560                            return values.elementAt(i);
3561                        }
3562                    }else
3563                        return values.elementAt(i);
3564                }
3565                return null;
3566            } // contains(Vector):boolean
3567
//
3568
// Protected methods
3569
//
3570

3571            protected void checkDuplicateValues() {
3572                // no-op
3573
} // duplicateValue(Hashtable)
3574

3575            /** Returns a string of the specified values. */
3576            protected String JavaDoc toString(Object JavaDoc[] values) {
3577                
3578                // no values
3579
int size = values.length;
3580                if (size == 0) {
3581                    return "";
3582                }
3583                
3584                fTempBuffer.setLength(0);
3585                
3586                // construct value string
3587
for (int i = 0; i < size; i++) {
3588                    if (i > 0) {
3589                        fTempBuffer.append(',');
3590                    }
3591                    fTempBuffer.append(values[i]);
3592                }
3593                return fTempBuffer.toString();
3594                
3595            } // toString(Object[]):String
3596

3597            //
3598
// Object methods
3599
//
3600

3601            /** Returns a string representation of this object. */
3602            public String JavaDoc toString() {
3603                String JavaDoc s = super.toString();
3604                int index1 = s.lastIndexOf('$');
3605                if (index1 != -1) {
3606                    s = s.substring(index1 + 1);
3607                }
3608                int index2 = s.lastIndexOf('.');
3609                if (index2 != -1) {
3610                    s = s.substring(index2 + 1);
3611                }
3612                return s + '[' + fIdentityConstraint + ']';
3613            } // toString():String
3614

3615        } // class ValueStoreBase
3616

3617        
3618        /**
3619         * Unique value store.
3620         *
3621         * @author Andy Clark, IBM
3622         */

3623        protected class UniqueValueStore extends ValueStoreBase {
3624            
3625            //
3626
// Constructors
3627
//
3628

3629            /** Constructs a unique value store. */
3630            public UniqueValueStore(UniqueOrKey unique) {
3631                super(unique);
3632            } // <init>(Unique)
3633

3634            //
3635
// ValueStoreBase protected methods
3636
//
3637

3638            /**
3639             * Called when a duplicate value is added.
3640             */

3641            protected void checkDuplicateValues() {
3642                // is this value as a group duplicated?
3643
if (contains()) {
3644                    String JavaDoc code = "DuplicateUnique";
3645                    String JavaDoc value = toString(fLocalValues);
3646                    String JavaDoc ename = fIdentityConstraint.getElementName();
3647                    reportSchemaError(code, new Object JavaDoc[]{value,ename});
3648                }
3649            } // duplicateValue(Hashtable)
3650

3651        } // class UniqueValueStore
3652

3653        /**
3654         * Key value store.
3655         *
3656         * @author Andy Clark, IBM
3657         */

3658        protected class KeyValueStore extends ValueStoreBase {
3659            
3660            // REVISIT: Implement a more efficient storage mechanism. -Ac
3661

3662            //
3663
// Constructors
3664
//
3665

3666            /** Constructs a key value store. */
3667            public KeyValueStore(UniqueOrKey key) {
3668                super(key);
3669            } // <init>(Key)
3670

3671            //
3672
// ValueStoreBase protected methods
3673
//
3674

3675            /**
3676             * Called when a duplicate value is added.
3677             */

3678            protected void checkDuplicateValues() {
3679                if (contains()) {
3680                    String JavaDoc code = "DuplicateKey";
3681                    String JavaDoc value = toString(fLocalValues);
3682                    String JavaDoc ename = fIdentityConstraint.getElementName();
3683                    reportSchemaError(code, new Object JavaDoc[]{value,ename});
3684                }
3685            } // duplicateValue(Hashtable)
3686

3687        } // class KeyValueStore
3688

3689        /**
3690         * Key reference value store.
3691         *
3692         * @author Andy Clark, IBM
3693         */

3694        protected class KeyRefValueStore extends ValueStoreBase {
3695            
3696            //
3697
// Data
3698
//
3699

3700            /** Key value store. */
3701            protected ValueStoreBase fKeyValueStore;
3702            
3703            //
3704
// Constructors
3705
//
3706

3707            /** Constructs a key value store. */
3708            public KeyRefValueStore(KeyRef keyRef, KeyValueStore keyValueStore) {
3709                super(keyRef);
3710                fKeyValueStore = keyValueStore;
3711            } // <init>(KeyRef)
3712

3713            //
3714
// ValueStoreBase methods
3715
//
3716

3717            // end the value Scope; here's where we have to tie
3718
// up keyRef loose ends.
3719
public void endDocumentFragment() {
3720                
3721                // do all the necessary management...
3722
super.endDocumentFragment();
3723                
3724                // verify references
3725
// get the key store corresponding (if it exists):
3726
fKeyValueStore =
3727                (ValueStoreBase) fValueStoreCache.fGlobalIDConstraintMap.get(
3728                ((KeyRef) fIdentityConstraint).getKey());
3729                
3730                if (fKeyValueStore == null) {
3731                    // report error
3732
String JavaDoc code = "KeyRefOutOfScope";
3733                    String JavaDoc value = fIdentityConstraint.toString();
3734                    reportSchemaError(code, new Object JavaDoc[]{value});
3735                    return;
3736                }
3737                Object JavaDoc value = fKeyValueStore.contains(fValues,fValueTypes);
3738                if (value != null) {
3739                    String JavaDoc code = "KeyNotFound";
3740                    String JavaDoc element = fIdentityConstraint.getElementName();
3741                    String JavaDoc name = fIdentityConstraint.getName();
3742                    reportSchemaError(code, new Object JavaDoc[] { name, value.toString(), element });
3743                }
3744                
3745            } // endDocumentFragment()
3746

3747            /** End document. */
3748            public void endDocument() {
3749                super.endDocument();
3750                
3751            } // endDocument()
3752

3753        } // class KeyRefValueStore
3754

3755        // value store management
3756

3757        /**
3758         * Value store cache. This class is used to store the values for
3759         * identity constraints.
3760         *
3761         * @author Andy Clark, IBM
3762         */

3763        protected class ValueStoreCache {
3764            
3765            //
3766
// Data
3767
//
3768
final LocalIDKey fLocalId = new LocalIDKey();
3769            // values stores
3770

3771            /** stores all global Values stores. */
3772            protected final Vector JavaDoc fValueStores = new Vector JavaDoc();
3773            
3774            /**
3775             * Values stores associated to specific identity constraints.
3776             * This hashtable maps IdentityConstraints and
3777             * the 0-based element on which their selectors first matched to
3778             * a corresponding ValueStore. This should take care
3779             * of all cases, including where ID constraints with
3780             * descendant-or-self axes occur on recursively-defined
3781             * elements.
3782             */

3783            protected final Hashtable JavaDoc fIdentityConstraint2ValueStoreMap = new Hashtable JavaDoc();
3784            
3785            // sketch of algorithm:
3786
// - when a constraint is first encountered, its
3787
// values are stored in the (local) fIdentityConstraint2ValueStoreMap;
3788
// - Once it is validated (i.e., when it goes out of scope),
3789
// its values are merged into the fGlobalIDConstraintMap;
3790
// - as we encounter keyref's, we look at the global table to
3791
// validate them.
3792
//
3793
// The fGlobalIDMapStack has the following structure:
3794
// - validation always occurs against the fGlobalIDConstraintMap
3795
// (which comprises all the "eligible" id constraints);
3796
// When an endElement is found, this Hashtable is merged with the one
3797
// below in the stack.
3798
// When a start tag is encountered, we create a new
3799
// fGlobalIDConstraintMap.
3800
// i.e., the top of the fGlobalIDMapStack always contains
3801
// the preceding siblings' eligible id constraints;
3802
// the fGlobalIDConstraintMap contains descendants+self.
3803
// keyrefs can only match descendants+self.
3804
protected final Stack JavaDoc fGlobalMapStack = new Stack JavaDoc();
3805            protected final Hashtable JavaDoc fGlobalIDConstraintMap = new Hashtable JavaDoc();
3806            
3807            //
3808
// Constructors
3809
//
3810

3811            /** Default constructor. */
3812            public ValueStoreCache() {
3813            } // <init>()
3814

3815            //
3816
// Public methods
3817
//
3818

3819            /** Resets the identity constraint cache. */
3820            public void startDocument() {
3821                fValueStores.removeAllElements();
3822                fIdentityConstraint2ValueStoreMap.clear();
3823                fGlobalIDConstraintMap.clear();
3824                fGlobalMapStack.removeAllElements();
3825            } // startDocument()
3826

3827            // startElement: pushes the current fGlobalIDConstraintMap
3828
// onto fGlobalMapStack and clears fGlobalIDConstraint map.
3829
public void startElement() {
3830                // only clone the hashtable when there are elements
3831
if (fGlobalIDConstraintMap.size() > 0)
3832                    fGlobalMapStack.push(fGlobalIDConstraintMap.clone());
3833                else
3834                    fGlobalMapStack.push(null);
3835                fGlobalIDConstraintMap.clear();
3836            } // startElement(void)
3837

3838            /** endElement(): merges contents of fGlobalIDConstraintMap with the
3839             * top of fGlobalMapStack into fGlobalIDConstraintMap.
3840             */

3841            public void endElement() {
3842                if (fGlobalMapStack.isEmpty())
3843                    return; // must be an invalid doc!
3844
Hashtable JavaDoc oldMap = (Hashtable JavaDoc)fGlobalMapStack.pop();
3845                // return if there is no element
3846
if (oldMap == null)
3847                    return;
3848                
3849                Enumeration JavaDoc keys = oldMap.keys();
3850                while (keys.hasMoreElements()) {
3851                    IdentityConstraint id = (IdentityConstraint)keys.nextElement();
3852                    ValueStoreBase oldVal = (ValueStoreBase)oldMap.get(id);
3853                    if (oldVal != null) {
3854                        ValueStoreBase currVal = (ValueStoreBase)fGlobalIDConstraintMap.get(id);
3855                        if (currVal == null)
3856                            fGlobalIDConstraintMap.put(id, oldVal);
3857                        else if (currVal != oldVal) {
3858                            currVal.append(oldVal);
3859                        }
3860                    }
3861                }
3862            } // endElement()
3863

3864            /**
3865             * Initializes the value stores for the specified element
3866             * declaration.
3867             */

3868            public void initValueStoresFor(XSElementDecl eDecl, FieldActivator activator) {
3869                // initialize value stores for unique fields
3870
IdentityConstraint [] icArray = eDecl.fIDConstraints;
3871                int icCount = eDecl.fIDCPos;
3872                for (int i = 0; i < icCount; i++) {
3873                    switch (icArray[i].getCategory()) {
3874                        case (IdentityConstraint.IC_UNIQUE):
3875                            // initialize value stores for unique fields
3876
UniqueOrKey unique = (UniqueOrKey)icArray[i];
3877                            LocalIDKey toHash = new LocalIDKey(unique, fElementDepth);
3878                            UniqueValueStore uniqueValueStore =
3879                            (UniqueValueStore) fIdentityConstraint2ValueStoreMap.get(toHash);
3880                            if (uniqueValueStore == null) {
3881                                uniqueValueStore = new UniqueValueStore(unique);
3882                                fIdentityConstraint2ValueStoreMap.put(toHash, uniqueValueStore);
3883                            } else {
3884                                uniqueValueStore.clear();
3885                            }
3886                            fValueStores.addElement(uniqueValueStore);
3887                            activateSelectorFor(icArray[i]);
3888                            break;
3889                        case (IdentityConstraint.IC_KEY):
3890                            // initialize value stores for key fields
3891
UniqueOrKey key = (UniqueOrKey)icArray[i];
3892                            toHash = new LocalIDKey(key, fElementDepth);
3893                            KeyValueStore keyValueStore =
3894                            (KeyValueStore) fIdentityConstraint2ValueStoreMap.get(toHash);
3895                            if (keyValueStore == null) {
3896                                keyValueStore = new KeyValueStore(key);
3897                                fIdentityConstraint2ValueStoreMap.put(toHash, keyValueStore);
3898                            } else {
3899                                keyValueStore.clear();
3900                            }
3901                            fValueStores.addElement(keyValueStore);
3902                            activateSelectorFor(icArray[i]);
3903                            break;
3904                        case (IdentityConstraint.IC_KEYREF):
3905                            // initialize value stores for keyRef fields
3906
KeyRef keyRef = (KeyRef)icArray[i];
3907                            toHash = new LocalIDKey(keyRef, fElementDepth);
3908                            KeyRefValueStore keyRefValueStore =
3909                            (KeyRefValueStore) fIdentityConstraint2ValueStoreMap.get(toHash);
3910                            if (keyRefValueStore == null) {
3911                                keyRefValueStore = new KeyRefValueStore(keyRef, null);
3912                                fIdentityConstraint2ValueStoreMap.put(toHash, keyRefValueStore);
3913                            } else {
3914                                keyRefValueStore.clear();
3915                            }
3916                            fValueStores.addElement(keyRefValueStore);
3917                            activateSelectorFor(icArray[i]);
3918                            break;
3919                    }
3920                }
3921            } // initValueStoresFor(XSElementDecl)
3922

3923            /** Returns the value store associated to the specified IdentityConstraint. */
3924            public ValueStoreBase getValueStoreFor(IdentityConstraint id, int initialDepth) {
3925                fLocalId.fDepth = initialDepth;
3926                fLocalId.fId = id;
3927                return (ValueStoreBase) fIdentityConstraint2ValueStoreMap.get(fLocalId);
3928            } // getValueStoreFor(IdentityConstraint, int):ValueStoreBase
3929

3930            /** Returns the global value store associated to the specified IdentityConstraint. */
3931            public ValueStoreBase getGlobalValueStoreFor(IdentityConstraint id) {
3932                return(ValueStoreBase)fGlobalIDConstraintMap.get(id);
3933            } // getValueStoreFor(IdentityConstraint):ValueStoreBase
3934

3935            // This method takes the contents of the (local) ValueStore
3936
// associated with id and moves them into the global
3937
// hashtable, if id is a <unique> or a <key>.
3938
// If it's a <keyRef>, then we leave it for later.
3939
public void transplant(IdentityConstraint id, int initialDepth) {
3940                fLocalId.fDepth = initialDepth;
3941                fLocalId.fId = id;
3942                ValueStoreBase newVals =
3943                (ValueStoreBase) fIdentityConstraint2ValueStoreMap.get(fLocalId);
3944                if (id.getCategory() == IdentityConstraint.IC_KEYREF)
3945                    return;
3946                ValueStoreBase currVals = (ValueStoreBase)fGlobalIDConstraintMap.get(id);
3947                if (currVals != null) {
3948                    currVals.append(newVals);
3949                    fGlobalIDConstraintMap.put(id, currVals);
3950                } else
3951                    fGlobalIDConstraintMap.put(id, newVals);
3952                
3953            } // transplant(id)
3954

3955            /** Check identity constraints. */
3956            public void endDocument() {
3957                
3958                int count = fValueStores.size();
3959                for (int i = 0; i < count; i++) {
3960                    ValueStoreBase valueStore = (ValueStoreBase)fValueStores.elementAt(i);
3961                    valueStore.endDocument();
3962                }
3963                
3964            } // endDocument()
3965

3966            //
3967
// Object methods
3968
//
3969

3970            /** Returns a string representation of this object. */
3971            public String JavaDoc toString() {
3972                String JavaDoc s = super.toString();
3973                int index1 = s.lastIndexOf('$');
3974                if (index1 != -1) {
3975                    return s.substring(index1 + 1);
3976                }
3977                int index2 = s.lastIndexOf('.');
3978                if (index2 != -1) {
3979                    return s.substring(index2 + 1);
3980                }
3981                return s;
3982            } // toString():String
3983

3984        } // class ValueStoreCache
3985

3986        // the purpose of this class is to enable IdentityConstraint,int
3987
// pairs to be used easily as keys in Hashtables.
3988
protected class LocalIDKey {
3989            
3990            public IdentityConstraint fId;
3991            public int fDepth;
3992            
3993            public LocalIDKey() {
3994            }
3995            
3996            public LocalIDKey(IdentityConstraint id, int depth) {
3997                fId = id;
3998                fDepth = depth;
3999            } // init(IdentityConstraint, int)
4000

4001            // object method
4002
public int hashCode() {
4003                return fId.hashCode()+fDepth;
4004            }
4005            
4006            public boolean equals(Object JavaDoc localIDKey) {
4007                if(localIDKey instanceof LocalIDKey) {
4008                    LocalIDKey lIDKey = (LocalIDKey)localIDKey;
4009                    return (lIDKey.fId == fId && lIDKey.fDepth == fDepth);
4010                }
4011                return false;
4012            }
4013        } // class LocalIDKey
4014

4015} // class SchemaValidator
4016
Popular Tags