1 /*
   2  * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  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 com.sun.org.apache.xerces.internal.impl.Constants;
  24 import com.sun.org.apache.xerces.internal.impl.RevalidationHandler;
  25 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
  26 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
  27 import com.sun.org.apache.xerces.internal.impl.dv.DatatypeException;
  28 import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
  29 import com.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo;
  30 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
  31 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
  32 import com.sun.org.apache.xerces.internal.impl.validation.ValidationState;
  33 import com.sun.org.apache.xerces.internal.impl.xs.identity.Field;
  34 import com.sun.org.apache.xerces.internal.impl.xs.identity.FieldActivator;
  35 import com.sun.org.apache.xerces.internal.impl.xs.identity.IdentityConstraint;
  36 import com.sun.org.apache.xerces.internal.impl.xs.identity.KeyRef;
  37 import com.sun.org.apache.xerces.internal.impl.xs.identity.Selector;
  38 import com.sun.org.apache.xerces.internal.impl.xs.identity.UniqueOrKey;
  39 import com.sun.org.apache.xerces.internal.impl.xs.identity.ValueStore;
  40 import com.sun.org.apache.xerces.internal.impl.xs.identity.XPathMatcher;
  41 import com.sun.org.apache.xerces.internal.impl.xs.models.CMBuilder;
  42 import com.sun.org.apache.xerces.internal.impl.xs.models.CMNodeFactory;
  43 import com.sun.org.apache.xerces.internal.impl.xs.models.XSCMValidator;
  44 import com.sun.org.apache.xerces.internal.parsers.XMLParser;
  45 import com.sun.org.apache.xerces.internal.util.AugmentationsImpl;
  46 import com.sun.org.apache.xerces.internal.util.IntStack;
  47 import com.sun.org.apache.xerces.internal.util.SymbolTable;
  48 import com.sun.org.apache.xerces.internal.util.URI.MalformedURIException;
  49 import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl;
  50 import com.sun.org.apache.xerces.internal.util.XMLChar;
  51 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
  52 import com.sun.org.apache.xerces.internal.xni.Augmentations;
  53 import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
  54 import com.sun.org.apache.xerces.internal.xni.QName;
  55 import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
  56 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
  57 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
  58 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
  59 import com.sun.org.apache.xerces.internal.xni.XMLString;
  60 import com.sun.org.apache.xerces.internal.xni.XNIException;
  61 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
  62 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
  63 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
  64 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
  65 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  66 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentFilter;
  67 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
  68 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
  69 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
  70 import com.sun.org.apache.xerces.internal.xs.AttributePSVI;
  71 import com.sun.org.apache.xerces.internal.xs.ElementPSVI;
  72 import com.sun.org.apache.xerces.internal.xs.ShortList;
  73 import com.sun.org.apache.xerces.internal.xs.StringList;
  74 import com.sun.org.apache.xerces.internal.xs.XSConstants;
  75 import com.sun.org.apache.xerces.internal.xs.XSObjectList;
  76 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
  77 import java.io.IOException;
  78 import java.util.ArrayList;
  79 import java.util.Collections;
  80 import java.util.HashMap;
  81 import java.util.Map;
  82 import java.util.Stack;
  83 import java.util.Vector;
  84 import jdk.xml.internal.JdkXmlUtils;
  85 
  86 /**
  87  * The XML Schema validator. The validator implements a document
  88  * filter: receiving document events from the scanner; validating
  89  * the content and structure; augmenting the InfoSet, if applicable;
  90  * and notifying the parser of the information resulting from the
  91  * validation process.
  92  * <p>
  93  * This component requires the following features and properties from the
  94  * component manager that uses it:
  95  * <ul>
  96  *  <li>http://xml.org/sax/features/validation</li>
  97  *  <li>http://apache.org/xml/properties/internal/symbol-table</li>
  98  *  <li>http://apache.org/xml/properties/internal/error-reporter</li>
  99  *  <li>http://apache.org/xml/properties/internal/entity-resolver</li>
 100  * </ul>
 101  *
 102  * @xerces.internal
 103  *
 104  * @author Sandy Gao IBM
 105  * @author Elena Litani IBM
 106  * @author Andy Clark IBM
 107  * @author Neeraj Bajaj, Sun Microsystems, inc.
 108  * @LastModified: Apr 2020
 109  */
 110 public class XMLSchemaValidator
 111     implements XMLComponent, XMLDocumentFilter, FieldActivator, RevalidationHandler {
 112 
 113     //
 114     // Constants
 115     //
 116     private static final boolean DEBUG = false;
 117 
 118     // feature identifiers
 119 
 120     /** Feature identifier: validation. */
 121     protected static final String VALIDATION =
 122         Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
 123 
 124     /** Feature identifier: validation. */
 125     protected static final String SCHEMA_VALIDATION =
 126         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
 127 
 128     /** Feature identifier: schema full checking*/
 129     protected static final String SCHEMA_FULL_CHECKING =
 130         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING;
 131 
 132     /** Feature identifier: dynamic validation. */
 133     protected static final String DYNAMIC_VALIDATION =
 134         Constants.XERCES_FEATURE_PREFIX + Constants.DYNAMIC_VALIDATION_FEATURE;
 135 
 136     /** Feature identifier: expose schema normalized value */
 137     protected static final String NORMALIZE_DATA =
 138         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE;
 139 
 140     /** Feature identifier: send element default value via characters() */
 141     protected static final String SCHEMA_ELEMENT_DEFAULT =
 142         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_ELEMENT_DEFAULT;
 143 
 144     /** Feature identifier: augment PSVI */
 145     protected static final String SCHEMA_AUGMENT_PSVI =
 146         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_AUGMENT_PSVI;
 147 
 148     /** Feature identifier: whether to recognize java encoding names */
 149     protected static final String ALLOW_JAVA_ENCODINGS =
 150         Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
 151 
 152     /** Feature identifier: standard uri conformant feature. */
 153     protected static final String STANDARD_URI_CONFORMANT_FEATURE =
 154         Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE;
 155 
 156     /** Feature: generate synthetic annotations */
 157     protected static final String GENERATE_SYNTHETIC_ANNOTATIONS =
 158         Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE;
 159 
 160     /** Feature identifier: validate annotations. */
 161     protected static final String VALIDATE_ANNOTATIONS =
 162         Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATE_ANNOTATIONS_FEATURE;
 163 
 164     /** Feature identifier: honour all schemaLocations */
 165     protected static final String HONOUR_ALL_SCHEMALOCATIONS =
 166         Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE;
 167 
 168     /** Feature identifier: use grammar pool only */
 169     protected static final String USE_GRAMMAR_POOL_ONLY =
 170         Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE;
 171 
 172     /** Feature identifier: whether to continue parsing a schema after a fatal error is encountered */
 173     protected static final String CONTINUE_AFTER_FATAL_ERROR =
 174         Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
 175 
 176     protected static final String PARSER_SETTINGS =
 177             Constants.XERCES_FEATURE_PREFIX + Constants.PARSER_SETTINGS;
 178 
 179     /** Feature identifier: namespace growth */
 180     protected static final String NAMESPACE_GROWTH =
 181         Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE;
 182 
 183     /** Feature identifier: tolerate duplicates */
 184     protected static final String TOLERATE_DUPLICATES =
 185         Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_FEATURE;
 186 
 187     protected static final String REPORT_WHITESPACE =
 188             Constants.SUN_SCHEMA_FEATURE_PREFIX + Constants.SUN_REPORT_IGNORED_ELEMENT_CONTENT_WHITESPACE;
 189 
 190     // property identifiers
 191 
 192     /** Property identifier: symbol table. */
 193     public static final String SYMBOL_TABLE =
 194         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
 195 
 196     /** Property identifier: error reporter. */
 197     public static final String ERROR_REPORTER =
 198         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
 199 
 200     /** Property identifier: entity resolver. */
 201     public static final String ENTITY_RESOLVER =
 202         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
 203 
 204     /** Property identifier: grammar pool. */
 205     public static final String XMLGRAMMAR_POOL =
 206         Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
 207 
 208     protected static final String VALIDATION_MANAGER =
 209         Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
 210 
 211     protected static final String ENTITY_MANAGER =
 212         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
 213 
 214     /** Property identifier: schema location. */
 215     protected static final String SCHEMA_LOCATION =
 216         Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_LOCATION;
 217 
 218     /** Property identifier: no namespace schema location. */
 219     protected static final String SCHEMA_NONS_LOCATION =
 220         Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_NONS_LOCATION;
 221 
 222     /** Property identifier: JAXP schema source. */
 223     protected static final String JAXP_SCHEMA_SOURCE =
 224         Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
 225 
 226     /** Property identifier: JAXP schema language. */
 227     protected static final String JAXP_SCHEMA_LANGUAGE =
 228         Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE;
 229 
 230     /** Property identifier: Schema DV Factory */
 231     protected static final String SCHEMA_DV_FACTORY =
 232         Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY;
 233 
 234     /** Property identifier: Security property manager. */
 235     private static final String XML_SECURITY_PROPERTY_MANAGER =
 236             Constants.XML_SECURITY_PROPERTY_MANAGER;
 237 
 238     protected static final String OVERRIDE_PARSER = JdkXmlUtils.OVERRIDE_PARSER;
 239 
 240     // recognized features and properties
 241 
 242     /** Recognized features. */
 243     private static final String[] RECOGNIZED_FEATURES =
 244         {
 245             VALIDATION,
 246             SCHEMA_VALIDATION,
 247             DYNAMIC_VALIDATION,
 248             SCHEMA_FULL_CHECKING,
 249             ALLOW_JAVA_ENCODINGS,
 250             CONTINUE_AFTER_FATAL_ERROR,
 251             STANDARD_URI_CONFORMANT_FEATURE,
 252             GENERATE_SYNTHETIC_ANNOTATIONS,
 253             VALIDATE_ANNOTATIONS,
 254             HONOUR_ALL_SCHEMALOCATIONS,
 255             USE_GRAMMAR_POOL_ONLY,
 256             NAMESPACE_GROWTH,
 257             TOLERATE_DUPLICATES,
 258             OVERRIDE_PARSER
 259     };
 260 
 261     /** Feature defaults. */
 262     private static final Boolean[] FEATURE_DEFAULTS = { null,
 263         // NOTE: The following defaults are nulled out on purpose.
 264         //       If they are set, then when the XML Schema validator
 265         //       is constructed dynamically, these values may override
 266         //       those set by the application. This goes against the
 267         //       whole purpose of XMLComponent#getFeatureDefault but
 268         //       it can't be helped in this case. -Ac
 269         null, //Boolean.FALSE,
 270         null, //Boolean.FALSE,
 271         null, //Boolean.FALSE,
 272         null, //Boolean.FALSE,
 273         null, //Boolean.FALSE,
 274         null,
 275         null,
 276         null,
 277         null,
 278         null,
 279         null,
 280         null,
 281         JdkXmlUtils.OVERRIDE_PARSER_DEFAULT
 282     };
 283 
 284     /** Recognized properties. */
 285     private static final String[] RECOGNIZED_PROPERTIES =
 286         {
 287             SYMBOL_TABLE,
 288             ERROR_REPORTER,
 289             ENTITY_RESOLVER,
 290             VALIDATION_MANAGER,
 291             SCHEMA_LOCATION,
 292             SCHEMA_NONS_LOCATION,
 293             JAXP_SCHEMA_SOURCE,
 294             JAXP_SCHEMA_LANGUAGE,
 295             SCHEMA_DV_FACTORY,
 296             XML_SECURITY_PROPERTY_MANAGER
 297             };
 298 
 299     /** Property defaults. */
 300     private static final Object[] PROPERTY_DEFAULTS =
 301         { null, null, null, null, null, null, null, null, null, null, null, null, null};
 302 
 303     // this is the number of valuestores of each kind
 304     // we expect an element to have.  It's almost
 305     // never > 1; so leave it at that.
 306     protected static final int ID_CONSTRAINT_NUM = 1;
 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 Map<String, XMLSchemaLoader.LocationArray> fLocationPairs = new HashMap<>();
 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 && !fUseGrammarPoolOnly) {
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 = fLocationPairs.get(XMLSymbols.EMPTY_STRING);
2357             if (la == null) {
2358                 la = new XMLSchemaLoader.LocationArray();
2359                 fLocationPairs.put(XMLSymbols.EMPTY_STRING, la);
2360             }
2361             la.addLocation(nsLocation);
2362         }
2363 
2364     } //storeLocations
2365 
2366     //this is the function where logic of retrieving grammar is written , parser first tries to get the grammar from
2367     //the local pool, if not in local pool, it gives chance to application to be able to retrieve the grammar, then it
2368     //tries to parse the grammar using location hints from the give namespace.
2369     SchemaGrammar findSchemaGrammar(
2370         short contextType,
2371         String namespace,
2372         QName enclosingElement,
2373         QName triggeringComponet,
2374         XMLAttributes attributes) {
2375         SchemaGrammar grammar = null;
2376         //get the grammar from local pool...
2377         grammar = fGrammarBucket.getGrammar(namespace);
2378 
2379         if (grammar == null) {
2380             fXSDDescription.setNamespace(namespace);
2381             // give a chance to application to be able to retreive the grammar.
2382             if (fGrammarPool != null) {
2383                 grammar = (SchemaGrammar) fGrammarPool.retrieveGrammar(fXSDDescription);
2384                 if (grammar != null) {
2385                     // put this grammar into the bucket, along with grammars
2386                     // imported by it (directly or indirectly)
2387                     if (!fGrammarBucket.putGrammar(grammar, true, fNamespaceGrowth)) {
2388                         // REVISIT: a conflict between new grammar(s) and grammars
2389                         // in the bucket. What to do? A warning? An exception?
2390                         fXSIErrorReporter.fErrorReporter.reportError(
2391                             XSMessageFormatter.SCHEMA_DOMAIN,
2392                             "GrammarConflict",
2393                             null,
2394                             XMLErrorReporter.SEVERITY_WARNING);
2395                         grammar = null;
2396                     }
2397                 }
2398             }
2399         }
2400         if ((grammar == null && !fUseGrammarPoolOnly) || fNamespaceGrowth) {
2401             fXSDDescription.reset();
2402             fXSDDescription.fContextType = contextType;
2403             fXSDDescription.setNamespace(namespace);
2404             fXSDDescription.fEnclosedElementName = enclosingElement;
2405             fXSDDescription.fTriggeringComponent = triggeringComponet;
2406             fXSDDescription.fAttributes = attributes;
2407             if (fLocator != null) {
2408                 fXSDDescription.setBaseSystemId(fLocator.getExpandedSystemId());
2409             }
2410 
2411             Map<String, XMLSchemaLoader.LocationArray> locationPairs = fLocationPairs;
2412             XMLSchemaLoader.LocationArray locationArray =
2413                 locationPairs.get(namespace == null ? XMLSymbols.EMPTY_STRING : namespace);
2414             if (locationArray != null) {
2415                 String[] temp = locationArray.getLocationArray();
2416                 if (temp.length != 0) {
2417                     setLocationHints(fXSDDescription, temp, grammar);
2418                 }
2419             }
2420 
2421             if (grammar == null || fXSDDescription.fLocationHints != null) {
2422                 boolean toParseSchema = true;
2423                 if (grammar != null) {
2424                      // use location hints instead
2425                     locationPairs = Collections.emptyMap();
2426                 }
2427 
2428                 // try to parse the grammar using location hints from that namespace..
2429                 try {
2430                     XMLInputSource xis =
2431                         XMLSchemaLoader.resolveDocument(
2432                             fXSDDescription,
2433                             locationPairs,
2434                             fEntityResolver);
2435                     if (grammar != null && fNamespaceGrowth) {
2436                         try {
2437                             // if we are dealing with a different schema location, then include the new schema
2438                             // into the existing grammar
2439                             if (grammar.getDocumentLocations().contains(XMLEntityManager.expandSystemId(xis.getSystemId(), xis.getBaseSystemId(), false))) {
2440                                 toParseSchema = false;
2441                             }
2442                         }
2443                         catch (MalformedURIException e) {
2444                         }
2445                     }
2446                     if (toParseSchema) {
2447                         grammar = fSchemaLoader.loadSchema(fXSDDescription, xis, fLocationPairs);
2448                     }
2449                 } catch (IOException ex) {
2450                     final String [] locationHints = fXSDDescription.getLocationHints();
2451                     fXSIErrorReporter.fErrorReporter.reportError(
2452                         XSMessageFormatter.SCHEMA_DOMAIN,
2453                         "schema_reference.4",
2454                         new Object[] { locationHints != null ? locationHints[0] : XMLSymbols.EMPTY_STRING },
2455                         XMLErrorReporter.SEVERITY_WARNING);
2456                 }
2457             }
2458         }
2459 
2460         return grammar;
2461 
2462     } //findSchemaGrammar
2463     private void setLocationHints(XSDDescription desc, String[] locations, SchemaGrammar grammar) {
2464         int length = locations.length;
2465         if (grammar == null) {
2466             fXSDDescription.fLocationHints = new String[length];
2467             System.arraycopy(locations, 0, fXSDDescription.fLocationHints, 0, length);
2468         }
2469         else {
2470             setLocationHints(desc, locations, grammar.getDocumentLocations());
2471         }
2472     }
2473 
2474     private void setLocationHints(XSDDescription desc, String[] locations, StringList docLocations) {
2475         int length = locations.length;
2476         String[] hints = new String[length];
2477         int counter = 0;
2478 
2479         for (int i=0; i<length; i++) {
2480             try {
2481                 String id = XMLEntityManager.expandSystemId(locations[i], desc.getBaseSystemId(), false);
2482                 if (!docLocations.contains(id)) {
2483                     hints[counter++] = locations[i];
2484                 }
2485             }
2486             catch (MalformedURIException e) {
2487             }
2488         }
2489 
2490         if (counter > 0) {
2491             if (counter == length) {
2492                 fXSDDescription.fLocationHints = hints;
2493             }
2494             else {
2495                 fXSDDescription.fLocationHints = new String[counter];
2496                 System.arraycopy(hints, 0, fXSDDescription.fLocationHints, 0, counter);
2497             }
2498         }
2499     }
2500 
2501 
2502     XSTypeDefinition getAndCheckXsiType(QName element, String xsiType, XMLAttributes attributes) {
2503         // This method also deals with clause 1.2.1.2 of the constraint
2504         // Validation Rule: Schema-Validity Assessment (Element)
2505 
2506         // Element Locally Valid (Element)
2507         // 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:
2508         // 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);
2509         QName typeName = null;
2510         try {
2511             typeName = (QName) fQNameDV.validate(xsiType, fValidationState, null);
2512         } catch (InvalidDatatypeValueException e) {
2513             reportSchemaError(e.getKey(), e.getArgs());
2514             reportSchemaError(
2515                 "cvc-elt.4.1",
2516                 new Object[] {
2517                     element.rawname,
2518                     SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_TYPE,
2519                     xsiType });
2520             return null;
2521         }
2522 
2523         // 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)
2524         XSTypeDefinition type = null;
2525         // if the namespace is schema namespace, first try built-in types
2526         if (typeName.uri == SchemaSymbols.URI_SCHEMAFORSCHEMA) {
2527             type = SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(typeName.localpart);
2528         }
2529         // if it's not schema built-in types, then try to get a grammar
2530         if (type == null) {
2531             //try to find schema grammar by different means....
2532             SchemaGrammar grammar =
2533                 findSchemaGrammar(
2534                     XSDDescription.CONTEXT_XSITYPE,
2535                     typeName.uri,
2536                     element,
2537                     typeName,
2538                     attributes);
2539 
2540             if (grammar != null)
2541                 type = grammar.getGlobalTypeDecl(typeName.localpart);
2542         }
2543         // still couldn't find the type, report an error
2544         if (type == null) {
2545             reportSchemaError("cvc-elt.4.2", new Object[] { element.rawname, xsiType });
2546             return null;
2547         }
2548 
2549         // if there is no current type, set this one as current.
2550         // and we don't need to do extra checking
2551         if (fCurrentType != null) {
2552             // 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).
2553             short block = fCurrentElemDecl.fBlock;
2554             if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE)
2555                 block |= ((XSComplexTypeDecl) fCurrentType).fBlock;
2556             if (!XSConstraints.checkTypeDerivationOk(type, fCurrentType, block))
2557                 reportSchemaError(
2558                     "cvc-elt.4.3",
2559                     new Object[] { element.rawname, xsiType, fCurrentType.getName()});
2560         }
2561 
2562         return type;
2563     } //getAndCheckXsiType
2564 
2565     boolean getXsiNil(QName element, String xsiNil) {
2566         // Element Locally Valid (Element)
2567         // 3 The appropriate case among the following must be true:
2568         // 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.
2569         if (fCurrentElemDecl != null && !fCurrentElemDecl.getNillable()) {
2570             reportSchemaError(
2571                 "cvc-elt.3.1",
2572                 new Object[] {
2573                     element.rawname,
2574                     SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_NIL });
2575         }
2576         // 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:
2577         // 3.2.2 There must be no fixed {value constraint}.
2578         else {
2579             String value = XMLChar.trim(xsiNil);
2580             if (value.equals(SchemaSymbols.ATTVAL_TRUE)
2581                 || value.equals(SchemaSymbols.ATTVAL_TRUE_1)) {
2582                 if (fCurrentElemDecl != null
2583                     && fCurrentElemDecl.getConstraintType() == XSConstants.VC_FIXED) {
2584                     reportSchemaError(
2585                         "cvc-elt.3.2.2",
2586                         new Object[] {
2587                             element.rawname,
2588                             SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_NIL });
2589                 }
2590                 return true;
2591             }
2592         }
2593         return false;
2594     }
2595 
2596     void processAttributes(QName element, XMLAttributes attributes, XSAttributeGroupDecl attrGrp) {
2597 
2598         if (DEBUG) {
2599             System.out.println("==>processAttributes: " + attributes.getLength());
2600         }
2601 
2602         // whether we have seen a Wildcard ID.
2603         String wildcardIDName = null;
2604 
2605         // for each present attribute
2606         int attCount = attributes.getLength();
2607 
2608         Augmentations augs = null;
2609         AttributePSVImpl attrPSVI = null;
2610 
2611         boolean isSimple =
2612             fCurrentType == null || fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE;
2613 
2614         XSObjectList attrUses = null;
2615         int useCount = 0;
2616         XSWildcardDecl attrWildcard = null;
2617         if (!isSimple) {
2618             attrUses = attrGrp.getAttributeUses();
2619             useCount = attrUses.getLength();
2620             attrWildcard = attrGrp.fAttributeWC;
2621         }
2622 
2623         // Element Locally Valid (Complex Type)
2624         // 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:
2625         // get the corresponding attribute decl
2626         for (int index = 0; index < attCount; index++) {
2627 
2628             attributes.getName(index, fTempQName);
2629 
2630             if (DEBUG) {
2631                 System.out.println("==>process attribute: " + fTempQName);
2632             }
2633 
2634             if (fAugPSVI || fIdConstraint) {
2635                 augs = attributes.getAugmentations(index);
2636                 attrPSVI = (AttributePSVImpl) augs.getItem(Constants.ATTRIBUTE_PSVI);
2637                 if (attrPSVI != null) {
2638                     attrPSVI.reset();
2639                 } else {
2640                     attrPSVI = new AttributePSVImpl();
2641                     augs.putItem(Constants.ATTRIBUTE_PSVI, attrPSVI);
2642                 }
2643                 // PSVI attribute: validation context
2644                 attrPSVI.fValidationContext = fValidationRoot;
2645             }
2646 
2647             // Element Locally Valid (Type)
2648             // 3.1.1 The element information item's [attributes] must be empty, excepting those
2649             // whose [namespace name] is identical to http://www.w3.org/2001/XMLSchema-instance and
2650             // whose [local name] is one of type, nil, schemaLocation or noNamespaceSchemaLocation.
2651 
2652             // for the 4 xsi attributes, get appropriate decl, and validate
2653             if (fTempQName.uri == SchemaSymbols.URI_XSI) {
2654                 XSAttributeDecl attrDecl = null;
2655                 if (fTempQName.localpart == SchemaSymbols.XSI_SCHEMALOCATION)
2656                     attrDecl =
2657                         SchemaGrammar.SG_XSI.getGlobalAttributeDecl(
2658                             SchemaSymbols.XSI_SCHEMALOCATION);
2659                 else if (fTempQName.localpart == SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION)
2660                     attrDecl =
2661                         SchemaGrammar.SG_XSI.getGlobalAttributeDecl(
2662                             SchemaSymbols.XSI_NONAMESPACESCHEMALOCATION);
2663                 else if (fTempQName.localpart == SchemaSymbols.XSI_NIL)
2664                     attrDecl = SchemaGrammar.SG_XSI.getGlobalAttributeDecl(SchemaSymbols.XSI_NIL);
2665                 else if (fTempQName.localpart == SchemaSymbols.XSI_TYPE)
2666                     attrDecl = SchemaGrammar.SG_XSI.getGlobalAttributeDecl(SchemaSymbols.XSI_TYPE);
2667                 if (attrDecl != null) {
2668                     processOneAttribute(element, attributes, index, attrDecl, null, attrPSVI);
2669                     continue;
2670                 }
2671             }
2672 
2673             // for namespace attributes, no_validation/unknow_validity
2674             if (fTempQName.rawname == XMLSymbols.PREFIX_XMLNS
2675                 || fTempQName.rawname.startsWith("xmlns:")) {
2676                 continue;
2677             }
2678 
2679             // simple type doesn't allow any other attributes
2680             if (isSimple) {
2681                 reportSchemaError(
2682                     "cvc-type.3.1.1",
2683                     new Object[] { element.rawname, fTempQName.rawname });
2684                 continue;
2685             }
2686 
2687             // it's not xmlns, and not xsi, then we need to find a decl for it
2688             XSAttributeUseImpl currUse = null, oneUse;
2689             for (int i = 0; i < useCount; i++) {
2690                 oneUse = (XSAttributeUseImpl) attrUses.item(i);
2691                 if (oneUse.fAttrDecl.fName == fTempQName.localpart
2692                     && oneUse.fAttrDecl.fTargetNamespace == fTempQName.uri) {
2693                     currUse = oneUse;
2694                     break;
2695                 }
2696             }
2697 
2698             // 3.2 otherwise all of the following must be true:
2699             // 3.2.1 There must be an {attribute wildcard}.
2700             // 3.2.2 The attribute information item must be valid with respect to it as defined in Item Valid (Wildcard) (3.10.4).
2701 
2702             // if failed, get it from wildcard
2703             if (currUse == null) {
2704                 //if (attrWildcard == null)
2705                 //    reportSchemaError("cvc-complex-type.3.2.1", new Object[]{element.rawname, fTempQName.rawname});
2706                 if (attrWildcard == null || !attrWildcard.allowNamespace(fTempQName.uri)) {
2707                     // so this attribute is not allowed
2708                     reportSchemaError(
2709                         "cvc-complex-type.3.2.2",
2710                         new Object[] { element.rawname, fTempQName.rawname });
2711                     continue;
2712                 }
2713             }
2714 
2715             XSAttributeDecl currDecl = null;
2716             if (currUse != null) {
2717                 currDecl = currUse.fAttrDecl;
2718             } else {
2719                 // which means it matches a wildcard
2720                 // skip it if processContents is skip
2721                 if (attrWildcard.fProcessContents == XSWildcardDecl.PC_SKIP)
2722                     continue;
2723 
2724                 //try to find grammar by different means...
2725                 SchemaGrammar grammar =
2726                     findSchemaGrammar(
2727                         XSDDescription.CONTEXT_ATTRIBUTE,
2728                         fTempQName.uri,
2729                         element,
2730                         fTempQName,
2731                         attributes);
2732 
2733                 if (grammar != null) {
2734                     currDecl = grammar.getGlobalAttributeDecl(fTempQName.localpart);
2735                 }
2736 
2737                 // if can't find
2738                 if (currDecl == null) {
2739                     // if strict, report error
2740                     if (attrWildcard.fProcessContents == XSWildcardDecl.PC_STRICT) {
2741                         reportSchemaError(
2742                             "cvc-complex-type.3.2.2",
2743                             new Object[] { element.rawname, fTempQName.rawname });
2744                     }
2745 
2746                     // then continue to the next attribute
2747                     continue;
2748                 } else {
2749                     // 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:
2750                     // 5.1 There must be no more than one item in wild IDs.
2751                     if (currDecl.fType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE
2752                         && ((XSSimpleType) currDecl.fType).isIDType()) {
2753                         if (wildcardIDName != null) {
2754                             reportSchemaError(
2755                                 "cvc-complex-type.5.1",
2756                                 new Object[] { element.rawname, currDecl.fName, wildcardIDName });
2757                         } else
2758                             wildcardIDName = currDecl.fName;
2759                     }
2760                 }
2761             }
2762 
2763             processOneAttribute(element, attributes, index, currDecl, currUse, attrPSVI);
2764         } // end of for (all attributes)
2765 
2766         // 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.
2767         if (!isSimple && attrGrp.fIDAttrName != null && wildcardIDName != null) {
2768             reportSchemaError(
2769                 "cvc-complex-type.5.2",
2770                 new Object[] { element.rawname, wildcardIDName, attrGrp.fIDAttrName });
2771         }
2772 
2773     } //processAttributes
2774 
2775     void processOneAttribute(
2776         QName element,
2777         XMLAttributes attributes,
2778         int index,
2779         XSAttributeDecl currDecl,
2780         XSAttributeUseImpl currUse,
2781         AttributePSVImpl attrPSVI) {
2782 
2783         String attrValue = attributes.getValue(index);
2784         fXSIErrorReporter.pushContext();
2785 
2786         // Attribute Locally Valid
2787         // For an attribute information item to be locally valid with respect to an attribute declaration all of the following must be true:
2788         // 1 The declaration must not be absent (see Missing Sub-components (5.3) for how this can fail to be the case).
2789         // 2 Its {type definition} must not be absent.
2790         // 3 The item's normalized value must be locally valid with respect to that {type definition} as per String Valid (3.14.4).
2791         // get simple type
2792         XSSimpleType attDV = currDecl.fType;
2793 
2794         Object actualValue = null;
2795         try {
2796             actualValue = attDV.validate(attrValue, fValidationState, fValidatedInfo);
2797             // store the normalized value
2798             if (fNormalizeData)
2799                 attributes.setValue(index, fValidatedInfo.normalizedValue);
2800             if (attributes instanceof XMLAttributesImpl) {
2801                 XMLAttributesImpl attrs = (XMLAttributesImpl) attributes;
2802                 boolean schemaId =
2803                     fValidatedInfo.memberType != null
2804                         ? fValidatedInfo.memberType.isIDType()
2805                         : attDV.isIDType();
2806                 attrs.setSchemaId(index, schemaId);
2807             }
2808 
2809             // PSVI: element notation
2810             if (attDV.getVariety() == XSSimpleType.VARIETY_ATOMIC
2811                 && attDV.getPrimitiveKind() == XSSimpleType.PRIMITIVE_NOTATION) {
2812                 QName qName = (QName) actualValue;
2813                 SchemaGrammar grammar = fGrammarBucket.getGrammar(qName.uri);
2814 
2815                 //REVISIT: is it possible for the notation to be in different namespace than the attribute
2816                 //with which it is associated, CHECK !!  <fof n1:att1 = "n2:notation1" ..>
2817                 // should we give chance to the application to be able to  retrieve a grammar - nb
2818                 //REVISIT: what would be the triggering component here.. if it is attribute value that
2819                 // triggered the loading of grammar ?? -nb
2820 
2821                 if (grammar != null) {
2822                     fNotation = grammar.getGlobalNotationDecl(qName.localpart);
2823                 }
2824             }
2825         } catch (InvalidDatatypeValueException idve) {
2826             reportSchemaError(idve.getKey(), idve.getArgs());
2827             reportSchemaError(
2828                 "cvc-attribute.3",
2829                 new Object[] { element.rawname, fTempQName.rawname, attrValue, attDV.getName()});
2830         }
2831 
2832         // get the value constraint from use or decl
2833         // 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
2834         if (actualValue != null && currDecl.getConstraintType() == XSConstants.VC_FIXED) {
2835             if (!isComparable(fValidatedInfo, currDecl.fDefault) || !actualValue.equals(currDecl.fDefault.actualValue)) {
2836                 reportSchemaError(
2837                     "cvc-attribute.4",
2838                     new Object[] {
2839                         element.rawname,
2840                         fTempQName.rawname,
2841                         attrValue,
2842                         currDecl.fDefault.stringValue()});
2843             }
2844         }
2845 
2846         // 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).
2847         if (actualValue != null
2848             && currUse != null
2849             && currUse.fConstraintType == XSConstants.VC_FIXED) {
2850             if (!isComparable(fValidatedInfo, currUse.fDefault) || !actualValue.equals(currUse.fDefault.actualValue)) {
2851                 reportSchemaError(
2852                     "cvc-complex-type.3.1",
2853                     new Object[] {
2854                         element.rawname,
2855                         fTempQName.rawname,
2856                         attrValue,
2857                         currUse.fDefault.stringValue()});
2858             }
2859         }
2860         if (fIdConstraint) {
2861             attrPSVI.fActualValue = actualValue;
2862         }
2863 
2864         if (fAugPSVI) {
2865             // PSVI: attribute declaration
2866             attrPSVI.fDeclaration = currDecl;
2867             // PSVI: attribute type
2868             attrPSVI.fTypeDecl = attDV;
2869 
2870             // PSVI: attribute memberType
2871             attrPSVI.fMemberType = fValidatedInfo.memberType;
2872             // PSVI: attribute normalized value
2873             // NOTE: we always store the normalized value, even if it's invlid,
2874             // because it might still be useful to the user. But when the it's
2875             // not valid, the normalized value is not trustable.
2876             attrPSVI.fNormalizedValue = fValidatedInfo.normalizedValue;
2877             attrPSVI.fActualValue = fValidatedInfo.actualValue;
2878             attrPSVI.fActualValueType = fValidatedInfo.actualValueType;
2879             attrPSVI.fItemValueTypes = fValidatedInfo.itemValueTypes;
2880 
2881 
2882 
2883             // PSVI: validation attempted:
2884             attrPSVI.fValidationAttempted = AttributePSVI.VALIDATION_FULL;
2885 
2886             String[] errors = fXSIErrorReporter.mergeContext();
2887             // PSVI: error codes
2888             attrPSVI.fErrorCodes = errors;
2889             // PSVI: validity
2890             attrPSVI.fValidity =
2891                 (errors == null) ? AttributePSVI.VALIDITY_VALID : AttributePSVI.VALIDITY_INVALID;
2892         }
2893     }
2894 
2895     void addDefaultAttributes(
2896         QName element,
2897         XMLAttributes attributes,
2898         XSAttributeGroupDecl attrGrp) {
2899         // Check after all specified attrs are scanned
2900         // (1) report error for REQUIRED attrs that are missing (V_TAGc)
2901         // REVISIT: should we check prohibited attributes?
2902         // (2) report error for PROHIBITED attrs that are present (V_TAGc)
2903         // (3) add default attrs (FIXED and NOT_FIXED)
2904         //
2905         if (DEBUG) {
2906             System.out.println("==>addDefaultAttributes: " + element);
2907         }
2908         XSObjectList attrUses = attrGrp.getAttributeUses();
2909         int useCount = attrUses.getLength();
2910         XSAttributeUseImpl currUse;
2911         XSAttributeDecl currDecl;
2912         short constType;
2913         ValidatedInfo defaultValue;
2914         boolean isSpecified;
2915         QName attName;
2916         // for each attribute use
2917         for (int i = 0; i < useCount; i++) {
2918 
2919             currUse = (XSAttributeUseImpl) attrUses.item(i);
2920             currDecl = currUse.fAttrDecl;
2921             // get value constraint
2922             constType = currUse.fConstraintType;
2923             defaultValue = currUse.fDefault;
2924             if (constType == XSConstants.VC_NONE) {
2925                 constType = currDecl.getConstraintType();
2926                 defaultValue = currDecl.fDefault;
2927             }
2928             // whether this attribute is specified
2929             isSpecified = attributes.getValue(currDecl.fTargetNamespace, currDecl.fName) != null;
2930 
2931             // Element Locally Valid (Complex Type)
2932             // 4 The {attribute declaration} of each attribute use in the {attribute uses} whose
2933             // {required} is true matches one of the attribute information items in the element
2934             // information item's [attributes] as per clause 3.1 above.
2935             if (currUse.fUse == SchemaSymbols.USE_REQUIRED) {
2936                 if (!isSpecified)
2937                     reportSchemaError(
2938                         "cvc-complex-type.4",
2939                         new Object[] { element.rawname, currDecl.fName });
2940             }
2941             // if the attribute is not specified, then apply the value constraint
2942             if (!isSpecified && constType != XSConstants.VC_NONE) {
2943                 attName =
2944                     new QName(null, currDecl.fName, currDecl.fName, currDecl.fTargetNamespace);
2945                 String normalized = (defaultValue != null) ? defaultValue.stringValue() : "";
2946                 int attrIndex = attributes.addAttribute(attName, "CDATA", normalized);
2947                 if (attributes instanceof XMLAttributesImpl) {
2948                     XMLAttributesImpl attrs = (XMLAttributesImpl) attributes;
2949                     boolean schemaId =
2950                         defaultValue != null
2951                             && defaultValue.memberType != null
2952                                 ? defaultValue.memberType.isIDType()
2953                                 : currDecl.fType.isIDType();
2954                     attrs.setSchemaId(attrIndex, schemaId);
2955                 }
2956 
2957                 if (fAugPSVI) {
2958 
2959                     // PSVI: attribute is "schema" specified
2960                     Augmentations augs = attributes.getAugmentations(attrIndex);
2961                     AttributePSVImpl attrPSVI = new AttributePSVImpl();
2962                     augs.putItem(Constants.ATTRIBUTE_PSVI, attrPSVI);
2963 
2964                     attrPSVI.fDeclaration = currDecl;
2965                     attrPSVI.fTypeDecl = currDecl.fType;
2966                     attrPSVI.fMemberType = defaultValue.memberType;
2967                     attrPSVI.fNormalizedValue = normalized;
2968                     attrPSVI.fActualValue = defaultValue.actualValue;
2969                     attrPSVI.fActualValueType = defaultValue.actualValueType;
2970                     attrPSVI.fItemValueTypes = defaultValue.itemValueTypes;
2971                     attrPSVI.fValidationContext = fValidationRoot;
2972                     attrPSVI.fValidity = AttributePSVI.VALIDITY_VALID;
2973                     attrPSVI.fValidationAttempted = AttributePSVI.VALIDATION_FULL;
2974                     attrPSVI.fSpecified = true;
2975                 }
2976             }
2977 
2978         } // for
2979     } // addDefaultAttributes
2980 
2981     /**
2982      *  If there is not text content, and there is a
2983      *  {value constraint} on the corresponding element decl, then return
2984      *  an XMLString representing the default value.
2985      */
2986     void processElementContent(QName element) {
2987         // 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.
2988         if (fCurrentElemDecl != null
2989             && fCurrentElemDecl.fDefault != null
2990             && !fSawText
2991             && !fSubElement
2992             && !fNil) {
2993 
2994             String strv = fCurrentElemDecl.fDefault.stringValue();
2995             int bufLen = strv.length();
2996             if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < bufLen) {
2997                 fNormalizedStr.ch = new char[bufLen];
2998             }
2999             strv.getChars(0, bufLen, fNormalizedStr.ch, 0);
3000             fNormalizedStr.offset = 0;
3001             fNormalizedStr.length = bufLen;
3002             fDefaultValue = fNormalizedStr;
3003         }
3004         // fixed values are handled later, after xsi:type determined.
3005 
3006         fValidatedInfo.normalizedValue = null;
3007 
3008         // Element Locally Valid (Element)
3009         // 3.2.1 The element information item must have no character or element information item [children].
3010         if (fNil) {
3011             if (fSubElement || fSawText) {
3012                 reportSchemaError(
3013                     "cvc-elt.3.2.1",
3014                     new Object[] {
3015                         element.rawname,
3016                         SchemaSymbols.URI_XSI + "," + SchemaSymbols.XSI_NIL });
3017             }
3018         }
3019 
3020         this.fValidatedInfo.reset();
3021 
3022         // 5 The appropriate case among the following must be true:
3023         // 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:
3024         if (fCurrentElemDecl != null
3025             && fCurrentElemDecl.getConstraintType() != XSConstants.VC_NONE
3026             && !fSubElement
3027             && !fSawText
3028             && !fNil) {
3029             // 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).
3030             if (fCurrentType != fCurrentElemDecl.fType) {
3031                 //REVISIT:we should pass ValidatedInfo here.
3032                 if (XSConstraints
3033                     .ElementDefaultValidImmediate(
3034                         fCurrentType,
3035                         fCurrentElemDecl.fDefault.stringValue(),
3036                         fState4XsiType,
3037                         null)
3038                     == null)
3039                     reportSchemaError(
3040                         "cvc-elt.5.1.1",
3041                         new Object[] {
3042                             element.rawname,
3043                             fCurrentType.getName(),
3044                             fCurrentElemDecl.fDefault.stringValue()});
3045             }
3046             // 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).
3047             // REVISIT: don't use toString, but validateActualValue instead
3048             //          use the fState4ApplyDefault
3049             elementLocallyValidType(element, fCurrentElemDecl.fDefault.stringValue());
3050         } else {
3051             // The following method call also deal with clause 1.2.2 of the constraint
3052             // Validation Rule: Schema-Validity Assessment (Element)
3053 
3054             // 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:
3055             // 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).
3056             Object actualValue = elementLocallyValidType(element, fBuffer);
3057             // 5.2.2 If there is a fixed {value constraint} and clause 3.2 has not applied, all of the following must be true:
3058             if (fCurrentElemDecl != null
3059                 && fCurrentElemDecl.getConstraintType() == XSConstants.VC_FIXED
3060                 && !fNil) {
3061                 String content = fBuffer.toString();
3062                 // 5.2.2.1 The element information item must have no element information item [children].
3063                 if (fSubElement)
3064                     reportSchemaError("cvc-elt.5.2.2.1", new Object[] { element.rawname });
3065                 // 5.2.2.2 The appropriate case among the following must be true:
3066                 if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
3067                     XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
3068                     // 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.
3069                     if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
3070                         // REVISIT: how to get the initial value, does whiteSpace count?
3071                         if (!fCurrentElemDecl.fDefault.normalizedValue.equals(content))
3072                             reportSchemaError(
3073                                 "cvc-elt.5.2.2.2.1",
3074                                 new Object[] {
3075                                     element.rawname,
3076                                     content,
3077                                     fCurrentElemDecl.fDefault.normalizedValue });
3078                     }
3079                     // 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.
3080                     else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
3081                         if (actualValue != null && (!isComparable(fValidatedInfo, fCurrentElemDecl.fDefault)
3082                                 || !actualValue.equals(fCurrentElemDecl.fDefault.actualValue))) {
3083                             reportSchemaError(
3084                                 "cvc-elt.5.2.2.2.2",
3085                                 new Object[] {
3086                                     element.rawname,
3087                                     content,
3088                                     fCurrentElemDecl.fDefault.stringValue()});
3089                         }
3090                     }
3091                 } else if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
3092                     if (actualValue != null && (!isComparable(fValidatedInfo, fCurrentElemDecl.fDefault)
3093                             || !actualValue.equals(fCurrentElemDecl.fDefault.actualValue))) {
3094                         // REVISIT: the spec didn't mention this case: fixed
3095                         //          value with simple type
3096                         reportSchemaError(
3097                             "cvc-elt.5.2.2.2.2",
3098                             new Object[] {
3099                                 element.rawname,
3100                                 content,
3101                                 fCurrentElemDecl.fDefault.stringValue()});
3102                     }
3103                 }
3104             }
3105         }
3106 
3107         if (fDefaultValue == null && fNormalizeData && fDocumentHandler != null && fUnionType) {
3108             // for union types we need to send data because we delayed sending
3109             // this data when we received it in the characters() call.
3110             String content = fValidatedInfo.normalizedValue;
3111             if (content == null)
3112                 content = fBuffer.toString();
3113 
3114             int bufLen = content.length();
3115             if (fNormalizedStr.ch == null || fNormalizedStr.ch.length < bufLen) {
3116                 fNormalizedStr.ch = new char[bufLen];
3117             }
3118             content.getChars(0, bufLen, fNormalizedStr.ch, 0);
3119             fNormalizedStr.offset = 0;
3120             fNormalizedStr.length = bufLen;
3121             fDocumentHandler.characters(fNormalizedStr, null);
3122         }
3123     } // processElementContent
3124 
3125     Object elementLocallyValidType(QName element, Object textContent) {
3126         if (fCurrentType == null)
3127             return null;
3128 
3129         Object retValue = null;
3130         // Element Locally Valid (Type)
3131         // 3 The appropriate case among the following must be true:
3132         // 3.1 If the type definition is a simple type definition, then all of the following must be true:
3133         if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
3134             // 3.1.2 The element information item must have no element information item [children].
3135             if (fSubElement)
3136                 reportSchemaError("cvc-type.3.1.2", new Object[] { element.rawname });
3137             // 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).
3138             if (!fNil) {
3139                 XSSimpleType dv = (XSSimpleType) fCurrentType;
3140                 try {
3141                     if (!fNormalizeData || fUnionType) {
3142                         fValidationState.setNormalizationRequired(true);
3143                     }
3144                     retValue = dv.validate(textContent, fValidationState, fValidatedInfo);
3145                 } catch (InvalidDatatypeValueException e) {
3146                     reportSchemaError(e.getKey(), e.getArgs());
3147                     reportSchemaError(
3148                         "cvc-type.3.1.3",
3149                         new Object[] { element.rawname, textContent });
3150                 }
3151             }
3152         } else {
3153             // 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);
3154             retValue = elementLocallyValidComplexType(element, textContent);
3155         }
3156 
3157         return retValue;
3158     } // elementLocallyValidType
3159 
3160     Object elementLocallyValidComplexType(QName element, Object textContent) {
3161         Object actualValue = null;
3162         XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType;
3163 
3164         // Element Locally Valid (Complex Type)
3165         // For an element information item to be locally valid with respect to a complex type definition all of the following must be true:
3166         // 1 {abstract} is false.
3167         // 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:
3168         if (!fNil) {
3169             // 2.1 If the {content type} is empty, then the element information item has no character or element information item [children].
3170             if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_EMPTY
3171                 && (fSubElement || fSawText)) {
3172                 reportSchemaError("cvc-complex-type.2.1", new Object[] { element.rawname });
3173             }
3174             // 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).
3175             else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
3176                 if (fSubElement)
3177                     reportSchemaError("cvc-complex-type.2.2", new Object[] { element.rawname });
3178                 XSSimpleType dv = ctype.fXSSimpleType;
3179                 try {
3180                     if (!fNormalizeData || fUnionType) {
3181                         fValidationState.setNormalizationRequired(true);
3182                     }
3183                     actualValue = dv.validate(textContent, fValidationState, fValidatedInfo);
3184                 } catch (InvalidDatatypeValueException e) {
3185                     reportSchemaError(e.getKey(), e.getArgs());
3186                     reportSchemaError("cvc-complex-type.2.2", new Object[] { element.rawname });
3187                 }
3188                 // REVISIT: eventually, this method should return the same actualValue as elementLocallyValidType...
3189                 // obviously it'll return null when the content is complex.
3190             }
3191             // 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)].
3192             else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT) {
3193                 if (fSawCharacters) {
3194                     reportSchemaError("cvc-complex-type.2.3", new Object[] { element.rawname });
3195                 }
3196             }
3197             // 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).
3198             if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_ELEMENT
3199                 || ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
3200                 // if the current state is a valid state, check whether
3201                 // it's one of the final states.
3202                 if (DEBUG) {
3203                     System.out.println(fCurrCMState);
3204                 }
3205                 if (fCurrCMState[0] >= 0 && !fCurrentCM.endContentModel(fCurrCMState)) {
3206                     String expected = expectedStr(fCurrentCM.whatCanGoHere(fCurrCMState));
3207                     reportSchemaError(
3208                         "cvc-complex-type.2.4.b",
3209                         new Object[] { element.rawname, expected });
3210                 } else {
3211                     // Constant space algorithm for a{n,m} for n > 1 and m <= unbounded
3212                     // After the DFA has completed, check minOccurs and maxOccurs
3213                     // for all elements and wildcards in this content model where
3214                     // a{n,m} is subsumed to a* or a+
3215                     ArrayList errors = fCurrentCM.checkMinMaxBounds();
3216                     if (errors != null) {
3217                         for (int i = 0; i < errors.size(); i += 2) {
3218                             reportSchemaError(
3219                                 (String) errors.get(i),
3220                                 new Object[] { element.rawname, errors.get(i + 1) });
3221                         }
3222                     }
3223                 }
3224              }
3225         }
3226         return actualValue;
3227     } // elementLocallyValidComplexType
3228 
3229     void reportSchemaError(String key, Object[] arguments) {
3230         if (fDoValidation)
3231             fXSIErrorReporter.reportError(
3232                 XSMessageFormatter.SCHEMA_DOMAIN,
3233                 key,
3234                 arguments,
3235                 XMLErrorReporter.SEVERITY_ERROR);
3236     }
3237 
3238     /** Returns true if the two ValidatedInfo objects can be compared in the same value space. **/
3239     private boolean isComparable(ValidatedInfo info1, ValidatedInfo info2) {
3240         final short primitiveType1 = convertToPrimitiveKind(info1.actualValueType);
3241         final short primitiveType2 = convertToPrimitiveKind(info2.actualValueType);
3242         if (primitiveType1 != primitiveType2) {
3243             return (primitiveType1 == XSConstants.ANYSIMPLETYPE_DT && primitiveType2 == XSConstants.STRING_DT ||
3244                     primitiveType1 == XSConstants.STRING_DT && primitiveType2 == XSConstants.ANYSIMPLETYPE_DT);
3245         }
3246         else if (primitiveType1 == XSConstants.LIST_DT || primitiveType1 == XSConstants.LISTOFUNION_DT) {
3247             final ShortList typeList1 = info1.itemValueTypes;
3248             final ShortList typeList2 = info2.itemValueTypes;
3249             final int typeList1Length = typeList1 != null ? typeList1.getLength() : 0;
3250             final int typeList2Length = typeList2 != null ? typeList2.getLength() : 0;
3251             if (typeList1Length != typeList2Length) {
3252                 return false;
3253             }
3254             for (int i = 0; i < typeList1Length; ++i) {
3255                 final short primitiveItem1 = convertToPrimitiveKind(typeList1.item(i));
3256                 final short primitiveItem2 = convertToPrimitiveKind(typeList2.item(i));
3257                 if (primitiveItem1 != primitiveItem2) {
3258                     if (primitiveItem1 == XSConstants.ANYSIMPLETYPE_DT && primitiveItem2 == XSConstants.STRING_DT ||
3259                         primitiveItem1 == XSConstants.STRING_DT && primitiveItem2 == XSConstants.ANYSIMPLETYPE_DT) {
3260                         continue;
3261                     }
3262                     return false;
3263                 }
3264             }
3265         }
3266         return true;
3267     }
3268 
3269     private short convertToPrimitiveKind(short valueType) {
3270         /** Primitive datatypes. */
3271         if (valueType <= XSConstants.NOTATION_DT) {
3272             return valueType;
3273         }
3274         /** Types derived from string. */
3275         if (valueType <= XSConstants.ENTITY_DT) {
3276             return XSConstants.STRING_DT;
3277         }
3278         /** Types derived from decimal. */
3279         if (valueType <= XSConstants.POSITIVEINTEGER_DT) {
3280             return XSConstants.DECIMAL_DT;
3281         }
3282         /** Other types. */
3283         return valueType;
3284     }
3285 
3286     private String expectedStr(Vector expected) {
3287         StringBuffer ret = new StringBuffer("{");
3288         int size = expected.size();
3289         for (int i = 0; i < size; i++) {
3290             if (i > 0)
3291                 ret.append(", ");
3292             ret.append(expected.elementAt(i).toString());
3293         }
3294         ret.append('}');
3295         return ret.toString();
3296     }
3297 
3298     /**********************************/
3299 
3300     // xpath matcher information
3301 
3302     /**
3303      * Stack of XPath matchers for identity constraints.
3304      *
3305      * @author Andy Clark, IBM
3306      */
3307     protected static class XPathMatcherStack {
3308 
3309         //
3310         // Data
3311         //
3312 
3313         /** Active matchers. */
3314         protected XPathMatcher[] fMatchers = new XPathMatcher[4];
3315 
3316         /** Count of active matchers. */
3317         protected int fMatchersCount;
3318 
3319         /** Offset stack for contexts. */
3320         protected IntStack fContextStack = new IntStack();
3321 
3322         //
3323         // Constructors
3324         //
3325 
3326         public XPathMatcherStack() {
3327         } // <init>()
3328 
3329         //
3330         // Public methods
3331         //
3332 
3333         /** Resets the XPath matcher stack. */
3334         public void clear() {
3335             for (int i = 0; i < fMatchersCount; i++) {
3336                 fMatchers[i] = null;
3337             }
3338             fMatchersCount = 0;
3339             fContextStack.clear();
3340         } // clear()
3341 
3342         /** Returns the size of the stack. */
3343         public int size() {
3344             return fContextStack.size();
3345         } // size():int
3346 
3347         /** Returns the count of XPath matchers. */
3348         public int getMatcherCount() {
3349             return fMatchersCount;
3350         } // getMatcherCount():int
3351 
3352         /** Adds a matcher. */
3353         public void addMatcher(XPathMatcher matcher) {
3354             ensureMatcherCapacity();
3355             fMatchers[fMatchersCount++] = matcher;
3356         } // addMatcher(XPathMatcher)
3357 
3358         /** Returns the XPath matcher at the specified index. */
3359         public XPathMatcher getMatcherAt(int index) {
3360             return fMatchers[index];
3361         } // getMatcherAt(index):XPathMatcher
3362 
3363         /** Pushes a new context onto the stack. */
3364         public void pushContext() {
3365             fContextStack.push(fMatchersCount);
3366         } // pushContext()
3367 
3368         /** Pops a context off of the stack. */
3369         public void popContext() {
3370             fMatchersCount = fContextStack.pop();
3371         } // popContext()
3372 
3373         //
3374         // Private methods
3375         //
3376 
3377         /** Ensures the size of the matchers array. */
3378         private void ensureMatcherCapacity() {
3379             if (fMatchersCount == fMatchers.length) {
3380                 XPathMatcher[] array = new XPathMatcher[fMatchers.length * 2];
3381                 System.arraycopy(fMatchers, 0, array, 0, fMatchers.length);
3382                 fMatchers = array;
3383             }
3384         } // ensureMatcherCapacity()
3385 
3386     } // class XPathMatcherStack
3387 
3388     // value store implementations
3389 
3390     /**
3391      * Value store implementation base class. There are specific subclasses
3392      * for handling unique, key, and keyref.
3393      *
3394      * @author Andy Clark, IBM
3395      */
3396     protected abstract class ValueStoreBase implements ValueStore {
3397 
3398         //
3399         // Data
3400         //
3401 
3402         /** Identity constraint. */
3403         protected IdentityConstraint fIdentityConstraint;
3404         protected int fFieldCount = 0;
3405         protected Field[] fFields = null;
3406         /** current data */
3407         protected Object[] fLocalValues = null;
3408         protected short[] fLocalValueTypes = null;
3409         protected ShortList[] fLocalItemValueTypes = null;
3410 
3411         /** Current data value count. */
3412         protected int fValuesCount;
3413 
3414         /** global data */
3415         public final Vector fValues = new Vector();
3416         public ShortVector fValueTypes = null;
3417         public Vector fItemValueTypes = null;
3418 
3419         private boolean fUseValueTypeVector = false;
3420         private int fValueTypesLength = 0;
3421         private short fValueType = 0;
3422 
3423         private boolean fUseItemValueTypeVector = false;
3424         private int fItemValueTypesLength = 0;
3425         private ShortList fItemValueType = null;
3426 
3427         /** buffer for error messages */
3428         final StringBuffer fTempBuffer = new StringBuffer();
3429 
3430         //
3431         // Constructors
3432         //
3433 
3434         /** Constructs a value store for the specified identity constraint. */
3435         protected ValueStoreBase(IdentityConstraint identityConstraint) {
3436             fIdentityConstraint = identityConstraint;
3437             fFieldCount = fIdentityConstraint.getFieldCount();
3438             fFields = new Field[fFieldCount];
3439             fLocalValues = new Object[fFieldCount];
3440             fLocalValueTypes = new short[fFieldCount];
3441             fLocalItemValueTypes = new ShortList[fFieldCount];
3442             for (int i = 0; i < fFieldCount; i++) {
3443                 fFields[i] = fIdentityConstraint.getFieldAt(i);
3444             }
3445         } // <init>(IdentityConstraint)
3446 
3447         //
3448         // Public methods
3449         //
3450 
3451         // destroys this ValueStore; useful when, for instance, a
3452         // locally-scoped ID constraint is involved.
3453         public void clear() {
3454             fValuesCount = 0;
3455             fUseValueTypeVector = false;
3456             fValueTypesLength = 0;
3457             fValueType = 0;
3458             fUseItemValueTypeVector = false;
3459             fItemValueTypesLength = 0;
3460             fItemValueType = null;
3461             fValues.setSize(0);
3462             if (fValueTypes != null) {
3463                 fValueTypes.clear();
3464             }
3465             if (fItemValueTypes != null) {
3466                 fItemValueTypes.setSize(0);
3467             }
3468         } // end clear():void
3469 
3470         // appends the contents of one ValueStore to those of us.
3471         public void append(ValueStoreBase newVal) {
3472             for (int i = 0; i < newVal.fValues.size(); i++) {
3473                 fValues.addElement(newVal.fValues.elementAt(i));
3474             }
3475         } // append(ValueStoreBase)
3476 
3477         /** Start scope for value store. */
3478         public void startValueScope() {
3479             fValuesCount = 0;
3480             for (int i = 0; i < fFieldCount; i++) {
3481                 fLocalValues[i] = null;
3482                 fLocalValueTypes[i] = 0;
3483                 fLocalItemValueTypes[i] = null;
3484             }
3485         } // startValueScope()
3486 
3487         /** Ends scope for value store. */
3488         public void endValueScope() {
3489 
3490             if (fValuesCount == 0) {
3491                 if (fIdentityConstraint.getCategory() == IdentityConstraint.IC_KEY) {
3492                     String code = "AbsentKeyValue";
3493                     String eName = fIdentityConstraint.getElementName();
3494                     String cName = fIdentityConstraint.getIdentityConstraintName();
3495                     reportSchemaError(code, new Object[] { eName, cName });
3496                 }
3497                 return;
3498             }
3499 
3500             // Validation Rule: Identity-constraint Satisfied
3501             // 4.2 If the {identity-constraint category} is key, then all of the following must be true:
3502             // 4.2.1 The target node set and the qualified node set are equal, that is, every member of the
3503             // target node set is also a member of the qualified node set and vice versa.
3504             //
3505             // If the IDC is a key check whether we have all the fields.
3506             if (fValuesCount != fFieldCount) {
3507                 if (fIdentityConstraint.getCategory() == IdentityConstraint.IC_KEY) {
3508                     String code = "KeyNotEnoughValues";
3509                     UniqueOrKey key = (UniqueOrKey) fIdentityConstraint;
3510                     String eName = fIdentityConstraint.getElementName();
3511                     String cName = key.getIdentityConstraintName();
3512                     reportSchemaError(code, new Object[] { eName, cName });
3513                 }
3514                 return;
3515             }
3516 
3517         } // endValueScope()
3518 
3519         // This is needed to allow keyref's to look for matched keys
3520         // in the correct scope.  Unique and Key may also need to
3521         // override this method for purposes of their own.
3522         // This method is called whenever the DocumentFragment
3523         // of an ID Constraint goes out of scope.
3524         public void endDocumentFragment() {
3525         } // endDocumentFragment():void
3526 
3527         /**
3528          * Signals the end of the document. This is where the specific
3529          * instances of value stores can verify the integrity of the
3530          * identity constraints.
3531          */
3532         public void endDocument() {
3533         } // endDocument()
3534 
3535         //
3536         // ValueStore methods
3537         //
3538 
3539         /* reports an error if an element is matched
3540          * has nillable true and is matched by a key.
3541          */
3542 
3543         public void reportError(String key, Object[] args) {
3544             reportSchemaError(key, args);
3545         } // reportError(String,Object[])
3546 
3547         /**
3548          * Adds the specified value to the value store.
3549          *
3550          * @param field The field associated to the value. This reference
3551          *              is used to ensure that each field only adds a value
3552          *              once within a selection scope.
3553          * @param actualValue The value to add.
3554          */
3555         public void addValue(Field field, Object actualValue, short valueType, ShortList itemValueType) {
3556             int i;
3557             for (i = fFieldCount - 1; i > -1; i--) {
3558                 if (fFields[i] == field) {
3559                     break;
3560                 }
3561             }
3562             // do we even know this field?
3563             if (i == -1) {
3564                 String code = "UnknownField";
3565                 String eName = fIdentityConstraint.getElementName();
3566                 String cName = fIdentityConstraint.getIdentityConstraintName();
3567                 reportSchemaError(code, new Object[] { field.toString(), eName, cName });
3568                 return;
3569             }
3570             if (Boolean.TRUE != mayMatch(field)) {
3571                 String code = "FieldMultipleMatch";
3572                 String cName = fIdentityConstraint.getIdentityConstraintName();
3573                 reportSchemaError(code, new Object[] { field.toString(), cName });
3574             } else {
3575                 fValuesCount++;
3576             }
3577             fLocalValues[i] = actualValue;
3578             fLocalValueTypes[i] = valueType;
3579             fLocalItemValueTypes[i] = itemValueType;
3580             if (fValuesCount == fFieldCount) {
3581                 checkDuplicateValues();
3582                 // store values
3583                 for (i = 0; i < fFieldCount; i++) {
3584                     fValues.addElement(fLocalValues[i]);
3585                     addValueType(fLocalValueTypes[i]);
3586                     addItemValueType(fLocalItemValueTypes[i]);
3587                 }
3588             }
3589         } // addValue(String,Field)
3590 
3591         /**
3592          * Returns true if this value store contains the locally scoped value stores
3593          */
3594         public boolean contains() {
3595             // REVISIT: we can improve performance by using hash codes, instead of
3596             // traversing global vector that could be quite large.
3597             int next = 0;
3598             final int size = fValues.size();
3599             LOOP : for (int i = 0; i < size; i = next) {
3600                 next = i + fFieldCount;
3601                 for (int j = 0; j < fFieldCount; j++) {
3602                     Object value1 = fLocalValues[j];
3603                     Object value2 = fValues.elementAt(i);
3604                     short valueType1 = fLocalValueTypes[j];
3605                     short valueType2 = getValueTypeAt(i);
3606                     if (value1 == null || value2 == null || valueType1 != valueType2 || !(value1.equals(value2))) {
3607                         continue LOOP;
3608                     }
3609                     else if(valueType1 == XSConstants.LIST_DT || valueType1 == XSConstants.LISTOFUNION_DT) {
3610                         ShortList list1 = fLocalItemValueTypes[j];
3611                         ShortList list2 = getItemValueTypeAt(i);
3612                         if(list1 == null || list2 == null || !list1.equals(list2))
3613                             continue LOOP;
3614                     }
3615                     i++;
3616                 }
3617                 // found it
3618                 return true;
3619             }
3620             // didn't find it
3621             return false;
3622         } // contains():boolean
3623 
3624         /**
3625          * Returns -1 if this value store contains the specified
3626          * values, otherwise the index of the first field in the
3627          * key sequence.
3628          */
3629         public int contains(ValueStoreBase vsb) {
3630 
3631             final Vector values = vsb.fValues;
3632             final int size1 = values.size();
3633             if (fFieldCount <= 1) {
3634                 for (int i = 0; i < size1; ++i) {
3635                     short val = vsb.getValueTypeAt(i);
3636                     if (!valueTypeContains(val) || !fValues.contains(values.elementAt(i))) {
3637                         return i;
3638                     }
3639                     else if(val == XSConstants.LIST_DT || val == XSConstants.LISTOFUNION_DT) {
3640                         ShortList list1 = vsb.getItemValueTypeAt(i);
3641                         if (!itemValueTypeContains(list1)) {
3642                             return i;
3643                         }
3644                     }
3645                 }
3646             }
3647             /** Handle n-tuples. **/
3648             else {
3649                 final int size2 = fValues.size();
3650                 /** Iterate over each set of fields. **/
3651                 OUTER: for (int i = 0; i < size1; i += fFieldCount) {
3652                     /** Check whether this set is contained in the value store. **/
3653                     INNER: for (int j = 0; j < size2; j += fFieldCount) {
3654                         for (int k = 0; k < fFieldCount; ++k) {
3655                             final Object value1 = values.elementAt(i+k);
3656                             final Object value2 = fValues.elementAt(j+k);
3657                             final short valueType1 = vsb.getValueTypeAt(i+k);
3658                             final short valueType2 = getValueTypeAt(j+k);
3659                             if (value1 != value2 && (valueType1 != valueType2 || value1 == null || !value1.equals(value2))) {
3660                                 continue INNER;
3661                             }
3662                             else if(valueType1 == XSConstants.LIST_DT || valueType1 == XSConstants.LISTOFUNION_DT) {
3663                                 ShortList list1 = vsb.getItemValueTypeAt(i+k);
3664                                 ShortList list2 = getItemValueTypeAt(j+k);
3665                                 if (list1 == null || list2 == null || !list1.equals(list2)) {
3666                                     continue INNER;
3667                                 }
3668                             }
3669                         }
3670                         continue OUTER;
3671                     }
3672                     return i;
3673                 }
3674             }
3675             return -1;
3676 
3677         } // contains(Vector):Object
3678 
3679         //
3680         // Protected methods
3681         //
3682 
3683         protected void checkDuplicateValues() {
3684             // no-op
3685         } // duplicateValue(Map)
3686 
3687         /** Returns a string of the specified values. */
3688         protected String toString(Object[] values) {
3689 
3690             // no values
3691             int size = values.length;
3692             if (size == 0) {
3693                 return "";
3694             }
3695 
3696             fTempBuffer.setLength(0);
3697 
3698             // construct value string
3699             for (int i = 0; i < size; i++) {
3700                 if (i > 0) {
3701                     fTempBuffer.append(',');
3702                 }
3703                 fTempBuffer.append(values[i]);
3704             }
3705             return fTempBuffer.toString();
3706 
3707         } // toString(Object[]):String
3708 
3709         /** Returns a string of the specified values. */
3710         protected String toString(Vector values, int start, int length) {
3711 
3712             // no values
3713             if (length == 0) {
3714                 return "";
3715             }
3716 
3717             // one value
3718             if (length == 1) {
3719                 return String.valueOf(values.elementAt(start));
3720             }
3721 
3722             // construct value string
3723             StringBuffer str = new StringBuffer();
3724             for (int i = 0; i < length; i++) {
3725                 if (i > 0) {
3726                     str.append(',');
3727                 }
3728                 str.append(values.elementAt(start + i));
3729             }
3730             return str.toString();
3731 
3732         } // toString(Vector,int,int):String
3733 
3734         //
3735         // Object methods
3736         //
3737 
3738         /** Returns a string representation of this object. */
3739         public String toString() {
3740             String s = super.toString();
3741             int index1 = s.lastIndexOf('$');
3742             if (index1 != -1) {
3743                 s = s.substring(index1 + 1);
3744             }
3745             int index2 = s.lastIndexOf('.');
3746             if (index2 != -1) {
3747                 s = s.substring(index2 + 1);
3748             }
3749             return s + '[' + fIdentityConstraint + ']';
3750         } // toString():String
3751 
3752         //
3753         // Private methods
3754         //
3755 
3756         private void addValueType(short type) {
3757             if (fUseValueTypeVector) {
3758                 fValueTypes.add(type);
3759             }
3760             else if (fValueTypesLength++ == 0) {
3761                 fValueType = type;
3762             }
3763             else if (fValueType != type) {
3764                 fUseValueTypeVector = true;
3765                 if (fValueTypes == null) {
3766                     fValueTypes = new ShortVector(fValueTypesLength * 2);
3767                 }
3768                 for (int i = 1; i < fValueTypesLength; ++i) {
3769                     fValueTypes.add(fValueType);
3770                 }
3771                 fValueTypes.add(type);
3772             }
3773         }
3774 
3775         private short getValueTypeAt(int index) {
3776             if (fUseValueTypeVector) {
3777                 return fValueTypes.valueAt(index);
3778             }
3779             return fValueType;
3780         }
3781 
3782         private boolean valueTypeContains(short value) {
3783             if (fUseValueTypeVector) {
3784                 return fValueTypes.contains(value);
3785             }
3786             return fValueType == value;
3787         }
3788 
3789         private void addItemValueType(ShortList itemValueType) {
3790             if (fUseItemValueTypeVector) {
3791                 fItemValueTypes.add(itemValueType);
3792             }
3793             else if (fItemValueTypesLength++ == 0) {
3794                 fItemValueType = itemValueType;
3795             }
3796             else if (!(fItemValueType == itemValueType ||
3797                     (fItemValueType != null && fItemValueType.equals(itemValueType)))) {
3798                 fUseItemValueTypeVector = true;
3799                 if (fItemValueTypes == null) {
3800                     fItemValueTypes = new Vector(fItemValueTypesLength * 2);
3801                 }
3802                 for (int i = 1; i < fItemValueTypesLength; ++i) {
3803                     fItemValueTypes.add(fItemValueType);
3804                 }
3805                 fItemValueTypes.add(itemValueType);
3806             }
3807         }
3808 
3809         private ShortList getItemValueTypeAt(int index) {
3810             if (fUseItemValueTypeVector) {
3811                 return (ShortList) fItemValueTypes.elementAt(index);
3812             }
3813             return fItemValueType;
3814         }
3815 
3816         private boolean itemValueTypeContains(ShortList value) {
3817             if (fUseItemValueTypeVector) {
3818                 return fItemValueTypes.contains(value);
3819             }
3820             return fItemValueType == value ||
3821                 (fItemValueType != null && fItemValueType.equals(value));
3822         }
3823 
3824     } // class ValueStoreBase
3825 
3826     /**
3827      * Unique value store.
3828      *
3829      * @author Andy Clark, IBM
3830      */
3831     protected class UniqueValueStore extends ValueStoreBase {
3832 
3833         //
3834         // Constructors
3835         //
3836 
3837         /** Constructs a unique value store. */
3838         public UniqueValueStore(UniqueOrKey unique) {
3839             super(unique);
3840         } // <init>(Unique)
3841 
3842         //
3843         // ValueStoreBase protected methods
3844         //
3845 
3846         /**
3847          * Called when a duplicate value is added.
3848          */
3849         protected void checkDuplicateValues() {
3850             // is this value as a group duplicated?
3851             if (contains()) {
3852                 String code = "DuplicateUnique";
3853                 String value = toString(fLocalValues);
3854                 String eName = fIdentityConstraint.getElementName();
3855                 String cName = fIdentityConstraint.getIdentityConstraintName();
3856                 reportSchemaError(code, new Object[] { value, eName, cName });
3857             }
3858         } // duplicateValue(Map)
3859 
3860     } // class UniqueValueStore
3861 
3862     /**
3863      * Key value store.
3864      *
3865      * @author Andy Clark, IBM
3866      */
3867     protected class KeyValueStore extends ValueStoreBase {
3868 
3869         // REVISIT: Implement a more efficient storage mechanism. -Ac
3870 
3871         //
3872         // Constructors
3873         //
3874 
3875         /** Constructs a key value store. */
3876         public KeyValueStore(UniqueOrKey key) {
3877             super(key);
3878         } // <init>(Key)
3879 
3880         //
3881         // ValueStoreBase protected methods
3882         //
3883 
3884         /**
3885          * Called when a duplicate value is added.
3886          */
3887         protected void checkDuplicateValues() {
3888             if (contains()) {
3889                 String code = "DuplicateKey";
3890                 String value = toString(fLocalValues);
3891                 String eName = fIdentityConstraint.getElementName();
3892                 String cName = fIdentityConstraint.getIdentityConstraintName();
3893                 reportSchemaError(code, new Object[] { value, eName, cName });
3894             }
3895         } // duplicateValue(Map)
3896 
3897     } // class KeyValueStore
3898 
3899     /**
3900      * Key reference value store.
3901      *
3902      * @author Andy Clark, IBM
3903      */
3904     protected class KeyRefValueStore extends ValueStoreBase {
3905 
3906         //
3907         // Data
3908         //
3909 
3910         /** Key value store. */
3911         protected ValueStoreBase fKeyValueStore;
3912 
3913         //
3914         // Constructors
3915         //
3916 
3917         /** Constructs a key value store. */
3918         public KeyRefValueStore(KeyRef keyRef, KeyValueStore keyValueStore) {
3919             super(keyRef);
3920             fKeyValueStore = keyValueStore;
3921         } // <init>(KeyRef)
3922 
3923         //
3924         // ValueStoreBase methods
3925         //
3926 
3927         // end the value Scope; here's where we have to tie
3928         // up keyRef loose ends.
3929         public void endDocumentFragment() {
3930 
3931             // do all the necessary management...
3932             super.endDocumentFragment();
3933 
3934             // verify references
3935             // get the key store corresponding (if it exists):
3936             fKeyValueStore =
3937                 (ValueStoreBase) fValueStoreCache.fGlobalIDConstraintMap.get(
3938                     ((KeyRef) fIdentityConstraint).getKey());
3939 
3940             if (fKeyValueStore == null) {
3941                 // report error
3942                 String code = "KeyRefOutOfScope";
3943                 String value = fIdentityConstraint.toString();
3944                 reportSchemaError(code, new Object[] { value });
3945                 return;
3946             }
3947             int errorIndex = fKeyValueStore.contains(this);
3948             if (errorIndex != -1) {
3949                 String code = "KeyNotFound";
3950                 String values = toString(fValues, errorIndex, fFieldCount);
3951                 String element = fIdentityConstraint.getElementName();
3952                 String name = fIdentityConstraint.getName();
3953                 reportSchemaError(code, new Object[] { name, values, element });
3954             }
3955 
3956         } // endDocumentFragment()
3957 
3958         /** End document. */
3959         public void endDocument() {
3960             super.endDocument();
3961 
3962         } // endDocument()
3963 
3964     } // class KeyRefValueStore
3965 
3966     // value store management
3967 
3968     /**
3969      * Value store cache. This class is used to store the values for
3970      * identity constraints.
3971      *
3972      * @author Andy Clark, IBM
3973      */
3974     protected class ValueStoreCache {
3975 
3976         //
3977         // Data
3978         //
3979         final LocalIDKey fLocalId = new LocalIDKey();
3980         // values stores
3981 
3982         /** stores all global Values stores. */
3983         protected final Vector fValueStores = new Vector();
3984 
3985         /**
3986          * Values stores associated to specific identity constraints.
3987          * This map maps IdentityConstraints and
3988          * the 0-based element on which their selectors first matched to
3989          * a corresponding ValueStore.  This should take care
3990          * of all cases, including where ID constraints with
3991          * descendant-or-self axes occur on recursively-defined
3992          * elements.
3993          */
3994         protected final Map<LocalIDKey, ValueStoreBase>
3995                 fIdentityConstraint2ValueStoreMap = new HashMap<>();
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 Map 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<Map<IdentityConstraint, ValueStoreBase>>
4017                 fGlobalMapStack = new Stack<>();
4018         protected final Map<IdentityConstraint, ValueStoreBase>
4019                 fGlobalIDConstraintMap = new HashMap<>();
4020 
4021         //
4022         // Constructors
4023         //
4024 
4025         /** Default constructor. */
4026         public ValueStoreCache() {
4027         } // <init>()
4028 
4029         //
4030         // Public methods
4031         //
4032 
4033         /** Resets the identity constraint cache. */
4034         public void startDocument() {
4035             fValueStores.removeAllElements();
4036             fIdentityConstraint2ValueStoreMap.clear();
4037             fGlobalIDConstraintMap.clear();
4038             fGlobalMapStack.removeAllElements();
4039         } // startDocument()
4040 
4041         // startElement:  pushes the current fGlobalIDConstraintMap
4042         // onto fGlobalMapStack and clears fGlobalIDConstraint map.
4043         public void startElement() {
4044             // only clone the hashtable when there are elements
4045             if (fGlobalIDConstraintMap.size() > 0)
4046                 fGlobalMapStack.push((Map<IdentityConstraint, ValueStoreBase>)
4047                         ((HashMap)fGlobalIDConstraintMap).clone());
4048             else
4049                 fGlobalMapStack.push(null);
4050             fGlobalIDConstraintMap.clear();
4051         } // startElement(void)
4052 
4053         /** endElement():  merges contents of fGlobalIDConstraintMap with the
4054          * top of fGlobalMapStack into fGlobalIDConstraintMap.
4055          */
4056         public void endElement() {
4057             if (fGlobalMapStack.isEmpty()) {
4058                 return; // must be an invalid doc!
4059             }
4060             Map<IdentityConstraint, ValueStoreBase> oldMap = fGlobalMapStack.pop();
4061             // return if there is no element
4062             if (oldMap == null) {
4063                 return;
4064             }
4065 
4066             for (Map.Entry<IdentityConstraint, ValueStoreBase> entry : oldMap.entrySet()) {
4067                 IdentityConstraint id = entry.getKey();
4068                 ValueStoreBase oldVal = entry.getValue();
4069                 if (oldVal != null) {
4070                     ValueStoreBase currVal = fGlobalIDConstraintMap.get(id);
4071                     if (currVal == null) {
4072                         fGlobalIDConstraintMap.put(id, oldVal);
4073                     }
4074                     else if (currVal != oldVal) {
4075                         currVal.append(oldVal);
4076                     }
4077                 }
4078             }
4079         } // endElement()
4080 
4081         /**
4082          * Initializes the value stores for the specified element
4083          * declaration.
4084          */
4085         public void initValueStoresFor(XSElementDecl eDecl, FieldActivator activator) {
4086             // initialize value stores for unique fields
4087             IdentityConstraint[] icArray = eDecl.fIDConstraints;
4088             int icCount = eDecl.fIDCPos;
4089             for (int i = 0; i < icCount; i++) {
4090                 switch (icArray[i].getCategory()) {
4091                     case (IdentityConstraint.IC_UNIQUE) :
4092                         // initialize value stores for unique fields
4093                         UniqueOrKey unique = (UniqueOrKey) icArray[i];
4094                         LocalIDKey toHash = new LocalIDKey(unique, fElementDepth);
4095                         UniqueValueStore uniqueValueStore =
4096                             (UniqueValueStore) fIdentityConstraint2ValueStoreMap.get(toHash);
4097                         if (uniqueValueStore == null) {
4098                             uniqueValueStore = new UniqueValueStore(unique);
4099                             fIdentityConstraint2ValueStoreMap.put(toHash, uniqueValueStore);
4100                         } else {
4101                             uniqueValueStore.clear();
4102                         }
4103                         fValueStores.addElement(uniqueValueStore);
4104                         activateSelectorFor(icArray[i]);
4105                         break;
4106                     case (IdentityConstraint.IC_KEY) :
4107                         // initialize value stores for key fields
4108                         UniqueOrKey key = (UniqueOrKey) icArray[i];
4109                         toHash = new LocalIDKey(key, fElementDepth);
4110                         KeyValueStore keyValueStore =
4111                             (KeyValueStore) fIdentityConstraint2ValueStoreMap.get(toHash);
4112                         if (keyValueStore == null) {
4113                             keyValueStore = new KeyValueStore(key);
4114                             fIdentityConstraint2ValueStoreMap.put(toHash, keyValueStore);
4115                         } else {
4116                             keyValueStore.clear();
4117                         }
4118                         fValueStores.addElement(keyValueStore);
4119                         activateSelectorFor(icArray[i]);
4120                         break;
4121                     case (IdentityConstraint.IC_KEYREF) :
4122                         // initialize value stores for keyRef fields
4123                         KeyRef keyRef = (KeyRef) icArray[i];
4124                         toHash = new LocalIDKey(keyRef, fElementDepth);
4125                         KeyRefValueStore keyRefValueStore =
4126                             (KeyRefValueStore) fIdentityConstraint2ValueStoreMap.get(toHash);
4127                         if (keyRefValueStore == null) {
4128                             keyRefValueStore = new KeyRefValueStore(keyRef, null);
4129                             fIdentityConstraint2ValueStoreMap.put(toHash, keyRefValueStore);
4130                         } else {
4131                             keyRefValueStore.clear();
4132                         }
4133                         fValueStores.addElement(keyRefValueStore);
4134                         activateSelectorFor(icArray[i]);
4135                         break;
4136                 }
4137             }
4138         } // initValueStoresFor(XSElementDecl)
4139 
4140         /** Returns the value store associated to the specified IdentityConstraint. */
4141         public ValueStoreBase getValueStoreFor(IdentityConstraint id, int initialDepth) {
4142             fLocalId.fDepth = initialDepth;
4143             fLocalId.fId = id;
4144             return fIdentityConstraint2ValueStoreMap.get(fLocalId);
4145         } // getValueStoreFor(IdentityConstraint, int):ValueStoreBase
4146 
4147         /** Returns the global value store associated to the specified IdentityConstraint. */
4148         public ValueStoreBase getGlobalValueStoreFor(IdentityConstraint id) {
4149             return fGlobalIDConstraintMap.get(id);
4150         } // getValueStoreFor(IdentityConstraint):ValueStoreBase
4151 
4152         // This method takes the contents of the (local) ValueStore
4153         // associated with id and moves them into the global
4154         // map, if id is a <unique> or a <key>.
4155         // If it's a <keyRef>, then we leave it for later.
4156         public void transplant(IdentityConstraint id, int initialDepth) {
4157             fLocalId.fDepth = initialDepth;
4158             fLocalId.fId = id;
4159             ValueStoreBase newVals = fIdentityConstraint2ValueStoreMap.get(fLocalId);
4160             if (id.getCategory() == IdentityConstraint.IC_KEYREF)
4161                 return;
4162             ValueStoreBase currVals = 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 Maps.
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