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