1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 1999-2005 The Apache Software Foundation.
   7  *
   8  * Licensed under the Apache License, Version 2.0 (the "License");
   9  * you may not use this file except in compliance with the License.
  10  * You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.xerces.internal.impl.xs;
  22 
  23 import java.io.IOException;
  24 import java.util.ArrayList;
  25 import java.util.HashMap;
  26 import java.util.Hashtable;
  27 import java.util.Iterator;
  28 import java.util.Map;
  29 import java.util.Stack;
  30 import java.util.Vector;
  31 import java.util.ArrayList;
  32 
  33 import com.sun.org.apache.xerces.internal.impl.Constants;
  34 import com.sun.org.apache.xerces.internal.impl.RevalidationHandler;
  35 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
  36 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
  37 import com.sun.org.apache.xerces.internal.impl.dv.DatatypeException;
  38 import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
  39 import com.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo;
  40 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
  41 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
  42 import com.sun.org.apache.xerces.internal.impl.validation.ValidationState;
  43 import com.sun.org.apache.xerces.internal.impl.xs.identity.Field;
  44 import com.sun.org.apache.xerces.internal.impl.xs.identity.FieldActivator;
  45 import com.sun.org.apache.xerces.internal.impl.xs.identity.IdentityConstraint;
  46 import com.sun.org.apache.xerces.internal.impl.xs.identity.KeyRef;
  47 import com.sun.org.apache.xerces.internal.impl.xs.identity.Selector;
  48 import com.sun.org.apache.xerces.internal.impl.xs.identity.UniqueOrKey;
  49 import com.sun.org.apache.xerces.internal.impl.xs.identity.ValueStore;
  50 import com.sun.org.apache.xerces.internal.impl.xs.identity.XPathMatcher;
  51 import com.sun.org.apache.xerces.internal.impl.xs.models.CMBuilder;
  52 import com.sun.org.apache.xerces.internal.impl.xs.models.CMNodeFactory;
  53 import com.sun.org.apache.xerces.internal.impl.xs.models.XSCMValidator;
  54 import com.sun.org.apache.xerces.internal.util.AugmentationsImpl;
  55 import com.sun.org.apache.xerces.internal.util.IntStack;
  56 import com.sun.org.apache.xerces.internal.util.SymbolTable;
  57 import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl;
  58 import com.sun.org.apache.xerces.internal.util.XMLChar;
  59 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
  60 import com.sun.org.apache.xerces.internal.util.URI.MalformedURIException;
  61 import com.sun.org.apache.xerces.internal.xni.Augmentations;
  62 import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
  63 import com.sun.org.apache.xerces.internal.xni.QName;
  64 import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
  65 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
  66 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
  67 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
  68 import com.sun.org.apache.xerces.internal.xni.XMLString;
  69 import com.sun.org.apache.xerces.internal.xni.XNIException;
  70 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
  71 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
  72 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
  73 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
  74 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  75 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentFilter;
  76 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
  77 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
  78 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
  79 import com.sun.org.apache.xerces.internal.xs.AttributePSVI;
  80 import com.sun.org.apache.xerces.internal.xs.ElementPSVI;
  81 import com.sun.org.apache.xerces.internal.xs.ShortList;
  82 import com.sun.org.apache.xerces.internal.xs.StringList;
  83 import com.sun.org.apache.xerces.internal.xs.XSConstants;
  84 import com.sun.org.apache.xerces.internal.xs.XSObjectList;
  85 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
  86 import com.sun.org.apache.xerces.internal.parsers.XMLParser;
  87 
  88 /**
  89  * The XML Schema validator. The validator implements a document
  90  * filter: receiving document events from the scanner; validating
  91  * the content and structure; augmenting the InfoSet, if applicable;
  92  * and notifying the parser of the information resulting from the
  93  * validation process.
  94  * <p>
  95  * This component requires the following features and properties from the
  96  * component manager that uses it:
  97  * <ul>
  98  *  <li>http://xml.org/sax/features/validation</li>
  99  *  <li>http://apache.org/xml/properties/internal/symbol-table</li>
 100  *  <li>http://apache.org/xml/properties/internal/error-reporter</li>
 101  *  <li>http://apache.org/xml/properties/internal/entity-resolver</li>
 102  * </ul>
 103  *
 104  * @xerces.internal
 105  *
 106  * @author Sandy Gao IBM
 107  * @author Elena Litani IBM
 108  * @author Andy Clark IBM
 109  * @author Neeraj Bajaj, Sun Microsystems, inc.
 110  * @version $Id: XMLSchemaValidator.java,v 1.16 2010-11-01 04:39:55 joehw Exp $
 111  */
 112 public class XMLSchemaValidator
 113     implements XMLComponent, XMLDocumentFilter, FieldActivator, RevalidationHandler {
 114 
 115     //
 116     // Constants
 117     //
 118     private static final boolean DEBUG = false;
 119 
 120     // feature identifiers
 121 
 122     /** Feature identifier: validation. */
 123     protected static final String VALIDATION =
 124         Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
 125 
 126     /** Feature identifier: validation. */
 127     protected static final String SCHEMA_VALIDATION =
 128         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
 129 
 130     /** Feature identifier: schema full checking*/
 131     protected static final String SCHEMA_FULL_CHECKING =
 132         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING;
 133 
 134     /** Feature identifier: dynamic validation. */
 135     protected static final String DYNAMIC_VALIDATION =
 136         Constants.XERCES_FEATURE_PREFIX + Constants.DYNAMIC_VALIDATION_FEATURE;
 137 
 138     /** Feature identifier: expose schema normalized value */
 139     protected static final String NORMALIZE_DATA =
 140         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE;
 141 
 142     /** Feature identifier: send element default value via characters() */
 143     protected static final String SCHEMA_ELEMENT_DEFAULT =
 144         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_ELEMENT_DEFAULT;
 145 
 146     /** Feature identifier: augment PSVI */
 147     protected static final String SCHEMA_AUGMENT_PSVI =
 148         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_AUGMENT_PSVI;
 149 
 150     /** Feature identifier: whether to recognize java encoding names */
 151     protected static final String ALLOW_JAVA_ENCODINGS =
 152         Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
 153 
 154     /** Feature identifier: standard uri conformant feature. */
 155     protected static final String STANDARD_URI_CONFORMANT_FEATURE =
 156         Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE;
 157 
 158     /** Feature: generate synthetic annotations */
 159     protected static final String GENERATE_SYNTHETIC_ANNOTATIONS =
 160         Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE;
 161 
 162     /** Feature identifier: validate annotations. */
 163     protected static final String VALIDATE_ANNOTATIONS =
 164         Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATE_ANNOTATIONS_FEATURE;
 165 
 166     /** Feature identifier: honour all schemaLocations */
 167     protected static final String HONOUR_ALL_SCHEMALOCATIONS =
 168         Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE;
 169 
 170     /** Feature identifier: use grammar pool only */
 171     protected static final String USE_GRAMMAR_POOL_ONLY =
 172         Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE;
 173 
 174     /** Feature identifier: whether to continue parsing a schema after a fatal error is encountered */
 175     protected static final String CONTINUE_AFTER_FATAL_ERROR =
 176         Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
 177 
 178     protected static final String PARSER_SETTINGS =
 179             Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
 180 
 181     /** Feature identifier: namespace growth */
 182     protected static final String NAMESPACE_GROWTH =
 183         Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE;
 184 
 185     /** Feature identifier: tolerate duplicates */
 186     protected static final String TOLERATE_DUPLICATES =
 187         Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_FEATURE;
 188 
 189     protected static final String REPORT_WHITESPACE =
 190             Constants.SUN_SCHEMA_FEATURE_PREFIX + Constants.SUN_REPORT_IGNORED_ELEMENT_CONTENT_WHITESPACE;
 191 
 192     // property identifiers
 193 
 194     /** Property identifier: symbol table. */
 195     public static final String SYMBOL_TABLE =
 196         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
 197 
 198     /** Property identifier: error reporter. */
 199     public static final String ERROR_REPORTER =
 200         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
 201 
 202     /** Property identifier: entity resolver. */
 203     public static final String ENTITY_RESOLVER =
 204         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
 205 
 206     /** Property identifier: grammar pool. */
 207     public static final String XMLGRAMMAR_POOL =
 208         Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
 209 
 210     protected static final String VALIDATION_MANAGER =
 211         Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
 212 
 213     protected static final String ENTITY_MANAGER =
 214         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
 215 
 216     /** Property identifier: schema location. */
 217     protected static final String SCHEMA_LOCATION =
 218         Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_LOCATION;
 219 
 220     /** Property identifier: no namespace schema location. */
 221     protected static final String SCHEMA_NONS_LOCATION =
 222         Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_NONS_LOCATION;
 223 
 224     /** Property identifier: JAXP schema source. */
 225     protected static final String JAXP_SCHEMA_SOURCE =
 226         Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
 227 
 228     /** Property identifier: JAXP schema language. */
 229     protected static final String JAXP_SCHEMA_LANGUAGE =
 230         Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE;
 231 
 232     /** Property identifier: Schema DV Factory */
 233     protected static final String SCHEMA_DV_FACTORY =
 234         Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY;
 235 
 236     protected static final String USE_SERVICE_MECHANISM = Constants.ORACLE_FEATURE_SERVICE_MECHANISM;
 237 
 238     // recognized features and properties
 239 
 240     /** Recognized features. */
 241     private static final String[] RECOGNIZED_FEATURES =
 242         {
 243             VALIDATION,
 244             SCHEMA_VALIDATION,
 245             DYNAMIC_VALIDATION,
 246             SCHEMA_FULL_CHECKING,
 247             ALLOW_JAVA_ENCODINGS,
 248             CONTINUE_AFTER_FATAL_ERROR,
 249             STANDARD_URI_CONFORMANT_FEATURE,
 250             GENERATE_SYNTHETIC_ANNOTATIONS,
 251             VALIDATE_ANNOTATIONS,
 252             HONOUR_ALL_SCHEMALOCATIONS,
 253             USE_GRAMMAR_POOL_ONLY,
 254             NAMESPACE_GROWTH,
 255             TOLERATE_DUPLICATES,
 256             USE_SERVICE_MECHANISM
 257     };
 258 
 259     /** Feature defaults. */
 260     private static final Boolean[] FEATURE_DEFAULTS = { null,
 261         // NOTE: The following defaults are nulled out on purpose.
 262         //       If they are set, then when the XML Schema validator
 263         //       is constructed dynamically, these values may override
 264         //       those set by the application. This goes against the
 265         //       whole purpose of XMLComponent#getFeatureDefault but
 266         //       it can't be helped in this case. -Ac
 267         null, //Boolean.FALSE,
 268         null, //Boolean.FALSE,
 269         null, //Boolean.FALSE,
 270         null, //Boolean.FALSE,
 271         null, //Boolean.FALSE,
 272         null,
 273         null,
 274         null,
 275         null,
 276         null,
 277         null,
 278         null,
 279         Boolean.TRUE
 280     };
 281 
 282     /** Recognized properties. */
 283     private static final String[] RECOGNIZED_PROPERTIES =
 284         {
 285             SYMBOL_TABLE,
 286             ERROR_REPORTER,
 287             ENTITY_RESOLVER,
 288             VALIDATION_MANAGER,
 289             SCHEMA_LOCATION,
 290             SCHEMA_NONS_LOCATION,
 291             JAXP_SCHEMA_SOURCE,
 292             JAXP_SCHEMA_LANGUAGE,
 293             SCHEMA_DV_FACTORY,
 294             };
 295 
 296     /** Property defaults. */
 297     private static final Object[] PROPERTY_DEFAULTS =
 298         { null, null, null, null, null, null, null, null, null, null, null};
 299 
 300     // this is the number of valuestores of each kind
 301     // we expect an element to have.  It's almost
 302     // never > 1; so leave it at that.
 303     protected static final int ID_CONSTRAINT_NUM = 1;
 304 
 305     //
 306     private static final Hashtable EMPTY_TABLE = new Hashtable();
 307 
 308     //
 309     // Data
 310     //
 311 
 312     /** current PSVI element info */
 313     protected ElementPSVImpl fCurrentPSVI = new ElementPSVImpl();
 314 
 315     // since it is the responsibility of each component to an
 316     // Augmentations parameter if one is null, to save ourselves from
 317     // having to create this object continually, it is created here.
 318     // If it is not present in calls that we're passing on, we *must*
 319     // clear this before we introduce it into the pipeline.
 320     protected final AugmentationsImpl fAugmentations = new AugmentationsImpl();
 321 
 322     /**
 323      * Map which is used to catch instance documents that try
 324      * and match a field several times in the same scope.
 325      */
 326     protected final HashMap fMayMatchFieldMap = new HashMap();
 327 
 328     // this is included for the convenience of handleEndElement
 329     protected XMLString fDefaultValue;
 330 
 331     // Validation features
 332     protected boolean fDynamicValidation = false;
 333     protected boolean fSchemaDynamicValidation = false;
 334     protected boolean fDoValidation = false;
 335     protected boolean fFullChecking = false;
 336     protected boolean fNormalizeData = true;
 337     protected boolean fSchemaElementDefault = true;
 338     protected boolean fAugPSVI = true;
 339     protected boolean fIdConstraint = false;
 340     protected boolean fUseGrammarPoolOnly = false;
 341 
 342     // Namespace growth feature
 343     protected boolean fNamespaceGrowth = false;
 344 
 345     /** Schema type: None, DTD, Schema */
 346     private String fSchemaType = null;
 347 
 348     // to indicate whether we are in the scope of entity reference or CData
 349     protected boolean fEntityRef = false;
 350     protected boolean fInCDATA = false;
 351 
 352     // Did we see only whitespace in element content?
 353     protected boolean fSawOnlyWhitespaceInElementContent = false;
 354 
 355     // properties
 356 
 357     /** Symbol table. */
 358     protected SymbolTable fSymbolTable;
 359 
 360     /**
 361      * While parsing a document, keep the location of the document.
 362      */
 363     private XMLLocator fLocator;
 364 
 365     /**
 366      * A wrapper of the standard error reporter. We'll store all schema errors
 367      * in this wrapper object, so that we can get all errors (error codes) of
 368      * a specific element. This is useful for PSVI.
 369      */
 370     protected final class XSIErrorReporter {
 371 
 372         // the error reporter property
 373         XMLErrorReporter fErrorReporter;
 374 
 375         // store error codes; starting position of the errors for each element;
 376         // number of element (depth); and whether to record error
 377         Vector fErrors = new Vector();
 378         int[] fContext = new int[INITIAL_STACK_SIZE];
 379         int fContextCount;
 380 
 381         // set the external error reporter, clear errors
 382         public void reset(XMLErrorReporter errorReporter) {
 383             fErrorReporter = errorReporter;
 384             fErrors.removeAllElements();
 385             fContextCount = 0;
 386         }
 387 
 388         // should be called when starting process an element or an attribute.
 389         // store the starting position for the current context
 390         public void pushContext() {
 391             if (!fAugPSVI) {
 392                 return;
 393             }
 394             // resize array if necessary
 395             if (fContextCount == fContext.length) {
 396                 int newSize = fContextCount + INC_STACK_SIZE;
 397                 int[] newArray = new int[newSize];
 398                 System.arraycopy(fContext, 0, newArray, 0, fContextCount);
 399                 fContext = newArray;
 400             }
 401 
 402             fContext[fContextCount++] = fErrors.size();
 403         }
 404 
 405         // should be called on endElement: get all errors of the current element
 406         public String[] popContext() {
 407             if (!fAugPSVI) {
 408                 return null;
 409             }
 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[] errors = new String[size];
 419             for (int i = 0; i < size; i++) {
 420                 errors[i] = (String) fErrors.elementAt(contextPos + i);
 421             }
 422             // remove errors of the current element
 423             fErrors.setSize(contextPos);
 424             return errors;
 425         }
 426 
 427         // should be called when an attribute is done: get all errors of
 428         // this attribute, but leave the errors to the containing element
 429         // also called after an element was strictly assessed.
 430         public String[] mergeContext() {
 431             if (!fAugPSVI) {
 432                 return null;
 433             }
 434             // get starting position of the current element
 435             int contextPos = fContext[--fContextCount];
 436             // number of errors of the current element
 437             int size = fErrors.size() - contextPos;
 438             // if no errors, return null
 439             if (size == 0)
 440                 return null;
 441             // copy errors from the list to an string array
 442             String[] errors = new String[size];
 443             for (int i = 0; i < size; i++) {
 444                 errors[i] = (String) fErrors.elementAt(contextPos + i);
 445             }
 446             // don't resize the vector: leave the errors for this attribute
 447             // to the containing element
 448             return errors;
 449         }
 450 
 451         public void reportError(String domain, String key, Object[] arguments, short severity)
 452             throws XNIException {
 453             fErrorReporter.reportError(domain, key, arguments, severity);
 454             if (fAugPSVI) {
 455                 fErrors.addElement(key);
 456             }
 457         } // reportError(String,String,Object[],short)
 458 
 459         public void reportError(
 460             XMLLocator location,
 461             String domain,
 462             String key,
 463             Object[] arguments,
 464             short severity)
 465             throws XNIException {
 466             fErrorReporter.reportError(location, domain, key, arguments, severity);
 467             if (fAugPSVI) {
 468                 fErrors.addElement(key);
 469             }
 470         } // reportError(XMLLocator,String,String,Object[],short)
 471     }
 472 
 473     /** Error reporter. */
 474     protected final XSIErrorReporter fXSIErrorReporter = new XSIErrorReporter();
 475 
 476     /** Entity resolver */
 477     protected XMLEntityResolver fEntityResolver;
 478 
 479     // updated during reset
 480     protected ValidationManager fValidationManager = null;
 481     protected ValidationState fValidationState = new ValidationState();
 482     protected XMLGrammarPool fGrammarPool;
 483 
 484     // schema location property values
 485     protected String fExternalSchemas = null;
 486     protected String fExternalNoNamespaceSchema = null;
 487 
 488     //JAXP Schema Source property
 489     protected Object fJaxpSchemaSource = null;
 490 
 491     /** Schema Grammar Description passed,  to give a chance to application to supply the Grammar */
 492     protected final XSDDescription fXSDDescription = new XSDDescription();
 493     protected final Hashtable fLocationPairs = new Hashtable();
 494 
 495 
 496     // handlers
 497 
 498     /** Document handler. */
 499     protected XMLDocumentHandler fDocumentHandler;
 500 
 501     protected XMLDocumentSource fDocumentSource;
 502 
 503     boolean reportWhitespace = false;
 504 
 505     //
 506     // XMLComponent methods
 507     //
 508 
 509     /**
 510      * Returns a list of feature identifiers that are recognized by
 511      * this component. This method may return null if no features
 512      * are recognized by this component.
 513      */
 514     public String[] getRecognizedFeatures() {
 515         return (String[]) (RECOGNIZED_FEATURES.clone());
 516     } // getRecognizedFeatures():String[]
 517 
 518     /**
 519      * Sets the state of a feature. This method is called by the component
 520      * manager any time after reset when a feature changes state.
 521      * <p>
 522      * <strong>Note:</strong> Components should silently ignore features
 523      * that do not affect the operation of the component.
 524      *
 525      * @param featureId The feature identifier.
 526      * @param state     The state of the feature.
 527      *
 528      * @throws SAXNotRecognizedException The component should not throw
 529      *                                   this exception.
 530      * @throws SAXNotSupportedException The component should not throw
 531      *                                  this exception.
 532      */
 533     public void setFeature(String featureId, boolean state) throws XMLConfigurationException {
 534     } // setFeature(String,boolean)
 535 
 536     /**
 537      * Returns a list of property identifiers that are recognized by
 538      * this component. This method may return null if no properties
 539      * are recognized by this component.
 540      */
 541     public String[] getRecognizedProperties() {
 542         return (String[]) (RECOGNIZED_PROPERTIES.clone());
 543     } // getRecognizedProperties():String[]
 544 
 545     /**
 546      * Sets the value of a property. This method is called by the component
 547      * manager any time after reset when a property changes value.
 548      * <p>
 549      * <strong>Note:</strong> Components should silently ignore properties
 550      * that do not affect the operation of the component.
 551      *
 552      * @param propertyId The property identifier.
 553      * @param value      The value of the property.
 554      *
 555      * @throws SAXNotRecognizedException The component should not throw
 556      *                                   this exception.
 557      * @throws SAXNotSupportedException The component should not throw
 558      *                                  this exception.
 559      */
 560     public void setProperty(String propertyId, Object value) throws XMLConfigurationException {
 561     } // setProperty(String,Object)
 562 
 563     /**
 564      * Returns the default state for a feature, or null if this
 565      * component does not want to report a default value for this
 566      * feature.
 567      *
 568      * @param featureId The feature identifier.
 569      *
 570      * @since Xerces 2.2.0
 571      */
 572     public Boolean getFeatureDefault(String featureId) {
 573         for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
 574             if (RECOGNIZED_FEATURES[i].equals(featureId)) {
 575                 return FEATURE_DEFAULTS[i];
 576             }
 577         }
 578         return null;
 579     } // getFeatureDefault(String):Boolean
 580 
 581     /**
 582      * Returns the default state for a property, or null if this
 583      * component does not want to report a default value for this
 584      * property.
 585      *
 586      * @param propertyId The property identifier.
 587      *
 588      * @since Xerces 2.2.0
 589      */
 590     public Object getPropertyDefault(String propertyId) {
 591         for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
 592             if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
 593                 return PROPERTY_DEFAULTS[i];
 594             }
 595         }
 596         return null;
 597     } // getPropertyDefault(String):Object
 598 
 599     //
 600     // XMLDocumentSource methods
 601     //
 602 
 603     /** Sets the document handler to receive information about the document. */
 604     public void setDocumentHandler(XMLDocumentHandler documentHandler) {
 605         fDocumentHandler = documentHandler;
 606 
 607         // Init reportWhitespace for this handler
 608         if (documentHandler instanceof XMLParser) {
 609             try {
 610                 reportWhitespace =
 611                     ((XMLParser) documentHandler).getFeature(REPORT_WHITESPACE);
 612             }
 613             catch (Exception e) {
 614                 reportWhitespace = false;
 615             }
 616         }
 617     } // setDocumentHandler(XMLDocumentHandler)
 618 
 619     /** Returns the document handler */
 620     public XMLDocumentHandler getDocumentHandler() {
 621         return fDocumentHandler;
 622     } // setDocumentHandler(XMLDocumentHandler)
 623 
 624     //
 625     // XMLDocumentHandler methods
 626     //
 627 
 628     /** Sets the document source */
 629     public void setDocumentSource(XMLDocumentSource source) {
 630         fDocumentSource = source;
 631     } // setDocumentSource
 632 
 633     /** Returns the document source */
 634     public XMLDocumentSource getDocumentSource() {
 635         return fDocumentSource;
 636     } // getDocumentSource
 637 
 638     /**
 639      * The start of the document.
 640      *
 641      * @param locator The system identifier of the entity if the entity
 642      *                 is external, null otherwise.
 643      * @param encoding The auto-detected IANA encoding name of the entity
 644      *                 stream. This value will be null in those situations
 645      *                 where the entity encoding is not auto-detected (e.g.
 646      *                 internal entities or a document entity that is
 647      *                 parsed from a java.io.Reader).
 648      * @param namespaceContext
 649      *                 The namespace context in effect at the
 650      *                 start of this document.
 651      *                 This object represents the current context.
 652      *                 Implementors of this class are responsible
 653      *                 for copying the namespace bindings from the
 654      *                 the current context (and its parent contexts)
 655      *                 if that information is important.
 656      * @param augs     Additional information that may include infoset augmentations
 657      *
 658      * @throws XNIException Thrown by handler to signal an error.
 659      */
 660     public void startDocument(
 661         XMLLocator locator,
 662         String encoding,
 663         NamespaceContext namespaceContext,
 664         Augmentations augs)
 665         throws XNIException {
 666 
 667         fValidationState.setNamespaceSupport(namespaceContext);
 668         fState4XsiType.setNamespaceSupport(namespaceContext);
 669         fState4ApplyDefault.setNamespaceSupport(namespaceContext);
 670         fLocator = locator;
 671 
 672         handleStartDocument(locator, encoding);
 673         // call handlers
 674         if (fDocumentHandler != null) {
 675             fDocumentHandler.startDocument(locator, encoding, namespaceContext, augs);
 676         }
 677 
 678     } // startDocument(XMLLocator,String)
 679 
 680     /**
 681      * Notifies of the presence of an XMLDecl line in the document. If
 682      * present, this method will be called immediately following the
 683      * startDocument call.
 684      *
 685      * @param version    The XML version.
 686      * @param encoding   The IANA encoding name of the document, or null if
 687      *                   not specified.
 688      * @param standalone The standalone value, or null if not specified.
 689      * @param augs     Additional information that may include infoset augmentations
 690      *
 691      * @throws XNIException Thrown by handler to signal an error.
 692      */
 693     public void xmlDecl(String version, String encoding, String standalone, Augmentations augs)
 694         throws XNIException {
 695 
 696         // call handlers
 697         if (fDocumentHandler != null) {
 698             fDocumentHandler.xmlDecl(version, encoding, standalone, augs);
 699         }
 700 
 701     } // xmlDecl(String,String,String)
 702 
 703     /**
 704      * Notifies of the presence of the DOCTYPE line in the document.
 705      *
 706      * @param rootElement The name of the root element.
 707      * @param publicId    The public identifier if an external DTD or null
 708      *                    if the external DTD is specified using SYSTEM.
 709      * @param systemId    The system identifier if an external DTD, null
 710      *                    otherwise.
 711      * @param augs     Additional information that may include infoset augmentations
 712      *
 713      * @throws XNIException Thrown by handler to signal an error.
 714      */
 715     public void doctypeDecl(
 716         String rootElement,
 717         String publicId,
 718         String systemId,
 719         Augmentations augs)
 720         throws XNIException {
 721 
 722         // call handlers
 723         if (fDocumentHandler != null) {
 724             fDocumentHandler.doctypeDecl(rootElement, publicId, systemId, augs);
 725         }
 726 
 727     } // doctypeDecl(String,String,String)
 728 
 729     /**
 730      * The start of an element.
 731      *
 732      * @param element    The name of the element.
 733      * @param attributes The element attributes.
 734      * @param augs     Additional information that may include infoset augmentations
 735      *
 736      * @throws XNIException Thrown by handler to signal an error.
 737      */
 738     public void startElement(QName element, XMLAttributes attributes, Augmentations augs)
 739         throws XNIException {
 740 
 741         Augmentations modifiedAugs = handleStartElement(element, attributes, augs);
 742         // call handlers
 743         if (fDocumentHandler != null) {
 744             fDocumentHandler.startElement(element, attributes, modifiedAugs);
 745         }
 746 
 747     } // startElement(QName,XMLAttributes, Augmentations)
 748 
 749     /**
 750      * An empty element.
 751      *
 752      * @param element    The name of the element.
 753      * @param attributes The element attributes.
 754      * @param augs     Additional information that may include infoset augmentations
 755      *
 756      * @throws XNIException Thrown by handler to signal an error.
 757      */
 758     public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs)
 759         throws XNIException {
 760 
 761         Augmentations modifiedAugs = handleStartElement(element, attributes, augs);
 762 
 763         // in the case where there is a {value constraint}, and the element
 764         // doesn't have any text content, change emptyElement call to
 765         // start + characters + end
 766         fDefaultValue = null;
 767         // fElementDepth == -2 indicates that the schema validator was removed
 768         // from the pipeline. then we don't need to call handleEndElement.
 769         if (fElementDepth != -2)
 770             modifiedAugs = handleEndElement(element, modifiedAugs);
 771 
 772         // call handlers
 773         if (fDocumentHandler != null) {
 774             if (!fSchemaElementDefault || fDefaultValue == null) {
 775                 fDocumentHandler.emptyElement(element, attributes, modifiedAugs);
 776             } else {
 777                 fDocumentHandler.startElement(element, attributes, modifiedAugs);
 778                 fDocumentHandler.characters(fDefaultValue, null);
 779                 fDocumentHandler.endElement(element, modifiedAugs);
 780             }
 781         }
 782     } // emptyElement(QName,XMLAttributes, Augmentations)
 783 
 784     /**
 785      * Character content.
 786      *
 787      * @param text The content.
 788      * @param augs     Additional information that may include infoset augmentations
 789      *
 790      * @throws XNIException Thrown by handler to signal an error.
 791      */
 792     public void characters(XMLString text, Augmentations augs) throws XNIException {
 793         text = handleCharacters(text);
 794 
 795         if (fSawOnlyWhitespaceInElementContent) {
 796             fSawOnlyWhitespaceInElementContent = false;
 797             if (!reportWhitespace) {
 798                 ignorableWhitespace(text, augs);
 799                 return;
 800             }
 801         }
 802 
 803         // call handlers
 804         if (fDocumentHandler != null) {
 805             if (fNormalizeData && fUnionType) {
 806                 // for union types we can't normalize data
 807                 // thus we only need to send augs information if any;
 808                 // the normalized data for union will be send
 809                 // after normalization is performed (at the endElement())
 810                 if (augs != null)
 811                     fDocumentHandler.characters(fEmptyXMLStr, augs);
 812             } else {
 813                 fDocumentHandler.characters(text, augs);
 814             }
 815         }
 816 
 817     } // characters(XMLString)
 818 
 819     /**
 820      * Ignorable whitespace. For this method to be called, the document
 821      * source must have some way of determining that the text containing
 822      * only whitespace characters should be considered ignorable. For
 823      * example, the validator can determine if a length of whitespace
 824      * characters in the document are ignorable based on the element
 825      * content model.
 826      *
 827      * @param text The ignorable whitespace.
 828      * @param augs     Additional information that may include infoset augmentations
 829      *
 830      * @throws XNIException Thrown by handler to signal an error.
 831      */
 832     public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
 833         handleIgnorableWhitespace(text);
 834         // call handlers
 835         if (fDocumentHandler != null) {
 836             fDocumentHandler.ignorableWhitespace(text, augs);
 837         }
 838 
 839     } // ignorableWhitespace(XMLString)
 840 
 841     /**
 842      * The end of an element.
 843      *
 844      * @param element The name of the element.
 845      * @param augs     Additional information that may include infoset augmentations
 846      *
 847      * @throws XNIException Thrown by handler to signal an error.
 848      */
 849     public void endElement(QName element, Augmentations augs) throws XNIException {
 850 
 851         // in the case where there is a {value constraint}, and the element
 852         // doesn't have any text content, add a characters call.
 853         fDefaultValue = null;
 854         Augmentations modifiedAugs = handleEndElement(element, augs);
 855         // call handlers
 856         if (fDocumentHandler != null) {
 857             if (!fSchemaElementDefault || fDefaultValue == null) {
 858                 fDocumentHandler.endElement(element, modifiedAugs);
 859             } else {
 860                 fDocumentHandler.characters(fDefaultValue, null);
 861                 fDocumentHandler.endElement(element, modifiedAugs);
 862             }
 863         }
 864     } // endElement(QName, Augmentations)
 865 
 866     /**
 867     * The start of a CDATA section.
 868     *
 869     * @param augs     Additional information that may include infoset augmentations
 870     *
 871     * @throws XNIException Thrown by handler to signal an error.
 872     */
 873     public void startCDATA(Augmentations augs) throws XNIException {
 874 
 875         // REVISIT: what should we do here if schema normalization is on??
 876         fInCDATA = true;
 877         // call handlers
 878         if (fDocumentHandler != null) {
 879             fDocumentHandler.startCDATA(augs);
 880         }
 881 
 882     } // startCDATA()
 883 
 884     /**
 885      * The end of a CDATA section.
 886      *
 887      * @param augs     Additional information that may include infoset augmentations
 888      *
 889      * @throws XNIException Thrown by handler to signal an error.
 890      */
 891     public void endCDATA(Augmentations augs) throws XNIException {
 892 
 893         // call handlers
 894         fInCDATA = false;
 895         if (fDocumentHandler != null) {
 896             fDocumentHandler.endCDATA(augs);
 897         }
 898 
 899     } // endCDATA()
 900 
 901     /**
 902      * The end of the document.
 903      *
 904      * @param augs     Additional information that may include infoset augmentations
 905      *
 906      * @throws XNIException Thrown by handler to signal an error.
 907      */
 908     public void endDocument(Augmentations augs) throws XNIException {
 909 
 910         handleEndDocument();
 911 
 912         // call handlers
 913         if (fDocumentHandler != null) {
 914             fDocumentHandler.endDocument(augs);
 915         }
 916         fLocator = null;
 917 
 918     } // endDocument(Augmentations)
 919 
 920     //
 921     // DOMRevalidationHandler methods
 922     //
 923 
 924 
 925 
 926 
 927 
 928     public boolean characterData(String data, Augmentations augs) {
 929 
 930         fSawText = fSawText || data.length() > 0;
 931 
 932         // REVISIT: this methods basically duplicates implementation of
 933         //          handleCharacters(). We should be able to reuse some code
 934 
 935         // if whitespace == -1 skip normalization, because it is a complexType
 936         // or a union type.
 937         if (fNormalizeData && fWhiteSpace != -1 && fWhiteSpace != XSSimpleType.WS_PRESERVE) {
 938             // normalize data
 939             normalizeWhitespace(data, fWhiteSpace == XSSimpleType.WS_COLLAPSE);
 940             fBuffer.append(fNormalizedStr.ch, fNormalizedStr.offset, fNormalizedStr.length);
 941         } else {
 942             if (fAppendBuffer)
 943                 fBuffer.append(data);
 944         }
 945 
 946         // When it's a complex type with element-only content, we need to
 947         // find out whether the content contains any non-whitespace character.
 948         boolean allWhiteSpace = true;
 949         if (fCurrentType != null
 950             && fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
 951             XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
 952             if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
 953                 // data outside of element content
 954                 for (int i = 0; i < data.length(); i++) {
 955                     if (!XMLChar.isSpace(data.charAt(i))) {
 956                         allWhiteSpace = false;
 957                         fSawCharacters = true;
 958                         break;
 959                     }
 960                 }
 961             }
 962         }
 963 
 964         return allWhiteSpace;
 965     }
 966 
 967     public void elementDefault(String data) {
 968         // no-op
 969     }
 970 
 971     //
 972     // XMLDocumentHandler and XMLDTDHandler methods
 973     //
 974 
 975     /**
 976      * This method notifies the start of a general entity.
 977      * <p>
 978      * <strong>Note:</strong> This method is not called for entity references
 979      * appearing as part of attribute values.
 980      *
 981      * @param name     The name of the general entity.
 982      * @param identifier The resource identifier.
 983      * @param encoding The auto-detected IANA encoding name of the entity
 984      *                 stream. This value will be null in those situations
 985      *                 where the entity encoding is not auto-detected (e.g.
 986      *                 internal entities or a document entity that is
 987      *                 parsed from a java.io.Reader).
 988      * @param augs     Additional information that may include infoset augmentations
 989      *
 990      * @exception XNIException Thrown by handler to signal an error.
 991      */
 992     public void startGeneralEntity(
 993         String name,
 994         XMLResourceIdentifier identifier,
 995         String encoding,
 996         Augmentations augs)
 997         throws XNIException {
 998 
 999         // REVISIT: what should happen if normalize_data_ is on??
1000         fEntityRef = true;
1001         // call handlers
1002         if (fDocumentHandler != null) {
1003             fDocumentHandler.startGeneralEntity(name, identifier, encoding, augs);
1004         }
1005 
1006     } // startEntity(String,String,String,String,String)
1007 
1008     /**
1009      * Notifies of the presence of a TextDecl line in an entity. If present,
1010      * this method will be called immediately following the startEntity call.
1011      * <p>
1012      * <strong>Note:</strong> This method will never be called for the
1013      * document entity; it is only called for external general entities
1014      * referenced in document content.
1015      * <p>
1016      * <strong>Note:</strong> This method is not called for entity references
1017      * appearing as part of attribute values.
1018      *
1019      * @param version  The XML version, or null if not specified.
1020      * @param encoding The IANA encoding name of the entity.
1021      * @param augs     Additional information that may include infoset augmentations
1022      *
1023      * @throws XNIException Thrown by handler to signal an error.
1024      */
1025     public void textDecl(String version, String encoding, Augmentations augs) throws XNIException {
1026 
1027         // call handlers
1028         if (fDocumentHandler != null) {
1029             fDocumentHandler.textDecl(version, encoding, augs);
1030         }
1031 
1032     } // textDecl(String,String)
1033 
1034     /**
1035      * A comment.
1036      *
1037      * @param text The text in the comment.
1038      * @param augs     Additional information that may include infoset augmentations
1039      *
1040      * @throws XNIException Thrown by application to signal an error.
1041      */
1042     public void comment(XMLString text, Augmentations augs) throws XNIException {
1043 
1044         // call handlers
1045         if (fDocumentHandler != null) {
1046             fDocumentHandler.comment(text, augs);
1047         }
1048 
1049     } // comment(XMLString)
1050 
1051     /**
1052      * A processing instruction. Processing instructions consist of a
1053      * target name and, optionally, text data. The data is only meaningful
1054      * to the application.
1055      * <p>
1056      * Typically, a processing instruction's data will contain a series
1057      * of pseudo-attributes. These pseudo-attributes follow the form of
1058      * element attributes but are <strong>not</strong> parsed or presented
1059      * to the application as anything other than text. The application is
1060      * responsible for parsing the data.
1061      *
1062      * @param target The target.
1063      * @param data   The data or null if none specified.
1064      * @param augs     Additional information that may include infoset augmentations
1065      *
1066      * @throws XNIException Thrown by handler to signal an error.
1067      */
1068     public void processingInstruction(String target, XMLString data, Augmentations augs)
1069         throws XNIException {
1070 
1071         // call handlers
1072         if (fDocumentHandler != null) {
1073             fDocumentHandler.processingInstruction(target, data, augs);
1074         }
1075 
1076     } // processingInstruction(String,XMLString)
1077 
1078     /**
1079      * This method notifies the end of a general entity.
1080      * <p>
1081      * <strong>Note:</strong> This method is not called for entity references
1082      * appearing as part of attribute values.
1083      *
1084      * @param name   The name of the entity.
1085      * @param augs   Additional information that may include infoset augmentations
1086      *
1087      * @exception XNIException
1088      *                   Thrown by handler to signal an error.
1089      */
1090     public void endGeneralEntity(String name, Augmentations augs) throws XNIException {
1091 
1092         // call handlers
1093         fEntityRef = false;
1094         if (fDocumentHandler != null) {
1095             fDocumentHandler.endGeneralEntity(name, augs);
1096         }
1097 
1098     } // endEntity(String)
1099 
1100     // constants
1101 
1102     static final int INITIAL_STACK_SIZE = 8;
1103     static final int INC_STACK_SIZE = 8;
1104 
1105     //
1106     // Data
1107     //
1108 
1109     // Schema Normalization
1110 
1111     private static final boolean DEBUG_NORMALIZATION = false;
1112     // temporary empty string buffer.
1113     private final XMLString fEmptyXMLStr = new XMLString(null, 0, -1);
1114     // temporary character buffer, and empty string buffer.
1115     private static final int BUFFER_SIZE = 20;
1116     private final XMLString fNormalizedStr = new XMLString();
1117     private boolean fFirstChunk = true;
1118     // got first chunk in characters() (SAX)
1119     private boolean fTrailing = false; // Previous chunk had a trailing space
1120     private short fWhiteSpace = -1; //whiteSpace: preserve/replace/collapse
1121     private boolean fUnionType = false;
1122 
1123     /** Schema grammar resolver. */
1124     private final XSGrammarBucket fGrammarBucket = new XSGrammarBucket();
1125     private final SubstitutionGroupHandler fSubGroupHandler = new SubstitutionGroupHandler(fGrammarBucket);
1126 
1127     /** the DV usd to convert xsi:type to a QName */
1128     // REVISIT: in new simple type design, make things in DVs static,
1129     //          so that we can QNameDV.getCompiledForm()
1130     private final XSSimpleType fQNameDV =
1131         (XSSimpleType) SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(SchemaSymbols.ATTVAL_QNAME);
1132 
1133     private final CMNodeFactory nodeFactory = new CMNodeFactory();
1134     /** used to build content models */
1135     // REVISIT: create decl pool, and pass it to each traversers
1136     private final CMBuilder fCMBuilder = new CMBuilder(nodeFactory);
1137 
1138     // Schema grammar loader
1139     private final XMLSchemaLoader fSchemaLoader =
1140         new XMLSchemaLoader(
1141                 fXSIErrorReporter.fErrorReporter,
1142                 fGrammarBucket,
1143                 fSubGroupHandler,
1144                 fCMBuilder);
1145 
1146     // state
1147 
1148     /** String representation of the validation root. */
1149     // REVISIT: what do we store here? QName, XPATH, some ID? use rawname now.
1150     private String fValidationRoot;
1151 
1152     /** Skip validation: anything below this level should be skipped */
1153     private int fSkipValidationDepth;
1154 
1155     /** anything above this level has validation_attempted != full */
1156     private int fNFullValidationDepth;
1157 
1158     /** anything above this level has validation_attempted != none */
1159     private int fNNoneValidationDepth;
1160 
1161     /** Element depth: -2: validator not in pipeline; >= -1 current depth. */
1162     private int fElementDepth;
1163 
1164     /** Seen sub elements. */
1165     private boolean fSubElement;
1166 
1167     /** Seen sub elements stack. */
1168     private boolean[] fSubElementStack = new boolean[INITIAL_STACK_SIZE];
1169 
1170     /** Current element declaration. */
1171     private XSElementDecl fCurrentElemDecl;
1172 
1173     /** Element decl stack. */
1174     private XSElementDecl[] fElemDeclStack = new XSElementDecl[INITIAL_STACK_SIZE];
1175 
1176     /** nil value of the current element */
1177     private boolean fNil;
1178 
1179     /** nil value stack */
1180     private boolean[] fNilStack = new boolean[INITIAL_STACK_SIZE];
1181 
1182     /** notation value of the current element */
1183     private XSNotationDecl fNotation;
1184 
1185     /** notation stack */
1186     private XSNotationDecl[] fNotationStack = new XSNotationDecl[INITIAL_STACK_SIZE];
1187 
1188     /** Current type. */
1189     private XSTypeDefinition fCurrentType;
1190 
1191     /** type stack. */
1192     private XSTypeDefinition[] fTypeStack = new XSTypeDefinition[INITIAL_STACK_SIZE];
1193 
1194     /** Current content model. */
1195     private XSCMValidator fCurrentCM;
1196 
1197     /** Content model stack. */
1198     private XSCMValidator[] fCMStack = new XSCMValidator[INITIAL_STACK_SIZE];
1199 
1200     /** the current state of the current content model */
1201     private int[] fCurrCMState;
1202 
1203     /** stack to hold content model states */
1204     private int[][] fCMStateStack = new int[INITIAL_STACK_SIZE][];
1205 
1206     /** whether the curret element is strictly assessed */
1207     private boolean fStrictAssess = true;
1208 
1209     /** strict assess stack */
1210     private boolean[] fStrictAssessStack = new boolean[INITIAL_STACK_SIZE];
1211 
1212     /** Temporary string buffers. */
1213     private final StringBuffer fBuffer = new StringBuffer();
1214 
1215     /** Whether need to append characters to fBuffer */
1216     private boolean fAppendBuffer = true;
1217 
1218     /** Did we see any character data? */
1219     private boolean fSawText = false;
1220 
1221     /** stack to record if we saw character data */
1222     private boolean[] fSawTextStack = new boolean[INITIAL_STACK_SIZE];
1223 
1224     /** Did we see non-whitespace character data? */
1225     private boolean fSawCharacters = false;
1226 
1227     /** Stack to record if we saw character data outside of element content*/
1228     private boolean[] fStringContent = new boolean[INITIAL_STACK_SIZE];
1229 
1230     /** temporary qname */
1231     private final QName fTempQName = new QName();
1232 
1233     /** temporary validated info */
1234     private ValidatedInfo fValidatedInfo = new ValidatedInfo();
1235 
1236     // used to validate default/fixed values against xsi:type
1237     // only need to check facets, so we set extraChecking to false (in reset)
1238     private ValidationState fState4XsiType = new ValidationState();
1239 
1240     // used to apply default/fixed values
1241     // only need to check id/idref/entity, so we set checkFacets to false
1242     private ValidationState fState4ApplyDefault = new ValidationState();
1243 
1244     // identity constraint information
1245 
1246     /**
1247      * Stack of active XPath matchers for identity constraints. All
1248      * active XPath matchers are notified of startElement
1249      * and endElement callbacks in order to perform their matches.
1250      * <p>
1251      * For each element with identity constraints, the selector of
1252      * each identity constraint is activated. When the selector matches
1253      * its XPath, then all the fields of the identity constraint are
1254      * activated.
1255      * <p>
1256      * <strong>Note:</strong> Once the activation scope is left, the
1257      * XPath matchers are automatically removed from the stack of
1258      * active matchers and no longer receive callbacks.
1259      */
1260     protected XPathMatcherStack fMatcherStack = new XPathMatcherStack();
1261 
1262     /** Cache of value stores for identity constraint fields. */
1263     protected ValueStoreCache fValueStoreCache = new ValueStoreCache();
1264 
1265     //
1266     // Constructors
1267     //
1268 
1269     /** Default constructor. */
1270     public XMLSchemaValidator() {
1271         fState4XsiType.setExtraChecking(false);
1272         fState4ApplyDefault.setFacetChecking(false);
1273 
1274     } // <init>()
1275 
1276     /*
1277      * Resets the component. The component can query the component manager
1278      * about any features and properties that affect the operation of the
1279      * component.
1280      *
1281      * @param componentManager The component manager.
1282      *
1283      * @throws SAXException Thrown by component on finitialization error.
1284      *                      For example, if a feature or property is
1285      *                      required for the operation of the component, the
1286      *                      component manager may throw a
1287      *                      SAXNotRecognizedException or a
1288      *                      SAXNotSupportedException.
1289      */
1290     public void reset(XMLComponentManager componentManager) throws XMLConfigurationException {
1291 
1292 
1293         fIdConstraint = false;
1294         //reset XSDDescription
1295         fLocationPairs.clear();
1296 
1297         // cleanup id table
1298         fValidationState.resetIDTables();
1299 
1300         //pass the component manager to the factory..
1301         nodeFactory.reset(componentManager);
1302 
1303         // reset schema loader
1304         fSchemaLoader.reset(componentManager);
1305 
1306         // initialize state
1307         fCurrentElemDecl = null;
1308         fCurrentCM = null;
1309         fCurrCMState = null;
1310         fSkipValidationDepth = -1;
1311         fNFullValidationDepth = -1;
1312         fNNoneValidationDepth = -1;
1313         fElementDepth = -1;
1314         fSubElement = false;
1315         fSchemaDynamicValidation = false;
1316 
1317         // datatype normalization
1318         fEntityRef = false;
1319         fInCDATA = false;
1320 
1321         fMatcherStack.clear();
1322 
1323         if (!fMayMatchFieldMap.isEmpty()) {
1324             // should only clear this if the last schema had identity constraints.
1325             fMayMatchFieldMap.clear();
1326         }
1327 
1328         // get error reporter
1329         fXSIErrorReporter.reset((XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER));
1330 
1331         boolean parser_settings = componentManager.getFeature(PARSER_SETTINGS, true);
1332 
1333         if (!parser_settings){
1334             // parser settings have not been changed
1335             fValidationManager.addValidationState(fValidationState);
1336             // Re-parse external schema location properties.
1337             XMLSchemaLoader.processExternalHints(
1338                 fExternalSchemas,
1339                 fExternalNoNamespaceSchema,
1340                 fLocationPairs,
1341                 fXSIErrorReporter.fErrorReporter);
1342             return;
1343         }
1344 
1345 
1346         // get symbol table. if it's a new one, add symbols to it.
1347         SymbolTable symbolTable = (SymbolTable) componentManager.getProperty(SYMBOL_TABLE);
1348         if (symbolTable != fSymbolTable) {
1349             fSymbolTable = symbolTable;
1350         }
1351 
1352         fNamespaceGrowth = componentManager.getFeature(NAMESPACE_GROWTH, false);
1353         fDynamicValidation = componentManager.getFeature(DYNAMIC_VALIDATION, false);
1354 
1355         if (fDynamicValidation) {
1356             fDoValidation = true;
1357         } else {
1358             fDoValidation = componentManager.getFeature(VALIDATION, false);
1359         }
1360 
1361         if (fDoValidation) {
1362             fDoValidation |= componentManager.getFeature(XMLSchemaValidator.SCHEMA_VALIDATION, false);
1363         }
1364 
1365         fFullChecking = componentManager.getFeature(SCHEMA_FULL_CHECKING, false);
1366         fNormalizeData = componentManager.getFeature(NORMALIZE_DATA, false);
1367         fSchemaElementDefault = componentManager.getFeature(SCHEMA_ELEMENT_DEFAULT, false);
1368 
1369         fAugPSVI = componentManager.getFeature(SCHEMA_AUGMENT_PSVI, true);
1370 
1371         fSchemaType =
1372                 (String) componentManager.getProperty(
1373                     Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE, null);
1374 
1375         fUseGrammarPoolOnly = componentManager.getFeature(USE_GRAMMAR_POOL_ONLY, false);
1376 
1377         fEntityResolver = (XMLEntityResolver) componentManager.getProperty(ENTITY_MANAGER);
1378 
1379         fValidationManager = (ValidationManager) componentManager.getProperty(VALIDATION_MANAGER);
1380         fValidationManager.addValidationState(fValidationState);
1381         fValidationState.setSymbolTable(fSymbolTable);
1382 
1383 
1384         // get schema location properties
1385         try {
1386             fExternalSchemas = (String) componentManager.getProperty(SCHEMA_LOCATION);
1387             fExternalNoNamespaceSchema =
1388                 (String) componentManager.getProperty(SCHEMA_NONS_LOCATION);
1389         } catch (XMLConfigurationException e) {
1390             fExternalSchemas = null;
1391             fExternalNoNamespaceSchema = null;
1392         }
1393 
1394         // store the external schema locations. they are set when reset is called,
1395         // so any other schemaLocation declaration for the same namespace will be
1396         // effectively ignored. becuase we choose to take first location hint
1397         // available for a particular namespace.
1398         XMLSchemaLoader.processExternalHints(
1399             fExternalSchemas,
1400             fExternalNoNamespaceSchema,
1401             fLocationPairs,
1402             fXSIErrorReporter.fErrorReporter);
1403 
1404         fJaxpSchemaSource = componentManager.getProperty(JAXP_SCHEMA_SOURCE, null);
1405 
1406         // clear grammars, and put the one for schema namespace there
1407         fGrammarPool = (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL, null);
1408 
1409         fState4XsiType.setSymbolTable(symbolTable);
1410         fState4ApplyDefault.setSymbolTable(symbolTable);
1411 
1412     } // reset(XMLComponentManager)
1413 
1414     //
1415     // FieldActivator methods
1416     //
1417 
1418     /**
1419      * Start the value scope for the specified identity constraint. This
1420      * method is called when the selector matches in order to initialize
1421      * the value store.
1422      *
1423      * @param identityConstraint The identity constraint.
1424      */
1425     public void startValueScopeFor(IdentityConstraint identityConstraint, int initialDepth) {
1426 
1427         ValueStoreBase valueStore =
1428             fValueStoreCache.getValueStoreFor(identityConstraint, initialDepth);
1429         valueStore.startValueScope();
1430 
1431     } // startValueScopeFor(IdentityConstraint identityConstraint)
1432 
1433     /**
1434      * Request to activate the specified field. This method returns the
1435      * matcher for the field.
1436      *
1437      * @param field The field to activate.
1438      */
1439     public XPathMatcher activateField(Field field, int initialDepth) {
1440         ValueStore valueStore =
1441             fValueStoreCache.getValueStoreFor(field.getIdentityConstraint(), initialDepth);
1442         setMayMatch(field, Boolean.TRUE);
1443         XPathMatcher matcher = field.createMatcher(this, valueStore);
1444         fMatcherStack.addMatcher(matcher);
1445         matcher.startDocumentFragment();
1446         return matcher;
1447     } // activateField(Field):XPathMatcher
1448 
1449     /**
1450      * Ends the value scope for the specified identity constraint.
1451      *
1452      * @param identityConstraint The identity constraint.
1453      */
1454     public void endValueScopeFor(IdentityConstraint identityConstraint, int initialDepth) {
1455 
1456         ValueStoreBase valueStore =
1457             fValueStoreCache.getValueStoreFor(identityConstraint, initialDepth);
1458         valueStore.endValueScope();
1459 
1460     } // endValueScopeFor(IdentityConstraint)
1461 
1462     /**
1463      * Sets whether the given field is permitted to match a value.
1464      * This should be used to catch instance documents that try
1465      * and match a field several times in the same scope.
1466      *
1467      * @param field The field that may be permitted to be matched.
1468      * @param state Boolean indiciating whether the field may be matched.
1469      */
1470     public void setMayMatch(Field field, Boolean state) {
1471         fMayMatchFieldMap.put(field, state);
1472     } // setMayMatch(Field, Boolean)
1473 
1474     /**
1475      * Returns whether the given field is permitted to match a value.
1476      *
1477      * @param field The field that may be permitted to be matched.
1478      * @return Boolean indicating whether the field may be matched.
1479      */
1480     public Boolean mayMatch(Field field) {
1481         return (Boolean) fMayMatchFieldMap.get(field);
1482     } // mayMatch(Field):Boolean
1483 
1484     // a utility method for Identity constraints
1485     private void activateSelectorFor(IdentityConstraint ic) {
1486         Selector selector = ic.getSelector();
1487         FieldActivator activator = this;
1488         if (selector == null)
1489             return;
1490         XPathMatcher matcher = selector.createMatcher(activator, fElementDepth);
1491         fMatcherStack.addMatcher(matcher);
1492         matcher.startDocumentFragment();
1493     }
1494 
1495     //
1496     // Protected methods
1497     //
1498 
1499     /** ensure element stack capacity */
1500     void ensureStackCapacity() {
1501 
1502         if (fElementDepth == fElemDeclStack.length) {
1503             int newSize = fElementDepth + INC_STACK_SIZE;
1504             boolean[] newArrayB = new boolean[newSize];
1505             System.arraycopy(fSubElementStack, 0, newArrayB, 0, fElementDepth);
1506             fSubElementStack = newArrayB;
1507 
1508             XSElementDecl[] newArrayE = new XSElementDecl[newSize];
1509             System.arraycopy(fElemDeclStack, 0, newArrayE, 0, fElementDepth);
1510             fElemDeclStack = newArrayE;
1511 
1512             newArrayB = new boolean[newSize];
1513             System.arraycopy(fNilStack, 0, newArrayB, 0, fElementDepth);
1514             fNilStack = newArrayB;
1515 
1516             XSNotationDecl[] newArrayN = new XSNotationDecl[newSize];
1517             System.arraycopy(fNotationStack, 0, newArrayN, 0, fElementDepth);
1518             fNotationStack = newArrayN;
1519 
1520             XSTypeDefinition[] newArrayT = new XSTypeDefinition[newSize];
1521             System.arraycopy(fTypeStack, 0, newArrayT, 0, fElementDepth);
1522             fTypeStack = newArrayT;
1523 
1524             XSCMValidator[] newArrayC = new XSCMValidator[newSize];
1525             System.arraycopy(fCMStack, 0, newArrayC, 0, fElementDepth);
1526             fCMStack = newArrayC;
1527 
1528             newArrayB = new boolean[newSize];
1529             System.arraycopy(fSawTextStack, 0, newArrayB, 0, fElementDepth);
1530             fSawTextStack = newArrayB;
1531 
1532             newArrayB = new boolean[newSize];
1533             System.arraycopy(fStringContent, 0, newArrayB, 0, fElementDepth);
1534             fStringContent = newArrayB;
1535 
1536             newArrayB = new boolean[newSize];
1537             System.arraycopy(fStrictAssessStack, 0, newArrayB, 0, fElementDepth);
1538             fStrictAssessStack = newArrayB;
1539 
1540             int[][] newArrayIA = new int[newSize][];
1541             System.arraycopy(fCMStateStack, 0, newArrayIA, 0, fElementDepth);
1542             fCMStateStack = newArrayIA;
1543         }
1544 
1545     } // ensureStackCapacity
1546 
1547     // handle start document
1548     void handleStartDocument(XMLLocator locator, String encoding) {
1549         fValueStoreCache.startDocument();
1550         if (fAugPSVI) {
1551             fCurrentPSVI.fGrammars = null;
1552             fCurrentPSVI.fSchemaInformation = null;
1553         }
1554     } // handleStartDocument(XMLLocator,String)
1555 
1556     void handleEndDocument() {
1557         fValueStoreCache.endDocument();
1558     } // handleEndDocument()
1559 
1560     // handle character contents
1561     // returns the normalized string if possible, otherwise the original string
1562     XMLString handleCharacters(XMLString text) {
1563 
1564         if (fSkipValidationDepth >= 0)
1565             return text;
1566 
1567         fSawText = fSawText || text.length > 0;
1568 
1569         // Note: data in EntityRef and CDATA is normalized as well
1570         // if whitespace == -1 skip normalization, because it is a complexType
1571         // or a union type.
1572         if (fNormalizeData && fWhiteSpace != -1 && fWhiteSpace != XSSimpleType.WS_PRESERVE) {
1573             // normalize data
1574             normalizeWhitespace(text, fWhiteSpace == XSSimpleType.WS_COLLAPSE);
1575             text = fNormalizedStr;
1576         }
1577         if (fAppendBuffer)
1578             fBuffer.append(text.ch, text.offset, text.length);
1579 
1580         // When it's a complex type with element-only content, we need to
1581         // find out whether the content contains any non-whitespace character.
1582         fSawOnlyWhitespaceInElementContent = false;
1583         if (fCurrentType != null
1584             && fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
1585             XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
1586             if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
1587                 // data outside of element content
1588                 for (int i = text.offset; i < text.offset + text.length; i++) {
1589                     if (!XMLChar.isSpace(text.ch[i])) {
1590                         fSawCharacters = true;
1591                         break;
1592                     }
1593                     fSawOnlyWhitespaceInElementContent = !fSawCharacters;
1594                 }
1595             }
1596         }
1597 
1598         return text;
1599     } // handleCharacters(XMLString)
1600 
1601     /**
1602      * Normalize whitespace in an XMLString according to the rules defined
1603      * in XML Schema specifications.
1604      * @param value    The string to normalize.
1605      * @param collapse replace or collapse
1606      */
1607     private void normalizeWhitespace(XMLString value, boolean collapse) {
1608         boolean skipSpace = collapse;
1609         boolean sawNonWS = false;
1610         boolean leading = false;
1611         boolean trailing = false;
1612         char c;
1613         int size = value.offset + value.length;
1614 
1615         // ensure the ch array is big enough
1616         if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < value.length + 1) {
1617             fNormalizedStr.ch = new char[value.length + 1];
1618         }
1619         // don't include the leading ' ' for now. might include it later.
1620         fNormalizedStr.offset = 1;
1621         fNormalizedStr.length = 1;
1622 
1623         for (int i = value.offset; i < size; i++) {
1624             c = value.ch[i];
1625             if (XMLChar.isSpace(c)) {
1626                 if (!skipSpace) {
1627                     // take the first whitespace as a space and skip the others
1628                     fNormalizedStr.ch[fNormalizedStr.length++] = ' ';
1629                     skipSpace = collapse;
1630                 }
1631                 if (!sawNonWS) {
1632                     // this is a leading whitespace, record it
1633                     leading = true;
1634                 }
1635             } else {
1636                 fNormalizedStr.ch[fNormalizedStr.length++] = c;
1637                 skipSpace = false;
1638                 sawNonWS = true;
1639             }
1640         }
1641         if (skipSpace) {
1642             if (fNormalizedStr.length > 1) {
1643                 // if we finished on a space trim it but also record it
1644                 fNormalizedStr.length--;
1645                 trailing = true;
1646             } else if (leading && !fFirstChunk) {
1647                 // if all we had was whitespace we skipped record it as
1648                 // trailing whitespace as well
1649                 trailing = true;
1650             }
1651         }
1652 
1653         if (fNormalizedStr.length > 1) {
1654             if (!fFirstChunk && (fWhiteSpace == XSSimpleType.WS_COLLAPSE)) {
1655                 if (fTrailing) {
1656                     // previous chunk ended on whitespace
1657                     // insert whitespace
1658                     fNormalizedStr.offset = 0;
1659                     fNormalizedStr.ch[0] = ' ';
1660                 } else if (leading) {
1661                     // previous chunk ended on character,
1662                     // this chunk starts with whitespace
1663                     fNormalizedStr.offset = 0;
1664                     fNormalizedStr.ch[0] = ' ';
1665                 }
1666             }
1667         }
1668 
1669         // The length includes the leading ' '. Now removing it.
1670         fNormalizedStr.length -= fNormalizedStr.offset;
1671 
1672         fTrailing = trailing;
1673 
1674         if (trailing || sawNonWS)
1675             fFirstChunk = false;
1676     }
1677 
1678     private void normalizeWhitespace(String value, boolean collapse) {
1679         boolean skipSpace = collapse;
1680         char c;
1681         int size = value.length();
1682 
1683         // ensure the ch array is big enough
1684         if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < size) {
1685             fNormalizedStr.ch = new char[size];
1686         }
1687         fNormalizedStr.offset = 0;
1688         fNormalizedStr.length = 0;
1689 
1690         for (int i = 0; i < size; i++) {
1691             c = value.charAt(i);
1692             if (XMLChar.isSpace(c)) {
1693                 if (!skipSpace) {
1694                     // take the first whitespace as a space and skip the others
1695                     fNormalizedStr.ch[fNormalizedStr.length++] = ' ';
1696                     skipSpace = collapse;
1697                 }
1698             } else {
1699                 fNormalizedStr.ch[fNormalizedStr.length++] = c;
1700                 skipSpace = false;
1701             }
1702         }
1703         if (skipSpace) {
1704             if (fNormalizedStr.length != 0)
1705                 // if we finished on a space trim it but also record it
1706                 fNormalizedStr.length--;
1707         }
1708     }
1709 
1710     // handle ignorable whitespace
1711     void handleIgnorableWhitespace(XMLString text) {
1712 
1713         if (fSkipValidationDepth >= 0)
1714             return;
1715 
1716         // REVISIT: the same process needs to be performed as handleCharacters.
1717         // only it's simpler here: we know all characters are whitespaces.
1718 
1719     } // handleIgnorableWhitespace(XMLString)
1720 
1721     /** Handle element. */
1722     Augmentations handleStartElement(QName element, XMLAttributes attributes, Augmentations augs) {
1723 
1724         if (DEBUG) {
1725             System.out.println("==>handleStartElement: " + element);
1726         }
1727 
1728         // root element
1729         if (fElementDepth == -1 && fValidationManager.isGrammarFound()) {
1730             if (fSchemaType == null) {
1731                 // schemaType is not specified
1732                 // if a DTD grammar is found, we do the same thing as Dynamic:
1733                 // if a schema grammar is found, validation is performed;
1734                 // otherwise, skip the whole document.
1735                 fSchemaDynamicValidation = true;
1736             } else {
1737                 // [1] Either schemaType is DTD, and in this case validate/schema is turned off
1738                 // [2] Validating against XML Schemas only
1739                 //   [a] dynamic validation is false: report error if SchemaGrammar is not found
1740                 //   [b] dynamic validation is true: if grammar is not found ignore.
1741             }
1742 
1743         }
1744 
1745         // get xsi:schemaLocation and xsi:noNamespaceSchemaLocation attributes,
1746         // parse them to get the grammars
1747 
1748         String sLocation =
1749             attributes.getValue(SchemaSymbols.URI_XSI, SchemaSymbols.XSI_SCHEMALOCATION);
1750         String nsLocation =
1751             attributes.getValue(SchemaSymbols.URI_XSI, SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION);
1752         //store the location hints..  we need to do it so that we can defer the loading of grammar until
1753         //there is a reference to a component from that namespace. To provide location hints to the
1754         //application for a namespace
1755         storeLocations(sLocation, nsLocation);
1756 
1757         // if we are in the content of "skip", then just skip this element
1758         // REVISIT:  is this the correct behaviour for ID constraints?  -NG
1759         if (fSkipValidationDepth >= 0) {
1760             fElementDepth++;
1761             if (fAugPSVI)
1762                 augs = getEmptyAugs(augs);
1763             return augs;
1764         }
1765 
1766         //try to find schema grammar by different means..
1767         SchemaGrammar sGrammar =
1768             findSchemaGrammar(
1769                 XSDDescription.CONTEXT_ELEMENT,
1770                 element.uri,
1771                 null,
1772                 element,
1773                 attributes);
1774 
1775         // if we are not skipping this element, and there is a content model,
1776         // we try to find the corresponding decl object for this element.
1777         // the reason we move this part of code here is to make sure the
1778         // error reported here (if any) is stored within the parent element's
1779         // context, instead of that of the current element.
1780         Object decl = null;
1781         if (fCurrentCM != null) {
1782             decl = fCurrentCM.oneTransition(element, fCurrCMState, fSubGroupHandler);
1783             // it could be an element decl or a wildcard decl
1784             if (fCurrCMState[0] == XSCMValidator.FIRST_ERROR) {
1785                 XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
1786                 //REVISIT: is it the only case we will have particle = null?
1787                 Vector next;
1788                 if (ctype.fParticle != null
1789                     && (next = fCurrentCM.whatCanGoHere(fCurrCMState)).size() > 0) {
1790                     String expected = expectedStr(next);
1791                     reportSchemaError(
1792                         "cvc-complex-type.2.4.a",
1793                         new Object[] { element.rawname, expected });
1794                 } else {
1795                     reportSchemaError("cvc-complex-type.2.4.d", new Object[] { element.rawname });
1796                 }
1797             }
1798         }
1799 
1800         // if it's not the root element, we push the current states in the stacks
1801         if (fElementDepth != -1) {
1802             ensureStackCapacity();
1803             fSubElementStack[fElementDepth] = true;
1804             fSubElement = false;
1805             fElemDeclStack[fElementDepth] = fCurrentElemDecl;
1806             fNilStack[fElementDepth] = fNil;
1807             fNotationStack[fElementDepth] = fNotation;
1808             fTypeStack[fElementDepth] = fCurrentType;
1809             fStrictAssessStack[fElementDepth] = fStrictAssess;
1810             fCMStack[fElementDepth] = fCurrentCM;
1811             fCMStateStack[fElementDepth] = fCurrCMState;
1812             fSawTextStack[fElementDepth] = fSawText;
1813             fStringContent[fElementDepth] = fSawCharacters;
1814         }
1815 
1816         // increase the element depth after we've saved
1817         // all states for the parent element
1818         fElementDepth++;
1819         fCurrentElemDecl = null;
1820         XSWildcardDecl wildcard = null;
1821         fCurrentType = null;
1822         fStrictAssess = true;
1823         fNil = false;
1824         fNotation = null;
1825 
1826         // and the buffer to hold the value of the element
1827         fBuffer.setLength(0);
1828         fSawText = false;
1829         fSawCharacters = false;
1830 
1831         // check what kind of declaration the "decl" from
1832         // oneTransition() maps to
1833         if (decl != null) {
1834             if (decl instanceof XSElementDecl) {
1835                 fCurrentElemDecl = (XSElementDecl) decl;
1836             } else {
1837                 wildcard = (XSWildcardDecl) decl;
1838             }
1839         }
1840 
1841         // if the wildcard is skip, then return
1842         if (wildcard != null && wildcard.fProcessContents == XSWildcardDecl.PC_SKIP) {
1843             fSkipValidationDepth = fElementDepth;
1844             if (fAugPSVI)
1845                 augs = getEmptyAugs(augs);
1846             return augs;
1847         }
1848 
1849         // try again to get the element decl:
1850         // case 1: find declaration for root element
1851         // case 2: find declaration for element from another namespace
1852         if (fCurrentElemDecl == null) {
1853             if (sGrammar != null) {
1854                 fCurrentElemDecl = sGrammar.getGlobalElementDecl(element.localpart);
1855             }
1856         }
1857 
1858         if (fCurrentElemDecl != null) {
1859             // then get the type
1860             fCurrentType = fCurrentElemDecl.fType;
1861         }
1862 
1863         // get type from xsi:type
1864         String xsiType = attributes.getValue(SchemaSymbols.URI_XSI, SchemaSymbols.XSI_TYPE);
1865 
1866         // if no decl/type found for the current element
1867         if (fCurrentType == null && xsiType == null) {
1868             // if this is the validation root, report an error, because
1869             // we can't find eith decl or type for this element
1870             // REVISIT: should we report error, or warning?
1871             if (fElementDepth == 0) {
1872                 // for dynamic validation, skip the whole content,
1873                 // because no grammar was found.
1874                 if (fDynamicValidation || fSchemaDynamicValidation) {
1875                     // no schema grammar was found, but it's either dynamic
1876                     // validation, or another kind of grammar was found (DTD,
1877                     // for example). The intended behavior here is to skip
1878                     // the whole document. To improve performance, we try to
1879                     // remove the validator from the pipeline, since it's not
1880                     // supposed to do anything.
1881                     if (fDocumentSource != null) {
1882                         fDocumentSource.setDocumentHandler(fDocumentHandler);
1883                         if (fDocumentHandler != null)
1884                             fDocumentHandler.setDocumentSource(fDocumentSource);
1885                         // indicate that the validator was removed.
1886                         fElementDepth = -2;
1887                         return augs;
1888                     }
1889 
1890                     fSkipValidationDepth = fElementDepth;
1891                     if (fAugPSVI)
1892                         augs = getEmptyAugs(augs);
1893                     return augs;
1894                 }
1895                 // We don't call reportSchemaError here, because the spec
1896                 // doesn't think it's invalid not to be able to find a
1897                 // declaration or type definition for an element. Xerces is
1898                 // reporting it as an error for historical reasons, but in
1899                 // PSVI, we shouldn't mark this element as invalid because
1900                 // of this. - SG
1901                 fXSIErrorReporter.fErrorReporter.reportError(
1902                     XSMessageFormatter.SCHEMA_DOMAIN,
1903                     "cvc-elt.1",
1904                     new Object[] { element.rawname },
1905                     XMLErrorReporter.SEVERITY_ERROR);
1906             }
1907             // if wildcard = strict, report error.
1908             // needs to be called before fXSIErrorReporter.pushContext()
1909             // so that the error belongs to the parent element.
1910             else if (wildcard != null && wildcard.fProcessContents == XSWildcardDecl.PC_STRICT) {
1911                 // report error, because wilcard = strict
1912                 reportSchemaError("cvc-complex-type.2.4.c", new Object[] { element.rawname });
1913             }
1914             // no element decl or type found for this element.
1915             // Allowed by the spec, we can choose to either laxly assess this
1916             // element, or to skip it. Now we choose lax assessment.
1917             fCurrentType = SchemaGrammar.fAnyType;
1918             fStrictAssess = false;
1919             fNFullValidationDepth = fElementDepth;
1920             // any type has mixed content, so we don't need to append buffer
1921             fAppendBuffer = false;
1922 
1923             // push error reporter context: record the current position
1924             // This has to happen after we process skip contents,
1925             // otherwise push and pop won't be correctly paired.
1926             fXSIErrorReporter.pushContext();
1927         } else {
1928             // push error reporter context: record the current position
1929             // This has to happen after we process skip contents,
1930             // otherwise push and pop won't be correctly paired.
1931             fXSIErrorReporter.pushContext();
1932 
1933             // get xsi:type
1934             if (xsiType != null) {
1935                 XSTypeDefinition oldType = fCurrentType;
1936                 fCurrentType = getAndCheckXsiType(element, xsiType, attributes);
1937                 // If it fails, use the old type. Use anyType if ther is no old type.
1938                 if (fCurrentType == null) {
1939                     if (oldType == null)
1940                         fCurrentType = SchemaGrammar.fAnyType;
1941                     else
1942                         fCurrentType = oldType;
1943                 }
1944             }
1945 
1946             fNNoneValidationDepth = fElementDepth;
1947             // if the element has a fixed value constraint, we need to append
1948             if (fCurrentElemDecl != null
1949                 && fCurrentElemDecl.getConstraintType() == XSConstants.VC_FIXED) {
1950                 fAppendBuffer = true;
1951             }
1952             // if the type is simple, we need to append
1953             else if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
1954                 fAppendBuffer = true;
1955             } else {
1956                 // if the type is simple content complex type, we need to append
1957                 XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
1958                 fAppendBuffer = (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE);
1959             }
1960         }
1961 
1962         // Element Locally Valid (Element)
1963         // 2 Its {abstract} must be false.
1964         if (fCurrentElemDecl != null && fCurrentElemDecl.getAbstract())
1965             reportSchemaError("cvc-elt.2", new Object[] { element.rawname });
1966 
1967         // make the current element validation root
1968         if (fElementDepth == 0) {
1969             fValidationRoot = element.rawname;
1970         }
1971 
1972         // update normalization flags
1973         if (fNormalizeData) {
1974             // reset values
1975             fFirstChunk = true;
1976             fTrailing = false;
1977             fUnionType = false;
1978             fWhiteSpace = -1;
1979         }
1980 
1981         // Element Locally Valid (Type)
1982         // 2 Its {abstract} must be false.
1983         if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
1984             XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
1985             if (ctype.getAbstract()) {
1986                 reportSchemaError("cvc-type.2", new Object[] { element.rawname });
1987             }
1988             if (fNormalizeData) {
1989                 // find out if the content type is simple and if variety is union
1990                 // to be able to do character normalization
1991                 if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
1992                     if (ctype.fXSSimpleType.getVariety() == XSSimpleType.VARIETY_UNION) {
1993                         fUnionType = true;
1994                     } else {
1995                         try {
1996                             fWhiteSpace = ctype.fXSSimpleType.getWhitespace();
1997                         } catch (DatatypeException e) {
1998                             // do nothing
1999                         }
2000                     }
2001                 }
2002             }
2003         }
2004         // normalization: simple type
2005         else if (fNormalizeData) {
2006             // if !union type
2007             XSSimpleType dv = (XSSimpleType) fCurrentType;
2008             if (dv.getVariety() == XSSimpleType.VARIETY_UNION) {
2009                 fUnionType = true;
2010             } else {
2011                 try {
2012                     fWhiteSpace = dv.getWhitespace();
2013                 } catch (DatatypeException e) {
2014                     // do nothing
2015                 }
2016             }
2017         }
2018 
2019         // then try to get the content model
2020         fCurrentCM = null;
2021         if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
2022             fCurrentCM = ((XSComplexTypeDecl) fCurrentType).getContentModel(fCMBuilder);
2023         }
2024 
2025         // and get the initial content model state
2026         fCurrCMState = null;
2027         if (fCurrentCM != null)
2028             fCurrCMState = fCurrentCM.startContentModel();
2029 
2030         // get information about xsi:nil
2031         String xsiNil = attributes.getValue(SchemaSymbols.URI_XSI, SchemaSymbols.XSI_NIL);
2032         // only deal with xsi:nil when there is an element declaration
2033         if (xsiNil != null && fCurrentElemDecl != null)
2034             fNil = getXsiNil(element, xsiNil);
2035 
2036         // now validate everything related with the attributes
2037         // first, get the attribute group
2038         XSAttributeGroupDecl attrGrp = null;
2039         if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
2040             XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
2041             attrGrp = ctype.getAttrGrp();
2042         }
2043         // activate identity constraints
2044         fValueStoreCache.startElement();
2045         fMatcherStack.pushContext();
2046         if (fCurrentElemDecl != null && fCurrentElemDecl.fIDCPos > 0) {
2047             fIdConstraint = true;
2048             // initialize when identity constrains are defined for the elem
2049             fValueStoreCache.initValueStoresFor(fCurrentElemDecl, this);
2050         }
2051         processAttributes(element, attributes, attrGrp);
2052 
2053         // add default attributes
2054         if (attrGrp != null) {
2055             addDefaultAttributes(element, attributes, attrGrp);
2056         }
2057 
2058         // call all active identity constraints
2059         int count = fMatcherStack.getMatcherCount();
2060         for (int i = 0; i < count; i++) {
2061             XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
2062             matcher.startElement( element, attributes);
2063         }
2064 
2065         if (fAugPSVI) {
2066             augs = getEmptyAugs(augs);
2067 
2068             // PSVI: add validation context
2069             fCurrentPSVI.fValidationContext = fValidationRoot;
2070             // PSVI: add element declaration
2071             fCurrentPSVI.fDeclaration = fCurrentElemDecl;
2072             // PSVI: add element type
2073             fCurrentPSVI.fTypeDecl = fCurrentType;
2074             // PSVI: add notation attribute
2075             fCurrentPSVI.fNotation = fNotation;
2076         }
2077 
2078         return augs;
2079 
2080     } // handleStartElement(QName,XMLAttributes,boolean)
2081 
2082     /**
2083      *  Handle end element. If there is not text content, and there is a
2084      *  {value constraint} on the corresponding element decl, then
2085      * set the fDefaultValue XMLString representing the default value.
2086      */
2087     Augmentations handleEndElement(QName element, Augmentations augs) {
2088 
2089         if (DEBUG) {
2090             System.out.println("==>handleEndElement:" + element);
2091         }
2092         // if we are skipping, return
2093         if (fSkipValidationDepth >= 0) {
2094             // but if this is the top element that we are skipping,
2095             // restore the states.
2096             if (fSkipValidationDepth == fElementDepth && fSkipValidationDepth > 0) {
2097                 // set the partial validation depth to the depth of parent
2098                 fNFullValidationDepth = fSkipValidationDepth - 1;
2099                 fSkipValidationDepth = -1;
2100                 fElementDepth--;
2101                 fSubElement = fSubElementStack[fElementDepth];
2102                 fCurrentElemDecl = fElemDeclStack[fElementDepth];
2103                 fNil = fNilStack[fElementDepth];
2104                 fNotation = fNotationStack[fElementDepth];
2105                 fCurrentType = fTypeStack[fElementDepth];
2106                 fCurrentCM = fCMStack[fElementDepth];
2107                 fStrictAssess = fStrictAssessStack[fElementDepth];
2108                 fCurrCMState = fCMStateStack[fElementDepth];
2109                 fSawText = fSawTextStack[fElementDepth];
2110                 fSawCharacters = fStringContent[fElementDepth];
2111             }
2112             else {
2113                 fElementDepth--;
2114             }
2115 
2116             // PSVI: validation attempted:
2117             // use default values in psvi item for
2118             // validation attempted, validity, and error codes
2119 
2120             // check extra schema constraints on root element
2121             if (fElementDepth == -1 && fFullChecking) {
2122                 XSConstraints.fullSchemaChecking(
2123                     fGrammarBucket,
2124                     fSubGroupHandler,
2125                     fCMBuilder,
2126                     fXSIErrorReporter.fErrorReporter);
2127             }
2128 
2129             if (fAugPSVI)
2130                 augs = getEmptyAugs(augs);
2131             return augs;
2132         }
2133 
2134         // now validate the content of the element
2135         processElementContent(element);
2136 
2137         // Element Locally Valid (Element)
2138         // 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).
2139 
2140         // call matchers and de-activate context
2141         int oldCount = fMatcherStack.getMatcherCount();
2142         for (int i = oldCount - 1; i >= 0; i--) {
2143             XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
2144             if (fCurrentElemDecl == null)
2145                 matcher.endElement(element, null, false, fValidatedInfo.actualValue, fValidatedInfo.actualValueType, fValidatedInfo.itemValueTypes);
2146 
2147             else
2148                 matcher.endElement(
2149                     element,
2150                     fCurrentType,
2151                     fCurrentElemDecl.getNillable(),
2152                     fDefaultValue == null
2153                         ? fValidatedInfo.actualValue
2154                         : fCurrentElemDecl.fDefault.actualValue,
2155                     fDefaultValue == null
2156                         ? fValidatedInfo.actualValueType
2157                         : fCurrentElemDecl.fDefault.actualValueType,
2158                     fDefaultValue == null
2159                         ? fValidatedInfo.itemValueTypes
2160                         : fCurrentElemDecl.fDefault.itemValueTypes);
2161         }
2162 
2163         if (fMatcherStack.size() > 0) {
2164             fMatcherStack.popContext();
2165         }
2166 
2167         int newCount = fMatcherStack.getMatcherCount();
2168         // handle everything *but* keyref's.
2169         for (int i = oldCount - 1; i >= newCount; i--) {
2170             XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
2171             if (matcher instanceof Selector.Matcher) {
2172                 Selector.Matcher selMatcher = (Selector.Matcher) matcher;
2173                 IdentityConstraint id;
2174                 if ((id = selMatcher.getIdentityConstraint()) != null
2175                     && id.getCategory() != IdentityConstraint.IC_KEYREF) {
2176                     fValueStoreCache.transplant(id, selMatcher.getInitialDepth());
2177                 }
2178             }
2179         }
2180 
2181         // now handle keyref's/...
2182         for (int i = oldCount - 1; i >= newCount; i--) {
2183             XPathMatcher matcher = fMatcherStack.getMatcherAt(i);
2184             if (matcher instanceof Selector.Matcher) {
2185                 Selector.Matcher selMatcher = (Selector.Matcher) matcher;
2186                 IdentityConstraint id;
2187                 if ((id = selMatcher.getIdentityConstraint()) != null
2188                     && id.getCategory() == IdentityConstraint.IC_KEYREF) {
2189                     ValueStoreBase values =
2190                         fValueStoreCache.getValueStoreFor(id, selMatcher.getInitialDepth());
2191                     if (values != null) // nothing to do if nothing matched!
2192                         values.endDocumentFragment();
2193                 }
2194             }
2195         }
2196         fValueStoreCache.endElement();
2197 
2198         SchemaGrammar[] grammars = null;
2199         // have we reached the end tag of the validation root?
2200         if (fElementDepth == 0) {
2201             // 7 If the element information item is the validation root, it must be valid per Validation Root Valid (ID/IDREF) (3.3.4).
2202             String invIdRef = fValidationState.checkIDRefID();
2203             fValidationState.resetIDTables();
2204             if (invIdRef != null) {
2205                 reportSchemaError("cvc-id.1", new Object[] { invIdRef });
2206             }
2207             // check extra schema constraints
2208             if (fFullChecking) {
2209                 XSConstraints.fullSchemaChecking(
2210                     fGrammarBucket,
2211                     fSubGroupHandler,
2212                     fCMBuilder,
2213                     fXSIErrorReporter.fErrorReporter);
2214             }
2215 
2216             grammars = fGrammarBucket.getGrammars();
2217             // return the final set of grammars validator ended up with
2218             if (fGrammarPool != null) {
2219                 // Set grammars as immutable
2220                 for (int k=0; k < grammars.length; k++) {
2221                     grammars[k].setImmutable(true);
2222                 }
2223                 fGrammarPool.cacheGrammars(XMLGrammarDescription.XML_SCHEMA, grammars);
2224             }
2225             augs = endElementPSVI(true, grammars, augs);
2226         } else {
2227             augs = endElementPSVI(false, grammars, augs);
2228 
2229             // decrease element depth and restore states
2230             fElementDepth--;
2231 
2232             // get the states for the parent element.
2233             fSubElement = fSubElementStack[fElementDepth];
2234             fCurrentElemDecl = fElemDeclStack[fElementDepth];
2235             fNil = fNilStack[fElementDepth];
2236             fNotation = fNotationStack[fElementDepth];
2237             fCurrentType = fTypeStack[fElementDepth];
2238             fCurrentCM = fCMStack[fElementDepth];
2239             fStrictAssess = fStrictAssessStack[fElementDepth];
2240             fCurrCMState = fCMStateStack[fElementDepth];
2241             fSawText = fSawTextStack[fElementDepth];
2242             fSawCharacters = fStringContent[fElementDepth];
2243 
2244             // We should have a stack for whitespace value, and pop it up here.
2245             // But when fWhiteSpace != -1, and we see a sub-element, it must be
2246             // an error (at least for Schema 1.0). So for valid documents, the
2247             // only value we are going to push/pop in the stack is -1.
2248             // Here we just mimic the effect of popping -1. -SG
2249             fWhiteSpace = -1;
2250             // Same for append buffer. Simple types and elements with fixed
2251             // value constraint don't allow sub-elements. -SG
2252             fAppendBuffer = false;
2253             // same here.
2254             fUnionType = false;
2255         }
2256 
2257         return augs;
2258     } // handleEndElement(QName,boolean)*/
2259 
2260     final Augmentations endElementPSVI(
2261         boolean root,
2262         SchemaGrammar[] grammars,
2263         Augmentations augs) {
2264 
2265         if (fAugPSVI) {
2266             augs = getEmptyAugs(augs);
2267 
2268             // the 4 properties sent on startElement calls
2269             fCurrentPSVI.fDeclaration = this.fCurrentElemDecl;
2270             fCurrentPSVI.fTypeDecl = this.fCurrentType;
2271             fCurrentPSVI.fNotation = this.fNotation;
2272             fCurrentPSVI.fValidationContext = this.fValidationRoot;
2273             // PSVI: validation attempted
2274             // nothing below or at the same level has none or partial
2275             // (which means this level is strictly assessed, and all chidren
2276             // are full), so this one has full
2277             if (fElementDepth > fNFullValidationDepth) {
2278                 fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_FULL;
2279             }
2280             // nothing below or at the same level has full or partial
2281             // (which means this level is not strictly assessed, and all chidren
2282             // are none), so this one has none
2283             else if (fElementDepth > fNNoneValidationDepth) {
2284                 fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_NONE;
2285             }
2286             // otherwise partial, and anything above this level will be partial
2287             else {
2288                 fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_PARTIAL;
2289                 fNFullValidationDepth = fNNoneValidationDepth = fElementDepth - 1;
2290             }
2291 
2292             if (fDefaultValue != null)
2293                 fCurrentPSVI.fSpecified = true;
2294             fCurrentPSVI.fNil = fNil;
2295             fCurrentPSVI.fMemberType = fValidatedInfo.memberType;
2296             fCurrentPSVI.fNormalizedValue = fValidatedInfo.normalizedValue;
2297             fCurrentPSVI.fActualValue = fValidatedInfo.actualValue;
2298             fCurrentPSVI.fActualValueType = fValidatedInfo.actualValueType;
2299             fCurrentPSVI.fItemValueTypes = fValidatedInfo.itemValueTypes;
2300 
2301             if (fStrictAssess) {
2302                 // get all errors for the current element, its attribute,
2303                 // and subelements (if they were strictly assessed).
2304                 // any error would make this element invalid.
2305                 // and we merge these errors to the parent element.
2306                 String[] errors = fXSIErrorReporter.mergeContext();
2307 
2308                 // PSVI: error codes
2309                 fCurrentPSVI.fErrorCodes = errors;
2310                 // PSVI: validity
2311                 fCurrentPSVI.fValidity =
2312                     (errors == null) ? ElementPSVI.VALIDITY_VALID : ElementPSVI.VALIDITY_INVALID;
2313             } else {
2314                 // PSVI: validity
2315                 fCurrentPSVI.fValidity = ElementPSVI.VALIDITY_NOTKNOWN;
2316                 // Discard the current context: ignore any error happened within
2317                 // the sub-elements/attributes of this element, because those
2318                 // errors won't affect the validity of the parent elements.
2319                 fXSIErrorReporter.popContext();
2320             }
2321 
2322             if (root) {
2323                 // store [schema information] in the PSVI
2324                 fCurrentPSVI.fGrammars = grammars;
2325                 fCurrentPSVI.fSchemaInformation = null;
2326             }
2327         }
2328 
2329         return augs;
2330 
2331     }
2332 
2333     Augmentations getEmptyAugs(Augmentations augs) {
2334         if (augs == null) {
2335             augs = fAugmentations;
2336             augs.removeAllItems();
2337         }
2338         augs.putItem(Constants.ELEMENT_PSVI, fCurrentPSVI);
2339         fCurrentPSVI.reset();
2340 
2341         return augs;
2342     }
2343 
2344     void storeLocations(String sLocation, String nsLocation) {
2345         if (sLocation != null) {
2346             if (!XMLSchemaLoader.tokenizeSchemaLocationStr(sLocation, fLocationPairs)) {
2347                 // error!
2348                 fXSIErrorReporter.reportError(
2349                     XSMessageFormatter.SCHEMA_DOMAIN,
2350                     "SchemaLocation",
2351                     new Object[] { sLocation },
2352                     XMLErrorReporter.SEVERITY_WARNING);
2353             }
2354         }
2355         if (nsLocation != null) {
2356             XMLSchemaLoader.LocationArray la =
2357                 ((XMLSchemaLoader.LocationArray) fLocationPairs.get(XMLSymbols.EMPTY_STRING));
2358             if (la == null) {
2359                 la = new XMLSchemaLoader.LocationArray();
2360                 fLocationPairs.put(XMLSymbols.EMPTY_STRING, la);
2361             }
2362             la.addLocation(nsLocation);
2363         }
2364 
2365     } //storeLocations
2366 
2367     //this is the function where logic of retrieving grammar is written , parser first tries to get the grammar from
2368     //the local pool, if not in local pool, it gives chance to application to be able to retrieve the grammar, then it
2369     //tries to parse the grammar using location hints from the give namespace.
2370     SchemaGrammar findSchemaGrammar(
2371         short contextType,
2372         String namespace,
2373         QName enclosingElement,
2374         QName triggeringComponet,
2375         XMLAttributes attributes) {
2376         SchemaGrammar grammar = null;
2377         //get the grammar from local pool...
2378         grammar = fGrammarBucket.getGrammar(namespace);
2379 
2380         if (grammar == null) {
2381             fXSDDescription.setNamespace(namespace);
2382             // give a chance to application to be able to retreive the grammar.
2383             if (fGrammarPool != null) {
2384                 grammar = (SchemaGrammar) fGrammarPool.retrieveGrammar(fXSDDescription);
2385                 if (grammar != null) {
2386                     // put this grammar into the bucket, along with grammars
2387                     // imported by it (directly or indirectly)
2388                     if (!fGrammarBucket.putGrammar(grammar, true, fNamespaceGrowth)) {
2389                         // REVISIT: a conflict between new grammar(s) and grammars
2390                         // in the bucket. What to do? A warning? An exception?
2391                         fXSIErrorReporter.fErrorReporter.reportError(
2392                             XSMessageFormatter.SCHEMA_DOMAIN,
2393                             "GrammarConflict",
2394                             null,
2395                             XMLErrorReporter.SEVERITY_WARNING);
2396                         grammar = null;
2397                     }
2398                 }
2399             }
2400         }
2401         if ((grammar == null && !fUseGrammarPoolOnly) || fNamespaceGrowth) {
2402             fXSDDescription.reset();
2403             fXSDDescription.fContextType = contextType;
2404             fXSDDescription.setNamespace(namespace);
2405             fXSDDescription.fEnclosedElementName = enclosingElement;
2406             fXSDDescription.fTriggeringComponent = triggeringComponet;
2407             fXSDDescription.fAttributes = attributes;
2408             if (fLocator != null) {
2409                 fXSDDescription.setBaseSystemId(fLocator.getExpandedSystemId());
2410             }
2411 
2412             Hashtable locationPairs = fLocationPairs;
2413             Object locationArray =
2414                 locationPairs.get(namespace == null ? XMLSymbols.EMPTY_STRING : namespace);
2415             if (locationArray != null) {
2416                 String[] temp = ((XMLSchemaLoader.LocationArray) locationArray).getLocationArray();
2417                 if (temp.length != 0) {
2418                     setLocationHints(fXSDDescription, temp, grammar);
2419                 }
2420             }
2421 
2422             if (grammar == null || fXSDDescription.fLocationHints != null) {
2423                 boolean toParseSchema = true;
2424                 if (grammar != null) {
2425                      // use location hints instead
2426                     locationPairs = EMPTY_TABLE;
2427                 }
2428 
2429                 // try to parse the grammar using location hints from that namespace..
2430                 try {
2431                     XMLInputSource xis =
2432                         XMLSchemaLoader.resolveDocument(
2433                             fXSDDescription,
2434                             locationPairs,
2435                             fEntityResolver);
2436                     if (grammar != null && fNamespaceGrowth) {
2437                         try {
2438                             // if we are dealing with a different schema location, then include the new schema
2439                             // into the existing grammar
2440                             if (grammar.getDocumentLocations().contains(XMLEntityManager.expandSystemId(xis.getSystemId(), xis.getBaseSystemId(), false))) {
2441                                 toParseSchema = false;
2442                             }
2443                         }
2444                         catch (MalformedURIException e) {
2445                         }
2446                     }
2447                     if (toParseSchema) {
2448                         grammar = fSchemaLoader.loadSchema(fXSDDescription, xis, fLocationPairs);
2449                     }
2450                 } catch (IOException ex) {
2451                     final String [] locationHints = fXSDDescription.getLocationHints();
2452                     fXSIErrorReporter.fErrorReporter.reportError(
2453                         XSMessageFormatter.SCHEMA_DOMAIN,
2454                         "schema_reference.4",
2455                         new Object[] { locationHints != null ? locationHints[0] : XMLSymbols.EMPTY_STRING },
2456                         XMLErrorReporter.SEVERITY_WARNING);
2457                 }
2458             }
2459         }
2460 
2461         return grammar;
2462 
2463     } //findSchemaGrammar
2464     private void setLocationHints(XSDDescription desc, String[] locations, SchemaGrammar grammar) {
2465         int length = locations.length;
2466         if (grammar == null) {
2467             fXSDDescription.fLocationHints = new String[length];
2468             System.arraycopy(locations, 0, fXSDDescription.fLocationHints, 0, length);
2469         }
2470         else {
2471             setLocationHints(desc, locations, grammar.getDocumentLocations());
2472         }
2473     }
2474 
2475     private void setLocationHints(XSDDescription desc, String[] locations, StringList docLocations) {
2476         int length = locations.length;
2477         String[] hints = new String[length];
2478         int counter = 0;
2479 
2480         for (int i=0; i<length; i++) {
2481             try {
2482                 String id = XMLEntityManager.expandSystemId(locations[i], desc.getBaseSystemId(), false);
2483                 if (!docLocations.contains(id)) {
2484                     hints[counter++] = locations[i];
2485                 }
2486             }
2487             catch (MalformedURIException e) {
2488             }
2489         }
2490 
2491         if (counter > 0) {
2492             if (counter == length) {
2493                 fXSDDescription.fLocationHints = hints;
2494             }
2495             else {
2496                 fXSDDescription.fLocationHints = new String[counter];
2497                 System.arraycopy(hints, 0, fXSDDescription.fLocationHints, 0, counter);
2498             }
2499         }
2500     }
2501 
2502 
2503     XSTypeDefinition getAndCheckXsiType(QName element, String xsiType, XMLAttributes attributes) {
2504         // This method also deals with clause 1.2.1.2 of the constraint
2505         // Validation Rule: Schema-Validity Assessment (Element)
2506 
2507         // Element Locally Valid (Element)
2508         // 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:
2509         // 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);
2510         QName typeName = null;
2511         try {
2512             typeName = (QName) fQNameDV.validate(xsiType, fValidationState, null);
2513         } catch (InvalidDatatypeValueException e) {
2514             reportSchemaError(e.getKey(), e.getArgs());
2515             reportSchemaError(
2516                 "cvc-elt.4.1",
2517                 new Object[] {
2518                     element.rawname,
2519                     SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_TYPE,
2520                     xsiType });
2521             return null;
2522         }
2523 
2524         // 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)
2525         XSTypeDefinition type = null;
2526         // if the namespace is schema namespace, first try built-in types
2527         if (typeName.uri == SchemaSymbols.URI_SCHEMAFORSCHEMA) {
2528             type = SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(typeName.localpart);
2529         }
2530         // if it's not schema built-in types, then try to get a grammar
2531         if (type == null) {
2532             //try to find schema grammar by different means....
2533             SchemaGrammar grammar =
2534                 findSchemaGrammar(
2535                     XSDDescription.CONTEXT_XSITYPE,
2536                     typeName.uri,
2537                     element,
2538                     typeName,
2539                     attributes);
2540 
2541             if (grammar != null)
2542                 type = grammar.getGlobalTypeDecl(typeName.localpart);
2543         }
2544         // still couldn't find the type, report an error
2545         if (type == null) {
2546             reportSchemaError("cvc-elt.4.2", new Object[] { element.rawname, xsiType });
2547             return null;
2548         }
2549 
2550         // if there is no current type, set this one as current.
2551         // and we don't need to do extra checking
2552         if (fCurrentType != null) {
2553             // 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).
2554             short block = fCurrentElemDecl.fBlock;
2555             if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE)
2556                 block |= ((XSComplexTypeDecl) fCurrentType).fBlock;
2557             if (!XSConstraints.checkTypeDerivationOk(type, fCurrentType, block))
2558                 reportSchemaError(
2559                     "cvc-elt.4.3",
2560                     new Object[] { element.rawname, xsiType, fCurrentType.getName()});
2561         }
2562 
2563         return type;
2564     } //getAndCheckXsiType
2565 
2566     boolean getXsiNil(QName element, String xsiNil) {
2567         // Element Locally Valid (Element)
2568         // 3 The appropriate case among the following must be true:
2569         // 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.
2570         if (fCurrentElemDecl != null && !fCurrentElemDecl.getNillable()) {
2571             reportSchemaError(
2572                 "cvc-elt.3.1",
2573                 new Object[] {
2574                     element.rawname,
2575                     SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_NIL });
2576         }
2577         // 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:
2578         // 3.2.2 There must be no fixed {value constraint}.
2579         else {
2580             String value = XMLChar.trim(xsiNil);
2581             if (value.equals(SchemaSymbols.ATTVAL_TRUE)
2582                 || value.equals(SchemaSymbols.ATTVAL_TRUE_1)) {
2583                 if (fCurrentElemDecl != null
2584                     && fCurrentElemDecl.getConstraintType() == XSConstants.VC_FIXED) {
2585                     reportSchemaError(
2586                         "cvc-elt.3.2.2",
2587                         new Object[] {
2588                             element.rawname,
2589                             SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_NIL });
2590                 }
2591                 return true;
2592             }
2593         }
2594         return false;
2595     }
2596 
2597     void processAttributes(QName element, XMLAttributes attributes, XSAttributeGroupDecl attrGrp) {
2598 
2599         if (DEBUG) {
2600             System.out.println("==>processAttributes: " + attributes.getLength());
2601         }
2602 
2603         // whether we have seen a Wildcard ID.
2604         String wildcardIDName = null;
2605 
2606         // for each present attribute
2607         int attCount = attributes.getLength();
2608 
2609         Augmentations augs = null;
2610         AttributePSVImpl attrPSVI = null;
2611 
2612         boolean isSimple =
2613             fCurrentType == null || fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE;
2614 
2615         XSObjectList attrUses = null;
2616         int useCount = 0;
2617         XSWildcardDecl attrWildcard = null;
2618         if (!isSimple) {
2619             attrUses = attrGrp.getAttributeUses();
2620             useCount = attrUses.getLength();
2621             attrWildcard = attrGrp.fAttributeWC;
2622         }
2623 
2624         // Element Locally Valid (Complex Type)
2625         // 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:
2626         // get the corresponding attribute decl
2627         for (int index = 0; index < attCount; index++) {
2628 
2629             attributes.getName(index, fTempQName);
2630 
2631             if (DEBUG) {
2632                 System.out.println("==>process attribute: " + fTempQName);
2633             }
2634 
2635             if (fAugPSVI || fIdConstraint) {
2636                 augs = attributes.getAugmentations(index);
2637                 attrPSVI = (AttributePSVImpl) augs.getItem(Constants.ATTRIBUTE_PSVI);
2638                 if (attrPSVI != null) {
2639                     attrPSVI.reset();
2640                 } else {
2641                     attrPSVI = new AttributePSVImpl();
2642                     augs.putItem(Constants.ATTRIBUTE_PSVI, attrPSVI);
2643                 }
2644                 // PSVI attribute: validation context
2645                 attrPSVI.fValidationContext = fValidationRoot;
2646             }
2647 
2648             // Element Locally Valid (Type)
2649             // 3.1.1 The element information item's [attributes] must be empty, excepting those
2650             // whose [namespace name] is identical to http://www.w3.org/2001/XMLSchema-instance and
2651             // whose [local name] is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
2652 
2653             // for the 4 xsi attributes, get appropriate decl, and validate
2654             if (fTempQName.uri == SchemaSymbols.URI_XSI) {
2655                 XSAttributeDecl attrDecl = null;
2656                 if (fTempQName.localpart == SchemaSymbols.XSI_SCHEMALOCATION)
2657                     attrDecl =
2658                         SchemaGrammar.SG_XSI.getGlobalAttributeDecl(
2659                             SchemaSymbols.XSI_SCHEMALOCATION);
2660                 else if (fTempQName.localpart == SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION)
2661                     attrDecl =
2662                         SchemaGrammar.SG_XSI.getGlobalAttributeDecl(
2663                             SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION);
2664                 else if (fTempQName.localpart == SchemaSymbols.XSI_NIL)
2665                     attrDecl = SchemaGrammar.SG_XSI.getGlobalAttributeDecl(SchemaSymbols.XSI_NIL);
2666                 else if (fTempQName.localpart == SchemaSymbols.XSI_TYPE)
2667                     attrDecl = SchemaGrammar.SG_XSI.getGlobalAttributeDecl(SchemaSymbols.XSI_TYPE);
2668                 if (attrDecl != null) {
2669                     processOneAttribute(element, attributes, index, attrDecl, null, attrPSVI);
2670                     continue;
2671                 }
2672             }
2673 
2674             // for namespace attributes, no_validation/unknow_validity
2675             if (fTempQName.rawname == XMLSymbols.PREFIX_XMLNS
2676                 || fTempQName.rawname.startsWith("xmlns:")) {
2677                 continue;
2678             }
2679 
2680             // simple type doesn't allow any other attributes
2681             if (isSimple) {
2682                 reportSchemaError(
2683                     "cvc-type.3.1.1",
2684                     new Object[] { element.rawname, fTempQName.rawname });
2685                 continue;
2686             }
2687 
2688             // it's not xmlns, and not xsi, then we need to find a decl for it
2689             XSAttributeUseImpl currUse = null, oneUse;
2690             for (int i = 0; i < useCount; i++) {
2691                 oneUse = (XSAttributeUseImpl) attrUses.item(i);
2692                 if (oneUse.fAttrDecl.fName == fTempQName.localpart
2693                     && oneUse.fAttrDecl.fTargetNamespace == fTempQName.uri) {
2694                     currUse = oneUse;
2695                     break;
2696                 }
2697             }
2698 
2699             // 3.2 otherwise all of the following must be true:
2700             // 3.2.1 There must be an {attribute wildcard}.
2701             // 3.2.2 The attribute information item must be valid with respect to it as defined in Item Valid (Wildcard) (3.10.4).
2702 
2703             // if failed, get it from wildcard
2704             if (currUse == null) {
2705                 //if (attrWildcard == null)
2706                 //    reportSchemaError("cvc-complex-type.3.2.1", new Object[]{element.rawname, fTempQName.rawname});
2707                 if (attrWildcard == null || !attrWildcard.allowNamespace(fTempQName.uri)) {
2708                     // so this attribute is not allowed
2709                     reportSchemaError(
2710                         "cvc-complex-type.3.2.2",
2711                         new Object[] { element.rawname, fTempQName.rawname });
2712                     continue;
2713                 }
2714             }
2715 
2716             XSAttributeDecl currDecl = null;
2717             if (currUse != null) {
2718                 currDecl = currUse.fAttrDecl;
2719             } else {
2720                 // which means it matches a wildcard
2721                 // skip it if processContents is skip
2722                 if (attrWildcard.fProcessContents == XSWildcardDecl.PC_SKIP)
2723                     continue;
2724 
2725                 //try to find grammar by different means...
2726                 SchemaGrammar grammar =
2727                     findSchemaGrammar(
2728                         XSDDescription.CONTEXT_ATTRIBUTE,
2729                         fTempQName.uri,
2730                         element,
2731                         fTempQName,
2732                         attributes);
2733 
2734                 if (grammar != null) {
2735                     currDecl = grammar.getGlobalAttributeDecl(fTempQName.localpart);
2736                 }
2737 
2738                 // if can't find
2739                 if (currDecl == null) {
2740                     // if strict, report error
2741                     if (attrWildcard.fProcessContents == XSWildcardDecl.PC_STRICT) {
2742                         reportSchemaError(
2743                             "cvc-complex-type.3.2.2",
2744                             new Object[] { element.rawname, fTempQName.rawname });
2745                     }
2746 
2747                     // then continue to the next attribute
2748                     continue;
2749                 } else {
2750                     // 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:
2751                     // 5.1 There must be no more than one item in wild IDs.
2752                     if (currDecl.fType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE
2753                         && ((XSSimpleType) currDecl.fType).isIDType()) {
2754                         if (wildcardIDName != null) {
2755                             reportSchemaError(
2756                                 "cvc-complex-type.5.1",
2757                                 new Object[] { element.rawname, currDecl.fName, wildcardIDName });
2758                         } else
2759                             wildcardIDName = currDecl.fName;
2760                     }
2761                 }
2762             }
2763 
2764             processOneAttribute(element, attributes, index, currDecl, currUse, attrPSVI);
2765         } // end of for (all attributes)
2766 
2767         // 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.
2768         if (!isSimple && attrGrp.fIDAttrName != null && wildcardIDName != null) {
2769             reportSchemaError(
2770                 "cvc-complex-type.5.2",
2771                 new Object[] { element.rawname, wildcardIDName, attrGrp.fIDAttrName });
2772         }
2773 
2774     } //processAttributes
2775 
2776     void processOneAttribute(
2777         QName element,
2778         XMLAttributes attributes,
2779         int index,
2780         XSAttributeDecl currDecl,
2781         XSAttributeUseImpl currUse,
2782         AttributePSVImpl attrPSVI) {
2783 
2784         String attrValue = attributes.getValue(index);
2785         fXSIErrorReporter.pushContext();
2786 
2787         // Attribute Locally Valid
2788         // For an attribute information item to be locally valid with respect to an attribute declaration all of the following must be true:
2789         // 1 The declaration must not be absent (see Missing Sub-components (5.3) for how this can fail to be the case).
2790         // 2 Its {type definition} must not be absent.
2791         // 3 The item's normalized value must be locally valid with respect to that {type definition} as per String Valid (3.14.4).
2792         // get simple type
2793         XSSimpleType attDV = currDecl.fType;
2794 
2795         Object actualValue = null;
2796         try {
2797             actualValue = attDV.validate(attrValue, fValidationState, fValidatedInfo);
2798             // store the normalized value
2799             if (fNormalizeData)
2800                 attributes.setValue(index, fValidatedInfo.normalizedValue);
2801             if (attributes instanceof XMLAttributesImpl) {
2802                 XMLAttributesImpl attrs = (XMLAttributesImpl) attributes;
2803                 boolean schemaId =
2804                     fValidatedInfo.memberType != null
2805                         ? fValidatedInfo.memberType.isIDType()
2806                         : attDV.isIDType();
2807                 attrs.setSchemaId(index, schemaId);
2808             }
2809 
2810             // PSVI: element notation
2811             if (attDV.getVariety() == XSSimpleType.VARIETY_ATOMIC
2812                 && attDV.getPrimitiveKind() == XSSimpleType.PRIMITIVE_NOTATION) {
2813                 QName qName = (QName) actualValue;
2814                 SchemaGrammar grammar = fGrammarBucket.getGrammar(qName.uri);
2815 
2816                 //REVISIT: is it possible for the notation to be in different namespace than the attribute
2817                 //with which it is associated, CHECK !!  <fof n1:att1 = "n2:notation1" ..>
2818                 // should we give chance to the application to be able to  retrieve a grammar - nb
2819                 //REVISIT: what would be the triggering component here.. if it is attribute value that
2820                 // triggered the loading of grammar ?? -nb
2821 
2822                 if (grammar != null) {
2823                     fNotation = grammar.getGlobalNotationDecl(qName.localpart);
2824                 }
2825             }
2826         } catch (InvalidDatatypeValueException idve) {
2827             reportSchemaError(idve.getKey(), idve.getArgs());
2828             reportSchemaError(
2829                 "cvc-attribute.3",
2830                 new Object[] { element.rawname, fTempQName.rawname, attrValue, attDV.getName()});
2831         }
2832 
2833         // get the value constraint from use or decl
2834         // 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
2835         if (actualValue != null && currDecl.getConstraintType() == XSConstants.VC_FIXED) {
2836             if (!isComparable(fValidatedInfo, currDecl.fDefault) || !actualValue.equals(currDecl.fDefault.actualValue)) {
2837                 reportSchemaError(
2838                     "cvc-attribute.4",
2839                     new Object[] {
2840                         element.rawname,
2841                         fTempQName.rawname,
2842                         attrValue,
2843                         currDecl.fDefault.stringValue()});
2844             }
2845         }
2846 
2847         // 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).
2848         if (actualValue != null
2849             && currUse != null
2850             && currUse.fConstraintType == XSConstants.VC_FIXED) {
2851             if (!isComparable(fValidatedInfo, currUse.fDefault) || !actualValue.equals(currUse.fDefault.actualValue)) {
2852                 reportSchemaError(
2853                     "cvc-complex-type.3.1",
2854                     new Object[] {
2855                         element.rawname,
2856                         fTempQName.rawname,
2857                         attrValue,
2858                         currUse.fDefault.stringValue()});
2859             }
2860         }
2861         if (fIdConstraint) {
2862             attrPSVI.fActualValue = actualValue;
2863         }
2864 
2865         if (fAugPSVI) {
2866             // PSVI: attribute declaration
2867             attrPSVI.fDeclaration = currDecl;
2868             // PSVI: attribute type
2869             attrPSVI.fTypeDecl = attDV;
2870 
2871             // PSVI: attribute memberType
2872             attrPSVI.fMemberType = fValidatedInfo.memberType;
2873             // PSVI: attribute normalized value
2874             // NOTE: we always store the normalized value, even if it's invlid,
2875             // because it might still be useful to the user. But when the it's
2876             // not valid, the normalized value is not trustable.
2877             attrPSVI.fNormalizedValue = fValidatedInfo.normalizedValue;
2878             attrPSVI.fActualValue = fValidatedInfo.actualValue;
2879             attrPSVI.fActualValueType = fValidatedInfo.actualValueType;
2880             attrPSVI.fItemValueTypes = fValidatedInfo.itemValueTypes;
2881 
2882 
2883 
2884             // PSVI: validation attempted:
2885             attrPSVI.fValidationAttempted = AttributePSVI.VALIDATION_FULL;
2886 
2887             String[] errors = fXSIErrorReporter.mergeContext();
2888             // PSVI: error codes
2889             attrPSVI.fErrorCodes = errors;
2890             // PSVI: validity
2891             attrPSVI.fValidity =
2892                 (errors == null) ? AttributePSVI.VALIDITY_VALID : AttributePSVI.VALIDITY_INVALID;
2893         }
2894     }
2895 
2896     void addDefaultAttributes(
2897         QName element,
2898         XMLAttributes attributes,
2899         XSAttributeGroupDecl attrGrp) {
2900         // Check after all specified attrs are scanned
2901         // (1) report error for REQUIRED attrs that are missing (V_TAGc)
2902         // REVISIT: should we check prohibited attributes?
2903         // (2) report error for PROHIBITED attrs that are present (V_TAGc)
2904         // (3) add default attrs (FIXED and NOT_FIXED)
2905         //
2906         if (DEBUG) {
2907             System.out.println("==>addDefaultAttributes: " + element);
2908         }
2909         XSObjectList attrUses = attrGrp.getAttributeUses();
2910         int useCount = attrUses.getLength();
2911         XSAttributeUseImpl currUse;
2912         XSAttributeDecl currDecl;
2913         short constType;
2914         ValidatedInfo defaultValue;
2915         boolean isSpecified;
2916         QName attName;
2917         // for each attribute use
2918         for (int i = 0; i < useCount; i++) {
2919 
2920             currUse = (XSAttributeUseImpl) attrUses.item(i);
2921             currDecl = currUse.fAttrDecl;
2922             // get value constraint
2923             constType = currUse.fConstraintType;
2924             defaultValue = currUse.fDefault;
2925             if (constType == XSConstants.VC_NONE) {
2926                 constType = currDecl.getConstraintType();
2927                 defaultValue = currDecl.fDefault;
2928             }
2929             // whether this attribute is specified
2930             isSpecified = attributes.getValue(currDecl.fTargetNamespace, currDecl.fName) != null;
2931 
2932             // Element Locally Valid (Complex Type)
2933             // 4 The {attribute declaration} of each attribute use in the {attribute uses} whose
2934             // {required} is true matches one of the attribute information items in the element
2935             // information item's [attributes] as per clause 3.1 above.
2936             if (currUse.fUse == SchemaSymbols.USE_REQUIRED) {
2937                 if (!isSpecified)
2938                     reportSchemaError(
2939                         "cvc-complex-type.4",
2940                         new Object[] { element.rawname, currDecl.fName });
2941             }
2942             // if the attribute is not specified, then apply the value constraint
2943             if (!isSpecified && constType != XSConstants.VC_NONE) {
2944                 attName =
2945                     new QName(null, currDecl.fName, currDecl.fName, currDecl.fTargetNamespace);
2946                 String normalized = (defaultValue != null) ? defaultValue.stringValue() : "";
2947                 int attrIndex = attributes.addAttribute(attName, "CDATA", normalized);
2948                 if (attributes instanceof XMLAttributesImpl) {
2949                     XMLAttributesImpl attrs = (XMLAttributesImpl) attributes;
2950                     boolean schemaId =
2951                         defaultValue != null
2952                             && defaultValue.memberType != null
2953                                 ? defaultValue.memberType.isIDType()
2954                                 : currDecl.fType.isIDType();
2955                     attrs.setSchemaId(attrIndex, schemaId);
2956                 }
2957 
2958                 if (fAugPSVI) {
2959 
2960                     // PSVI: attribute is "schema" specified
2961                     Augmentations augs = attributes.getAugmentations(attrIndex);
2962                     AttributePSVImpl attrPSVI = new AttributePSVImpl();
2963                     augs.putItem(Constants.ATTRIBUTE_PSVI, attrPSVI);
2964 
2965                     attrPSVI.fDeclaration = currDecl;
2966                     attrPSVI.fTypeDecl = currDecl.fType;
2967                     attrPSVI.fMemberType = defaultValue.memberType;
2968                     attrPSVI.fNormalizedValue = normalized;
2969                     attrPSVI.fActualValue = defaultValue.actualValue;
2970                     attrPSVI.fActualValueType = defaultValue.actualValueType;
2971                     attrPSVI.fItemValueTypes = defaultValue.itemValueTypes;
2972                     attrPSVI.fValidationContext = fValidationRoot;
2973                     attrPSVI.fValidity = AttributePSVI.VALIDITY_VALID;
2974                     attrPSVI.fValidationAttempted = AttributePSVI.VALIDATION_FULL;
2975                     attrPSVI.fSpecified = true;
2976                 }
2977             }
2978 
2979         } // for
2980     } // addDefaultAttributes
2981 
2982     /**
2983      *  If there is not text content, and there is a
2984      *  {value constraint} on the corresponding element decl, then return
2985      *  an XMLString representing the default value.
2986      */
2987     void processElementContent(QName element) {
2988         // 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.
2989         if (fCurrentElemDecl != null
2990             && fCurrentElemDecl.fDefault != null
2991             && !fSawText
2992             && !fSubElement
2993             && !fNil) {
2994 
2995             String strv = fCurrentElemDecl.fDefault.stringValue();
2996             int bufLen = strv.length();
2997             if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < bufLen) {
2998                 fNormalizedStr.ch = new char[bufLen];
2999             }
3000             strv.getChars(0, bufLen, fNormalizedStr.ch, 0);
3001             fNormalizedStr.offset = 0;
3002             fNormalizedStr.length = bufLen;
3003             fDefaultValue = fNormalizedStr;
3004         }
3005         // fixed values are handled later, after xsi:type determined.
3006 
3007         fValidatedInfo.normalizedValue = null;
3008 
3009         // Element Locally Valid (Element)
3010         // 3.2.1 The element information item must have no character or element information item [children].
3011         if (fNil) {
3012             if (fSubElement || fSawText) {
3013                 reportSchemaError(
3014                     "cvc-elt.3.2.1",
3015                     new Object[] {
3016                         element.rawname,
3017                         SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_NIL });
3018             }
3019         }
3020 
3021         this.fValidatedInfo.reset();
3022 
3023         // 5 The appropriate case among the following must be true:
3024         // 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:
3025         if (fCurrentElemDecl != null
3026             && fCurrentElemDecl.getConstraintType() != XSConstants.VC_NONE
3027             && !fSubElement
3028             && !fSawText
3029             && !fNil) {
3030             // 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).
3031             if (fCurrentType != fCurrentElemDecl.fType) {
3032                 //REVISIT:we should pass ValidatedInfo here.
3033                 if (XSConstraints
3034                     .ElementDefaultValidImmediate(
3035                         fCurrentType,
3036                         fCurrentElemDecl.fDefault.stringValue(),
3037                         fState4XsiType,
3038                         null)
3039                     == null)
3040                     reportSchemaError(
3041                         "cvc-elt.5.1.1",
3042                         new Object[] {
3043                             element.rawname,
3044                             fCurrentType.getName(),
3045                             fCurrentElemDecl.fDefault.stringValue()});
3046             }
3047             // 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).
3048             // REVISIT: don't use toString, but validateActualValue instead
3049             //          use the fState4ApplyDefault
3050             elementLocallyValidType(element, fCurrentElemDecl.fDefault.stringValue());
3051         } else {
3052             // The following method call also deal with clause 1.2.2 of the constraint
3053             // Validation Rule: Schema-Validity Assessment (Element)
3054 
3055             // 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:
3056             // 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).
3057             Object actualValue = elementLocallyValidType(element, fBuffer);
3058             // 5.2.2 If there is a fixed {value constraint} and clause 3.2 has not applied, all of the following must be true:
3059             if (fCurrentElemDecl != null
3060                 && fCurrentElemDecl.getConstraintType() == XSConstants.VC_FIXED
3061                 && !fNil) {
3062                 String content = fBuffer.toString();
3063                 // 5.2.2.1 The element information item must have no element information item [children].
3064                 if (fSubElement)
3065                     reportSchemaError("cvc-elt.5.2.2.1", new Object[] { element.rawname });
3066                 // 5.2.2.2 The appropriate case among the following must be true:
3067                 if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
3068                     XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
3069                     // 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.
3070                     if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
3071                         // REVISIT: how to get the initial value, does whiteSpace count?
3072                         if (!fCurrentElemDecl.fDefault.normalizedValue.equals(content))
3073                             reportSchemaError(
3074                                 "cvc-elt.5.2.2.2.1",
3075                                 new Object[] {
3076                                     element.rawname,
3077                                     content,
3078                                     fCurrentElemDecl.fDefault.normalizedValue });
3079                     }
3080                     // 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.
3081                     else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
3082                         if (actualValue != null && (!isComparable(fValidatedInfo, fCurrentElemDecl.fDefault)
3083                                 || !actualValue.equals(fCurrentElemDecl.fDefault.actualValue))) {
3084                             reportSchemaError(
3085                                 "cvc-elt.5.2.2.2.2",
3086                                 new Object[] {
3087                                     element.rawname,
3088                                     content,
3089                                     fCurrentElemDecl.fDefault.stringValue()});
3090                         }
3091                     }
3092                 } else if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
3093                     if (actualValue != null && (!isComparable(fValidatedInfo, fCurrentElemDecl.fDefault)
3094                             || !actualValue.equals(fCurrentElemDecl.fDefault.actualValue))) {
3095                         // REVISIT: the spec didn't mention this case: fixed
3096                         //          value with simple type
3097                         reportSchemaError(
3098                             "cvc-elt.5.2.2.2.2",
3099                             new Object[] {
3100                                 element.rawname,
3101                                 content,
3102                                 fCurrentElemDecl.fDefault.stringValue()});
3103                     }
3104                 }
3105             }
3106         }
3107 
3108         if (fDefaultValue == null && fNormalizeData && fDocumentHandler != null && fUnionType) {
3109             // for union types we need to send data because we delayed sending
3110             // this data when we received it in the characters() call.
3111             String content = fValidatedInfo.normalizedValue;
3112             if (content == null)
3113                 content = fBuffer.toString();
3114 
3115             int bufLen = content.length();
3116             if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < bufLen) {
3117                 fNormalizedStr.ch = new char[bufLen];
3118             }
3119             content.getChars(0, bufLen, fNormalizedStr.ch, 0);
3120             fNormalizedStr.offset = 0;
3121             fNormalizedStr.length = bufLen;
3122             fDocumentHandler.characters(fNormalizedStr, null);
3123         }
3124     } // processElementContent
3125 
3126     Object elementLocallyValidType(QName element, Object textContent) {
3127         if (fCurrentType == null)
3128             return null;
3129 
3130         Object retValue = null;
3131         // Element Locally Valid (Type)
3132         // 3 The appropriate case among the following must be true:
3133         // 3.1 If the type definition is a simple type definition, then all of the following must be true:
3134         if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
3135             // 3.1.2 The element information item must have no element information item [children].
3136             if (fSubElement)
3137                 reportSchemaError("cvc-type.3.1.2", new Object[] { element.rawname });
3138             // 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).
3139             if (!fNil) {
3140                 XSSimpleType dv = (XSSimpleType) fCurrentType;
3141                 try {
3142                     if (!fNormalizeData || fUnionType) {
3143                         fValidationState.setNormalizationRequired(true);
3144                     }
3145                     retValue = dv.validate(textContent, fValidationState, fValidatedInfo);
3146                 } catch (InvalidDatatypeValueException e) {
3147                     reportSchemaError(e.getKey(), e.getArgs());
3148                     reportSchemaError(
3149                         "cvc-type.3.1.3",
3150                         new Object[] { element.rawname, textContent });
3151                 }
3152             }
3153         } else {
3154             // 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);
3155             retValue = elementLocallyValidComplexType(element, textContent);
3156         }
3157 
3158         return retValue;
3159     } // elementLocallyValidType
3160 
3161     Object elementLocallyValidComplexType(QName element, Object textContent) {
3162         Object actualValue = null;
3163         XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
3164 
3165         // Element Locally Valid (Complex Type)
3166         // For an element information item to be locally valid with respect to a complex type definition all of the following must be true:
3167         // 1 {abstract} is false.
3168         // 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:
3169         if (!fNil) {
3170             // 2.1 If the {content type} is empty, then the element information item has no character or element information item [children].
3171             if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_EMPTY
3172                 && (fSubElement || fSawText)) {
3173                 reportSchemaError("cvc-complex-type.2.1", new Object[] { element.rawname });
3174             }
3175             // 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).
3176             else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
3177                 if (fSubElement)
3178                     reportSchemaError("cvc-complex-type.2.2", new Object[] { element.rawname });
3179                 XSSimpleType dv = ctype.fXSSimpleType;
3180                 try {
3181                     if (!fNormalizeData || fUnionType) {
3182                         fValidationState.setNormalizationRequired(true);
3183                     }
3184                     actualValue = dv.validate(textContent, fValidationState, fValidatedInfo);
3185                 } catch (InvalidDatatypeValueException e) {
3186                     reportSchemaError(e.getKey(), e.getArgs());
3187                     reportSchemaError("cvc-complex-type.2.2", new Object[] { element.rawname });
3188                 }
3189                 // REVISIT: eventually, this method should return the same actualValue as elementLocallyValidType...
3190                 // obviously it'll return null when the content is complex.
3191             }
3192             // 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)].
3193             else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
3194                 if (fSawCharacters) {
3195                     reportSchemaError("cvc-complex-type.2.3", new Object[] { element.rawname });
3196                 }
3197             }
3198             // 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).
3199             if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT
3200                 || ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
3201                 // if the current state is a valid state, check whether
3202                 // it's one of the final states.
3203                 if (DEBUG) {
3204                     System.out.println(fCurrCMState);
3205                 }
3206                 if (fCurrCMState[0] >= 0 && !fCurrentCM.endContentModel(fCurrCMState)) {
3207                     String expected = expectedStr(fCurrentCM.whatCanGoHere(fCurrCMState));
3208                     reportSchemaError(
3209                         "cvc-complex-type.2.4.b",
3210                         new Object[] { element.rawname, expected });
3211                 } else {
3212                     // Constant space algorithm for a{n,m} for n > 1 and m <= unbounded
3213                     // After the DFA has completed, check minOccurs and maxOccurs
3214                     // for all elements and wildcards in this content model where
3215                     // a{n,m} is subsumed to a* or a+
3216                     ArrayList errors = fCurrentCM.checkMinMaxBounds();
3217                     if (errors != null) {
3218                         for (int i = 0; i < errors.size(); i += 2) {
3219                             reportSchemaError(
3220                                 (String) errors.get(i),
3221                                 new Object[] { element.rawname, errors.get(i + 1) });
3222                         }
3223                     }
3224                 }
3225              }
3226         }
3227         return actualValue;
3228     } // elementLocallyValidComplexType
3229 
3230     void reportSchemaError(String key, Object[] arguments) {
3231         if (fDoValidation)
3232             fXSIErrorReporter.reportError(
3233                 XSMessageFormatter.SCHEMA_DOMAIN,
3234                 key,
3235                 arguments,
3236                 XMLErrorReporter.SEVERITY_ERROR);
3237     }
3238 
3239     /** Returns true if the two ValidatedInfo objects can be compared in the same value space. **/
3240     private boolean isComparable(ValidatedInfo info1, ValidatedInfo info2) {
3241         final short primitiveType1 = convertToPrimitiveKind(info1.actualValueType);
3242         final short primitiveType2 = convertToPrimitiveKind(info2.actualValueType);
3243         if (primitiveType1 != primitiveType2) {
3244             return (primitiveType1 == XSConstants.ANYSIMPLETYPE_DT && primitiveType2 == XSConstants.STRING_DT ||
3245                     primitiveType1 == XSConstants.STRING_DT && primitiveType2 == XSConstants.ANYSIMPLETYPE_DT);
3246         }
3247         else if (primitiveType1 == XSConstants.LIST_DT || primitiveType1 == XSConstants.LISTOFUNION_DT) {
3248             final ShortList typeList1 = info1.itemValueTypes;
3249             final ShortList typeList2 = info2.itemValueTypes;
3250             final int typeList1Length = typeList1 != null ? typeList1.getLength() : 0;
3251             final int typeList2Length = typeList2 != null ? typeList2.getLength() : 0;
3252             if (typeList1Length != typeList2Length) {
3253                 return false;
3254             }
3255             for (int i = 0; i < typeList1Length; ++i) {
3256                 final short primitiveItem1 = convertToPrimitiveKind(typeList1.item(i));
3257                 final short primitiveItem2 = convertToPrimitiveKind(typeList2.item(i));
3258                 if (primitiveItem1 != primitiveItem2) {
3259                     if (primitiveItem1 == XSConstants.ANYSIMPLETYPE_DT && primitiveItem2 == XSConstants.STRING_DT ||
3260                         primitiveItem1 == XSConstants.STRING_DT && primitiveItem2 == XSConstants.ANYSIMPLETYPE_DT) {
3261                         continue;
3262                     }
3263                     return false;
3264                 }
3265             }
3266         }
3267         return true;
3268     }
3269 
3270     private short convertToPrimitiveKind(short valueType) {
3271         /** Primitive datatypes. */
3272         if (valueType <= XSConstants.NOTATION_DT) {
3273             return valueType;
3274         }
3275         /** Types derived from string. */
3276         if (valueType <= XSConstants.ENTITY_DT) {
3277             return XSConstants.STRING_DT;
3278         }
3279         /** Types derived from decimal. */
3280         if (valueType <= XSConstants.POSITIVEINTEGER_DT) {
3281             return XSConstants.DECIMAL_DT;
3282         }
3283         /** Other types. */
3284         return valueType;
3285     }
3286 
3287     private String expectedStr(Vector expected) {
3288         StringBuffer ret = new StringBuffer("{");
3289         int size = expected.size();
3290         for (int i = 0; i < size; i++) {
3291             if (i > 0)
3292                 ret.append(", ");
3293             ret.append(expected.elementAt(i).toString());
3294         }
3295         ret.append('}');
3296         return ret.toString();
3297     }
3298 
3299     /**********************************/
3300 
3301     // xpath matcher information
3302 
3303     /**
3304      * Stack of XPath matchers for identity constraints.
3305      *
3306      * @author Andy Clark, IBM
3307      */
3308     protected static class XPathMatcherStack {
3309 
3310         //
3311         // Data
3312         //
3313 
3314         /** Active matchers. */
3315         protected XPathMatcher[] fMatchers = new XPathMatcher[4];
3316 
3317         /** Count of active matchers. */
3318         protected int fMatchersCount;
3319 
3320         /** Offset stack for contexts. */
3321         protected IntStack fContextStack = new IntStack();
3322 
3323         //
3324         // Constructors
3325         //
3326 
3327         public XPathMatcherStack() {
3328         } // <init>()
3329 
3330         //
3331         // Public methods
3332         //
3333 
3334         /** Resets the XPath matcher stack. */
3335         public void clear() {
3336             for (int i = 0; i < fMatchersCount; i++) {
3337                 fMatchers[i] = null;
3338             }
3339             fMatchersCount = 0;
3340             fContextStack.clear();
3341         } // clear()
3342 
3343         /** Returns the size of the stack. */
3344         public int size() {
3345             return fContextStack.size();
3346         } // size():int
3347 
3348         /** Returns the count of XPath matchers. */
3349         public int getMatcherCount() {
3350             return fMatchersCount;
3351         } // getMatcherCount():int
3352 
3353         /** Adds a matcher. */
3354         public void addMatcher(XPathMatcher matcher) {
3355             ensureMatcherCapacity();
3356             fMatchers[fMatchersCount++] = matcher;
3357         } // addMatcher(XPathMatcher)
3358 
3359         /** Returns the XPath matcher at the specified index. */
3360         public XPathMatcher getMatcherAt(int index) {
3361             return fMatchers[index];
3362         } // getMatcherAt(index):XPathMatcher
3363 
3364         /** Pushes a new context onto the stack. */
3365         public void pushContext() {
3366             fContextStack.push(fMatchersCount);
3367         } // pushContext()
3368 
3369         /** Pops a context off of the stack. */
3370         public void popContext() {
3371             fMatchersCount = fContextStack.pop();
3372         } // popContext()
3373 
3374         //
3375         // Private methods
3376         //
3377 
3378         /** Ensures the size of the matchers array. */
3379         private void ensureMatcherCapacity() {
3380             if (fMatchersCount == fMatchers.length) {
3381                 XPathMatcher[] array = new XPathMatcher[fMatchers.length * 2];
3382                 System.arraycopy(fMatchers, 0, array, 0, fMatchers.length);
3383                 fMatchers = array;
3384             }
3385         } // ensureMatcherCapacity()
3386 
3387     } // class XPathMatcherStack
3388 
3389     // value store implementations
3390 
3391     /**
3392      * Value store implementation base class. There are specific subclasses
3393      * for handling unique, key, and keyref.
3394      *
3395      * @author Andy Clark, IBM
3396      */
3397     protected abstract class ValueStoreBase implements ValueStore {
3398 
3399         //
3400         // Data
3401         //
3402 
3403         /** Identity constraint. */
3404         protected IdentityConstraint fIdentityConstraint;
3405         protected int fFieldCount = 0;
3406         protected Field[] fFields = null;
3407         /** current data */
3408         protected Object[] fLocalValues = null;
3409         protected short[] fLocalValueTypes = null;
3410         protected ShortList[] fLocalItemValueTypes = null;
3411 
3412         /** Current data value count. */
3413         protected int fValuesCount;
3414 
3415         /** global data */
3416         public final Vector fValues = new Vector();
3417         public ShortVector fValueTypes = null;
3418         public Vector fItemValueTypes = null;
3419 
3420         private boolean fUseValueTypeVector = false;
3421         private int fValueTypesLength = 0;
3422         private short fValueType = 0;
3423 
3424         private boolean fUseItemValueTypeVector = false;
3425         private int fItemValueTypesLength = 0;
3426         private ShortList fItemValueType = null;
3427 
3428         /** buffer for error messages */
3429         final StringBuffer fTempBuffer = new StringBuffer();
3430 
3431         //
3432         // Constructors
3433         //
3434 
3435         /** Constructs a value store for the specified identity constraint. */
3436         protected ValueStoreBase(IdentityConstraint identityConstraint) {
3437             fIdentityConstraint = identityConstraint;
3438             fFieldCount = fIdentityConstraint.getFieldCount();
3439             fFields = new Field[fFieldCount];
3440             fLocalValues = new Object[fFieldCount];
3441             fLocalValueTypes = new short[fFieldCount];
3442             fLocalItemValueTypes = new ShortList[fFieldCount];
3443             for (int i = 0; i < fFieldCount; i++) {
3444                 fFields[i] = fIdentityConstraint.getFieldAt(i);
3445             }
3446         } // <init>(IdentityConstraint)
3447 
3448         //
3449         // Public methods
3450         //
3451 
3452         // destroys this ValueStore; useful when, for instance, a
3453         // locally-scoped ID constraint is involved.
3454         public void clear() {
3455             fValuesCount = 0;
3456             fUseValueTypeVector = false;
3457             fValueTypesLength = 0;
3458             fValueType = 0;
3459             fUseItemValueTypeVector = false;
3460             fItemValueTypesLength = 0;
3461             fItemValueType = null;
3462             fValues.setSize(0);
3463             if (fValueTypes != null) {
3464                 fValueTypes.clear();
3465             }
3466             if (fItemValueTypes != null) {
3467                 fItemValueTypes.setSize(0);
3468             }
3469         } // end clear():void
3470 
3471         // appends the contents of one ValueStore to those of us.
3472         public void append(ValueStoreBase newVal) {
3473             for (int i = 0; i < newVal.fValues.size(); i++) {
3474                 fValues.addElement(newVal.fValues.elementAt(i));
3475             }
3476         } // append(ValueStoreBase)
3477 
3478         /** Start scope for value store. */
3479         public void startValueScope() {
3480             fValuesCount = 0;
3481             for (int i = 0; i < fFieldCount; i++) {
3482                 fLocalValues[i] = null;
3483                 fLocalValueTypes[i] = 0;
3484                 fLocalItemValueTypes[i] = null;
3485             }
3486         } // startValueScope()
3487 
3488         /** Ends scope for value store. */
3489         public void endValueScope() {
3490 
3491             if (fValuesCount == 0) {
3492                 if (fIdentityConstraint.getCategory() == IdentityConstraint.IC_KEY) {
3493                     String code = "AbsentKeyValue";
3494                     String eName = fIdentityConstraint.getElementName();
3495                     String cName = fIdentityConstraint.getIdentityConstraintName();
3496                     reportSchemaError(code, new Object[] { eName, cName });
3497                 }
3498                 return;
3499             }
3500 
3501             // Validation Rule: Identity-constraint Satisfied
3502             // 4.2 If the {identity-constraint category} is key, then all of the following must be true:
3503             // 4.2.1 The target node set and the qualified node set are equal, that is, every member of the
3504             // target node set is also a member of the qualified node set and vice versa.
3505             //
3506             // If the IDC is a key check whether we have all the fields.
3507             if (fValuesCount != fFieldCount) {
3508                 if (fIdentityConstraint.getCategory() == IdentityConstraint.IC_KEY) {
3509                     String code = "KeyNotEnoughValues";
3510                     UniqueOrKey key = (UniqueOrKey) fIdentityConstraint;
3511                     String eName = fIdentityConstraint.getElementName();
3512                     String cName = key.getIdentityConstraintName();
3513                     reportSchemaError(code, new Object[] { eName, cName });
3514                 }
3515                 return;
3516             }
3517 
3518         } // endValueScope()
3519 
3520         // This is needed to allow keyref's to look for matched keys
3521         // in the correct scope.  Unique and Key may also need to
3522         // override this method for purposes of their own.
3523         // This method is called whenever the DocumentFragment
3524         // of an ID Constraint goes out of scope.
3525         public void endDocumentFragment() {
3526         } // endDocumentFragment():void
3527 
3528         /**
3529          * Signals the end of the document. This is where the specific
3530          * instances of value stores can verify the integrity of the
3531          * identity constraints.
3532          */
3533         public void endDocument() {
3534         } // endDocument()
3535 
3536         //
3537         // ValueStore methods
3538         //
3539 
3540         /* reports an error if an element is matched
3541          * has nillable true and is matched by a key.
3542          */
3543 
3544         public void reportError(String key, Object[] args) {
3545             reportSchemaError(key, args);
3546         } // reportError(String,Object[])
3547 
3548         /**
3549          * Adds the specified value to the value store.
3550          *
3551          * @param field The field associated to the value. This reference
3552          *              is used to ensure that each field only adds a value
3553          *              once within a selection scope.
3554          * @param actualValue The value to add.
3555          */
3556         public void addValue(Field field, Object actualValue, short valueType, ShortList itemValueType) {
3557             int i;
3558             for (i = fFieldCount - 1; i > -1; i--) {
3559                 if (fFields[i] == field) {
3560                     break;
3561                 }
3562             }
3563             // do we even know this field?
3564             if (i == -1) {
3565                 String code = "UnknownField";
3566                 String eName = fIdentityConstraint.getElementName();
3567                 String cName = fIdentityConstraint.getIdentityConstraintName();
3568                 reportSchemaError(code, new Object[] { field.toString(), eName, cName });
3569                 return;
3570             }
3571             if (Boolean.TRUE != mayMatch(field)) {
3572                 String code = "FieldMultipleMatch";
3573                 String cName = fIdentityConstraint.getIdentityConstraintName();
3574                 reportSchemaError(code, new Object[] { field.toString(), cName });
3575             } else {
3576                 fValuesCount++;
3577             }
3578             fLocalValues[i] = actualValue;
3579             fLocalValueTypes[i] = valueType;
3580             fLocalItemValueTypes[i] = itemValueType;
3581             if (fValuesCount == fFieldCount) {
3582                 checkDuplicateValues();
3583                 // store values
3584                 for (i = 0; i < fFieldCount; i++) {
3585                     fValues.addElement(fLocalValues[i]);
3586                     addValueType(fLocalValueTypes[i]);
3587                     addItemValueType(fLocalItemValueTypes[i]);
3588                 }
3589             }
3590         } // addValue(String,Field)
3591 
3592         /**
3593          * Returns true if this value store contains the locally scoped value stores
3594          */
3595         public boolean contains() {
3596             // REVISIT: we can improve performance by using hash codes, instead of
3597             // traversing global vector that could be quite large.
3598             int next = 0;
3599             final int size = fValues.size();
3600             LOOP : for (int i = 0; i < size; i = next) {
3601                 next = i + fFieldCount;
3602                 for (int j = 0; j < fFieldCount; j++) {
3603                     Object value1 = fLocalValues[j];
3604                     Object value2 = fValues.elementAt(i);
3605                     short valueType1 = fLocalValueTypes[j];
3606                     short valueType2 = getValueTypeAt(i);
3607                     if (value1 == null || value2 == null || valueType1 != valueType2 || !(value1.equals(value2))) {
3608                         continue LOOP;
3609                     }
3610                     else if(valueType1 == XSConstants.LIST_DT || valueType1 == XSConstants.LISTOFUNION_DT) {
3611                         ShortList list1 = fLocalItemValueTypes[j];
3612                         ShortList list2 = getItemValueTypeAt(i);
3613                         if(list1 == null || list2 == null || !list1.equals(list2))
3614                             continue LOOP;
3615                     }
3616                     i++;
3617                 }
3618                 // found it
3619                 return true;
3620             }
3621             // didn't find it
3622             return false;
3623         } // contains():boolean
3624 
3625         /**
3626          * Returns -1 if this value store contains the specified
3627          * values, otherwise the index of the first field in the
3628          * key sequence.
3629          */
3630         public int contains(ValueStoreBase vsb) {
3631 
3632             final Vector values = vsb.fValues;
3633             final int size1 = values.size();
3634             if (fFieldCount <= 1) {
3635                 for (int i = 0; i < size1; ++i) {
3636                     short val = vsb.getValueTypeAt(i);
3637                     if (!valueTypeContains(val) || !fValues.contains(values.elementAt(i))) {
3638                         return i;
3639                     }
3640                     else if(val == XSConstants.LIST_DT || val == XSConstants.LISTOFUNION_DT) {
3641                         ShortList list1 = vsb.getItemValueTypeAt(i);
3642                         if (!itemValueTypeContains(list1)) {
3643                             return i;
3644                         }
3645                     }
3646                 }
3647             }
3648             /** Handle n-tuples. **/
3649             else {
3650                 final int size2 = fValues.size();
3651                 /** Iterate over each set of fields. **/
3652                 OUTER: for (int i = 0; i < size1; i += fFieldCount) {
3653                     /** Check whether this set is contained in the value store. **/
3654                     INNER: for (int j = 0; j < size2; j += fFieldCount) {
3655                         for (int k = 0; k < fFieldCount; ++k) {
3656                             final Object value1 = values.elementAt(i+k);
3657                             final Object value2 = fValues.elementAt(j+k);
3658                             final short valueType1 = vsb.getValueTypeAt(i+k);
3659                             final short valueType2 = getValueTypeAt(j+k);
3660                             if (value1 != value2 && (valueType1 != valueType2 || value1 == null || !value1.equals(value2))) {
3661                                 continue INNER;
3662                             }
3663                             else if(valueType1 == XSConstants.LIST_DT || valueType1 == XSConstants.LISTOFUNION_DT) {
3664                                 ShortList list1 = vsb.getItemValueTypeAt(i+k);
3665                                 ShortList list2 = getItemValueTypeAt(j+k);
3666                                 if (list1 == null || list2 == null || !list1.equals(list2)) {
3667                                     continue INNER;
3668                                 }
3669                             }
3670                         }
3671                         continue OUTER;
3672                     }
3673                     return i;
3674                 }
3675             }
3676             return -1;
3677 
3678         } // contains(Vector):Object
3679 
3680         //
3681         // Protected methods
3682         //
3683 
3684         protected void checkDuplicateValues() {
3685             // no-op
3686         } // duplicateValue(Hashtable)
3687 
3688         /** Returns a string of the specified values. */
3689         protected String toString(Object[] values) {
3690 
3691             // no values
3692             int size = values.length;
3693             if (size == 0) {
3694                 return "";
3695             }
3696 
3697             fTempBuffer.setLength(0);
3698 
3699             // construct value string
3700             for (int i = 0; i < size; i++) {
3701                 if (i > 0) {
3702                     fTempBuffer.append(',');
3703                 }
3704                 fTempBuffer.append(values[i]);
3705             }
3706             return fTempBuffer.toString();
3707 
3708         } // toString(Object[]):String
3709 
3710         /** Returns a string of the specified values. */
3711         protected String toString(Vector values, int start, int length) {
3712 
3713             // no values
3714             if (length == 0) {
3715                 return "";
3716             }
3717 
3718             // one value
3719             if (length == 1) {
3720                 return String.valueOf(values.elementAt(start));
3721             }
3722 
3723             // construct value string
3724             StringBuffer str = new StringBuffer();
3725             for (int i = 0; i < length; i++) {
3726                 if (i > 0) {
3727                     str.append(',');
3728                 }
3729                 str.append(values.elementAt(start + i));
3730             }
3731             return str.toString();
3732 
3733         } // toString(Vector,int,int):String
3734 
3735         //
3736         // Object methods
3737         //
3738 
3739         /** Returns a string representation of this object. */
3740         public String toString() {
3741             String s = super.toString();
3742             int index1 = s.lastIndexOf('$');
3743             if (index1 != -1) {
3744                 s = s.substring(index1 + 1);
3745             }
3746             int index2 = s.lastIndexOf('.');
3747             if (index2 != -1) {
3748                 s = s.substring(index2 + 1);
3749             }
3750             return s + '[' + fIdentityConstraint + ']';
3751         } // toString():String
3752 
3753         //
3754         // Private methods
3755         //
3756 
3757         private void addValueType(short type) {
3758             if (fUseValueTypeVector) {
3759                 fValueTypes.add(type);
3760             }
3761             else if (fValueTypesLength++ == 0) {
3762                 fValueType = type;
3763             }
3764             else if (fValueType != type) {
3765                 fUseValueTypeVector = true;
3766                 if (fValueTypes == null) {
3767                     fValueTypes = new ShortVector(fValueTypesLength * 2);
3768                 }
3769                 for (int i = 1; i < fValueTypesLength; ++i) {
3770                     fValueTypes.add(fValueType);
3771                 }
3772                 fValueTypes.add(type);
3773             }
3774         }
3775 
3776         private short getValueTypeAt(int index) {
3777             if (fUseValueTypeVector) {
3778                 return fValueTypes.valueAt(index);
3779             }
3780             return fValueType;
3781         }
3782 
3783         private boolean valueTypeContains(short value) {
3784             if (fUseValueTypeVector) {
3785                 return fValueTypes.contains(value);
3786             }
3787             return fValueType == value;
3788         }
3789 
3790         private void addItemValueType(ShortList itemValueType) {
3791             if (fUseItemValueTypeVector) {
3792                 fItemValueTypes.add(itemValueType);
3793             }
3794             else if (fItemValueTypesLength++ == 0) {
3795                 fItemValueType = itemValueType;
3796             }
3797             else if (!(fItemValueType == itemValueType ||
3798                     (fItemValueType != null && fItemValueType.equals(itemValueType)))) {
3799                 fUseItemValueTypeVector = true;
3800                 if (fItemValueTypes == null) {
3801                     fItemValueTypes = new Vector(fItemValueTypesLength * 2);
3802                 }
3803                 for (int i = 1; i < fItemValueTypesLength; ++i) {
3804                     fItemValueTypes.add(fItemValueType);
3805                 }
3806                 fItemValueTypes.add(itemValueType);
3807             }
3808         }
3809 
3810         private ShortList getItemValueTypeAt(int index) {
3811             if (fUseItemValueTypeVector) {
3812                 return (ShortList) fItemValueTypes.elementAt(index);
3813             }
3814             return fItemValueType;
3815         }
3816 
3817         private boolean itemValueTypeContains(ShortList value) {
3818             if (fUseItemValueTypeVector) {
3819                 return fItemValueTypes.contains(value);
3820             }
3821             return fItemValueType == value ||
3822                 (fItemValueType != null && fItemValueType.equals(value));
3823         }
3824 
3825     } // class ValueStoreBase
3826 
3827     /**
3828      * Unique value store.
3829      *
3830      * @author Andy Clark, IBM
3831      */
3832     protected class UniqueValueStore extends ValueStoreBase {
3833 
3834         //
3835         // Constructors
3836         //
3837 
3838         /** Constructs a unique value store. */
3839         public UniqueValueStore(UniqueOrKey unique) {
3840             super(unique);
3841         } // <init>(Unique)
3842 
3843         //
3844         // ValueStoreBase protected methods
3845         //
3846 
3847         /**
3848          * Called when a duplicate value is added.
3849          */
3850         protected void checkDuplicateValues() {
3851             // is this value as a group duplicated?
3852             if (contains()) {
3853                 String code = "DuplicateUnique";
3854                 String value = toString(fLocalValues);
3855                 String eName = fIdentityConstraint.getElementName();
3856                 String cName = fIdentityConstraint.getIdentityConstraintName();
3857                 reportSchemaError(code, new Object[] { value, eName, cName });
3858             }
3859         } // duplicateValue(Hashtable)
3860 
3861     } // class UniqueValueStore
3862 
3863     /**
3864      * Key value store.
3865      *
3866      * @author Andy Clark, IBM
3867      */
3868     protected class KeyValueStore extends ValueStoreBase {
3869 
3870         // REVISIT: Implement a more efficient storage mechanism. -Ac
3871 
3872         //
3873         // Constructors
3874         //
3875 
3876         /** Constructs a key value store. */
3877         public KeyValueStore(UniqueOrKey key) {
3878             super(key);
3879         } // <init>(Key)
3880 
3881         //
3882         // ValueStoreBase protected methods
3883         //
3884 
3885         /**
3886          * Called when a duplicate value is added.
3887          */
3888         protected void checkDuplicateValues() {
3889             if (contains()) {
3890                 String code = "DuplicateKey";
3891                 String value = toString(fLocalValues);
3892                 String eName = fIdentityConstraint.getElementName();
3893                 String cName = fIdentityConstraint.getIdentityConstraintName();
3894                 reportSchemaError(code, new Object[] { value, eName, cName });
3895             }
3896         } // duplicateValue(Hashtable)
3897 
3898     } // class KeyValueStore
3899 
3900     /**
3901      * Key reference value store.
3902      *
3903      * @author Andy Clark, IBM
3904      */
3905     protected class KeyRefValueStore extends ValueStoreBase {
3906 
3907         //
3908         // Data
3909         //
3910 
3911         /** Key value store. */
3912         protected ValueStoreBase fKeyValueStore;
3913 
3914         //
3915         // Constructors
3916         //
3917 
3918         /** Constructs a key value store. */
3919         public KeyRefValueStore(KeyRef keyRef, KeyValueStore keyValueStore) {
3920             super(keyRef);
3921             fKeyValueStore = keyValueStore;
3922         } // <init>(KeyRef)
3923 
3924         //
3925         // ValueStoreBase methods
3926         //
3927 
3928         // end the value Scope; here's where we have to tie
3929         // up keyRef loose ends.
3930         public void endDocumentFragment() {
3931 
3932             // do all the necessary management...
3933             super.endDocumentFragment();
3934 
3935             // verify references
3936             // get the key store corresponding (if it exists):
3937             fKeyValueStore =
3938                 (ValueStoreBase) fValueStoreCache.fGlobalIDConstraintMap.get(
3939                     ((KeyRef) fIdentityConstraint).getKey());
3940 
3941             if (fKeyValueStore == null) {
3942                 // report error
3943                 String code = "KeyRefOutOfScope";
3944                 String value = fIdentityConstraint.toString();
3945                 reportSchemaError(code, new Object[] { value });
3946                 return;
3947             }
3948             int errorIndex = fKeyValueStore.contains(this);
3949             if (errorIndex != -1) {
3950                 String code = "KeyNotFound";
3951                 String values = toString(fValues, errorIndex, fFieldCount);
3952                 String element = fIdentityConstraint.getElementName();
3953                 String name = fIdentityConstraint.getName();
3954                 reportSchemaError(code, new Object[] { name, values, element });
3955             }
3956 
3957         } // endDocumentFragment()
3958 
3959         /** End document. */
3960         public void endDocument() {
3961             super.endDocument();
3962 
3963         } // endDocument()
3964 
3965     } // class KeyRefValueStore
3966 
3967     // value store management
3968 
3969     /**
3970      * Value store cache. This class is used to store the values for
3971      * identity constraints.
3972      *
3973      * @author Andy Clark, IBM
3974      */
3975     protected class ValueStoreCache {
3976 
3977         //
3978         // Data
3979         //
3980         final LocalIDKey fLocalId = new LocalIDKey();
3981         // values stores
3982 
3983         /** stores all global Values stores. */
3984         protected final Vector fValueStores = new Vector();
3985 
3986         /**
3987          * Values stores associated to specific identity constraints.
3988          * This hashtable maps IdentityConstraints and
3989          * the 0-based element on which their selectors first matched to
3990          * a corresponding ValueStore.  This should take care
3991          * of all cases, including where ID constraints with
3992          * descendant-or-self axes occur on recursively-defined
3993          * elements.
3994          */
3995         protected final Hashtable fIdentityConstraint2ValueStoreMap = new Hashtable();
3996 
3997         // sketch of algorithm:
3998         // - when a constraint is first encountered, its
3999         //   values are stored in the (local) fIdentityConstraint2ValueStoreMap;
4000         // - Once it is validated (i.e., when it goes out of scope),
4001         //   its values are merged into the fGlobalIDConstraintMap;
4002         // - as we encounter keyref's, we look at the global table to
4003         //    validate them.
4004         //
4005         // The fGlobalIDMapStack has the following structure:
4006         // - validation always occurs against the fGlobalIDConstraintMap
4007         // (which comprises all the "eligible" id constraints);
4008         // When an endElement is found, this Hashtable is merged with the one
4009         // below in the stack.
4010         // When a start tag is encountered, we create a new
4011         // fGlobalIDConstraintMap.
4012         // i.e., the top of the fGlobalIDMapStack always contains
4013         // the preceding siblings' eligible id constraints;
4014         // the fGlobalIDConstraintMap contains descendants+self.
4015         // keyrefs can only match descendants+self.
4016         protected final Stack fGlobalMapStack = new Stack();
4017         protected final Hashtable fGlobalIDConstraintMap = new Hashtable();
4018 
4019         //
4020         // Constructors
4021         //
4022 
4023         /** Default constructor. */
4024         public ValueStoreCache() {
4025         } // <init>()
4026 
4027         //
4028         // Public methods
4029         //
4030 
4031         /** Resets the identity constraint cache. */
4032         public void startDocument() {
4033             fValueStores.removeAllElements();
4034             fIdentityConstraint2ValueStoreMap.clear();
4035             fGlobalIDConstraintMap.clear();
4036             fGlobalMapStack.removeAllElements();
4037         } // startDocument()
4038 
4039         // startElement:  pushes the current fGlobalIDConstraintMap
4040         // onto fGlobalMapStack and clears fGlobalIDConstraint map.
4041         public void startElement() {
4042             // only clone the hashtable when there are elements
4043             if (fGlobalIDConstraintMap.size() > 0)
4044                 fGlobalMapStack.push(fGlobalIDConstraintMap.clone());
4045             else
4046                 fGlobalMapStack.push(null);
4047             fGlobalIDConstraintMap.clear();
4048         } // startElement(void)
4049 
4050         /** endElement():  merges contents of fGlobalIDConstraintMap with the
4051          * top of fGlobalMapStack into fGlobalIDConstraintMap.
4052          */
4053         public void endElement() {
4054             if (fGlobalMapStack.isEmpty()) {
4055                 return; // must be an invalid doc!
4056             }
4057             Hashtable oldMap = (Hashtable) fGlobalMapStack.pop();
4058             // return if there is no element
4059             if (oldMap == null) {
4060                 return;
4061             }
4062 
4063             Iterator entries = oldMap.entrySet().iterator();
4064             while (entries.hasNext()) {
4065                 Map.Entry entry = (Map.Entry) entries.next();
4066                 IdentityConstraint id = (IdentityConstraint) entry.getKey();
4067                 ValueStoreBase oldVal = (ValueStoreBase) entry.getValue();
4068                 if (oldVal != null) {
4069                     ValueStoreBase currVal = (ValueStoreBase) fGlobalIDConstraintMap.get(id);
4070                     if (currVal == null) {
4071                         fGlobalIDConstraintMap.put(id, oldVal);
4072                     }
4073                     else if (currVal != oldVal) {
4074                         currVal.append(oldVal);
4075                     }
4076                 }
4077             }
4078         } // endElement()
4079 
4080         /**
4081          * Initializes the value stores for the specified element
4082          * declaration.
4083          */
4084         public void initValueStoresFor(XSElementDecl eDecl, FieldActivator activator) {
4085             // initialize value stores for unique fields
4086             IdentityConstraint[] icArray = eDecl.fIDConstraints;
4087             int icCount = eDecl.fIDCPos;
4088             for (int i = 0; i < icCount; i++) {
4089                 switch (icArray[i].getCategory()) {
4090                     case (IdentityConstraint.IC_UNIQUE) :
4091                         // initialize value stores for unique fields
4092                         UniqueOrKey unique = (UniqueOrKey) icArray[i];
4093                         LocalIDKey toHash = new LocalIDKey(unique, fElementDepth);
4094                         UniqueValueStore uniqueValueStore =
4095                             (UniqueValueStore) fIdentityConstraint2ValueStoreMap.get(toHash);
4096                         if (uniqueValueStore == null) {
4097                             uniqueValueStore = new UniqueValueStore(unique);
4098                             fIdentityConstraint2ValueStoreMap.put(toHash, uniqueValueStore);
4099                         } else {
4100                             uniqueValueStore.clear();
4101                         }
4102                         fValueStores.addElement(uniqueValueStore);
4103                         activateSelectorFor(icArray[i]);
4104                         break;
4105                     case (IdentityConstraint.IC_KEY) :
4106                         // initialize value stores for key fields
4107                         UniqueOrKey key = (UniqueOrKey) icArray[i];
4108                         toHash = new LocalIDKey(key, fElementDepth);
4109                         KeyValueStore keyValueStore =
4110                             (KeyValueStore) fIdentityConstraint2ValueStoreMap.get(toHash);
4111                         if (keyValueStore == null) {
4112                             keyValueStore = new KeyValueStore(key);
4113                             fIdentityConstraint2ValueStoreMap.put(toHash, keyValueStore);
4114                         } else {
4115                             keyValueStore.clear();
4116                         }
4117                         fValueStores.addElement(keyValueStore);
4118                         activateSelectorFor(icArray[i]);
4119                         break;
4120                     case (IdentityConstraint.IC_KEYREF) :
4121                         // initialize value stores for keyRef fields
4122                         KeyRef keyRef = (KeyRef) icArray[i];
4123                         toHash = new LocalIDKey(keyRef, fElementDepth);
4124                         KeyRefValueStore keyRefValueStore =
4125                             (KeyRefValueStore) fIdentityConstraint2ValueStoreMap.get(toHash);
4126                         if (keyRefValueStore == null) {
4127                             keyRefValueStore = new KeyRefValueStore(keyRef, null);
4128                             fIdentityConstraint2ValueStoreMap.put(toHash, keyRefValueStore);
4129                         } else {
4130                             keyRefValueStore.clear();
4131                         }
4132                         fValueStores.addElement(keyRefValueStore);
4133                         activateSelectorFor(icArray[i]);
4134                         break;
4135                 }
4136             }
4137         } // initValueStoresFor(XSElementDecl)
4138 
4139         /** Returns the value store associated to the specified IdentityConstraint. */
4140         public ValueStoreBase getValueStoreFor(IdentityConstraint id, int initialDepth) {
4141             fLocalId.fDepth = initialDepth;
4142             fLocalId.fId = id;
4143             return (ValueStoreBase) fIdentityConstraint2ValueStoreMap.get(fLocalId);
4144         } // getValueStoreFor(IdentityConstraint, int):ValueStoreBase
4145 
4146         /** Returns the global value store associated to the specified IdentityConstraint. */
4147         public ValueStoreBase getGlobalValueStoreFor(IdentityConstraint id) {
4148             return (ValueStoreBase) fGlobalIDConstraintMap.get(id);
4149         } // getValueStoreFor(IdentityConstraint):ValueStoreBase
4150 
4151         // This method takes the contents of the (local) ValueStore
4152         // associated with id and moves them into the global
4153         // hashtable, if id is a <unique> or a <key>.
4154         // If it's a <keyRef>, then we leave it for later.
4155         public void transplant(IdentityConstraint id, int initialDepth) {
4156             fLocalId.fDepth = initialDepth;
4157             fLocalId.fId = id;
4158             ValueStoreBase newVals =
4159                 (ValueStoreBase) fIdentityConstraint2ValueStoreMap.get(fLocalId);
4160             if (id.getCategory() == IdentityConstraint.IC_KEYREF)
4161                 return;
4162             ValueStoreBase currVals = (ValueStoreBase) fGlobalIDConstraintMap.get(id);
4163             if (currVals != null) {
4164                 currVals.append(newVals);
4165                 fGlobalIDConstraintMap.put(id, currVals);
4166             } else
4167                 fGlobalIDConstraintMap.put(id, newVals);
4168 
4169         } // transplant(id)
4170 
4171         /** Check identity constraints. */
4172         public void endDocument() {
4173 
4174             int count = fValueStores.size();
4175             for (int i = 0; i < count; i++) {
4176                 ValueStoreBase valueStore = (ValueStoreBase) fValueStores.elementAt(i);
4177                 valueStore.endDocument();
4178             }
4179 
4180         } // endDocument()
4181 
4182         //
4183         // Object methods
4184         //
4185 
4186         /** Returns a string representation of this object. */
4187         public String toString() {
4188             String s = super.toString();
4189             int index1 = s.lastIndexOf('$');
4190             if (index1 != -1) {
4191                 return s.substring(index1 + 1);
4192             }
4193             int index2 = s.lastIndexOf('.');
4194             if (index2 != -1) {
4195                 return s.substring(index2 + 1);
4196             }
4197             return s;
4198         } // toString():String
4199 
4200     } // class ValueStoreCache
4201 
4202     // the purpose of this class is to enable IdentityConstraint,int
4203     // pairs to be used easily as keys in Hashtables.
4204     protected class LocalIDKey {
4205 
4206         public IdentityConstraint fId;
4207         public int fDepth;
4208 
4209         public LocalIDKey() {
4210         }
4211 
4212         public LocalIDKey(IdentityConstraint id, int depth) {
4213             fId = id;
4214             fDepth = depth;
4215         } // init(IdentityConstraint, int)
4216 
4217         // object method
4218         public int hashCode() {
4219             return fId.hashCode() + fDepth;
4220         }
4221 
4222         public boolean equals(Object localIDKey) {
4223             if (localIDKey instanceof LocalIDKey) {
4224                 LocalIDKey lIDKey = (LocalIDKey) localIDKey;
4225                 return (lIDKey.fId == fId && lIDKey.fDepth == fDepth);
4226             }
4227             return false;
4228         }
4229     } // class LocalIDKey
4230 
4231     /**
4232      * A simple vector for <code>short</code>s.
4233      */
4234     protected static final class ShortVector {
4235 
4236         //
4237         // Data
4238         //
4239 
4240         /** Current length. */
4241         private int fLength;
4242 
4243         /** Data. */
4244         private short[] fData;
4245 
4246         //
4247         // Constructors
4248         //
4249 
4250         public ShortVector() {}
4251 
4252         public ShortVector(int initialCapacity) {
4253             fData = new short[initialCapacity];
4254         }
4255 
4256         //
4257         // Public methods
4258         //
4259 
4260         /** Returns the length of the vector. */
4261         public int length() {
4262             return fLength;
4263         }
4264 
4265         /** Adds the value to the vector. */
4266         public void add(short value) {
4267             ensureCapacity(fLength + 1);
4268             fData[fLength++] = value;
4269         }
4270 
4271         /** Returns the short value at the specified position in the vector. */
4272         public short valueAt(int position) {
4273             return fData[position];
4274         }
4275 
4276         /** Clears the vector. */
4277         public void clear() {
4278             fLength = 0;
4279         }
4280 
4281         /** Returns whether the short is contained in the vector. */
4282         public boolean contains(short value) {
4283             for (int i = 0; i < fLength; ++i) {
4284                 if (fData[i] == value) {
4285                     return true;
4286                 }
4287             }
4288             return false;
4289         }
4290 
4291         //
4292         // Private methods
4293         //
4294 
4295         /** Ensures capacity. */
4296         private void ensureCapacity(int size) {
4297             if (fData == null) {
4298                 fData = new short[8];
4299             }
4300             else if (fData.length <= size) {
4301                 short[] newdata = new short[fData.length * 2];
4302                 System.arraycopy(fData, 0, newdata, 0, fData.length);
4303                 fData = newdata;
4304             }
4305         }
4306     }
4307 
4308 } // class SchemaValidator