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