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