1 /*
   2  * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.xerces.internal.impl.xs.traversers;
  22 
  23 import com.sun.org.apache.xerces.internal.impl.Constants;
  24 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
  25 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
  26 import com.sun.org.apache.xerces.internal.impl.dv.SchemaDVFactory;
  27 import com.sun.org.apache.xerces.internal.impl.dv.xs.XSSimpleTypeDecl;
  28 import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar;
  29 import com.sun.org.apache.xerces.internal.impl.xs.SchemaNamespaceSupport;
  30 import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols;
  31 import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaException;
  32 import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader;
  33 import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeDecl;
  34 import com.sun.org.apache.xerces.internal.impl.xs.XSAttributeGroupDecl;
  35 import com.sun.org.apache.xerces.internal.impl.xs.XSComplexTypeDecl;
  36 import com.sun.org.apache.xerces.internal.impl.xs.XSDDescription;
  37 import com.sun.org.apache.xerces.internal.impl.xs.XSDeclarationPool;
  38 import com.sun.org.apache.xerces.internal.impl.xs.XSElementDecl;
  39 import com.sun.org.apache.xerces.internal.impl.xs.XSGrammarBucket;
  40 import com.sun.org.apache.xerces.internal.impl.xs.XSGroupDecl;
  41 import com.sun.org.apache.xerces.internal.impl.xs.XSMessageFormatter;
  42 import com.sun.org.apache.xerces.internal.impl.xs.XSModelGroupImpl;
  43 import com.sun.org.apache.xerces.internal.impl.xs.XSNotationDecl;
  44 import com.sun.org.apache.xerces.internal.impl.xs.XSParticleDecl;
  45 import com.sun.org.apache.xerces.internal.impl.xs.identity.IdentityConstraint;
  46 import com.sun.org.apache.xerces.internal.impl.xs.opti.ElementImpl;
  47 import com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOMParser;
  48 import com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaParsingConfig;
  49 import com.sun.org.apache.xerces.internal.impl.xs.util.SimpleLocator;
  50 import com.sun.org.apache.xerces.internal.impl.xs.util.XSInputSource;
  51 import com.sun.org.apache.xerces.internal.parsers.SAXParser;
  52 import com.sun.org.apache.xerces.internal.parsers.XML11Configuration;
  53 import com.sun.org.apache.xerces.internal.util.DOMInputSource;
  54 import com.sun.org.apache.xerces.internal.util.DOMUtil;
  55 import com.sun.org.apache.xerces.internal.util.DefaultErrorHandler;
  56 import com.sun.org.apache.xerces.internal.util.ErrorHandlerWrapper;
  57 import com.sun.org.apache.xerces.internal.util.SAXInputSource;
  58 import com.sun.org.apache.xerces.internal.util.StAXInputSource;
  59 import com.sun.org.apache.xerces.internal.util.StAXLocationWrapper;
  60 import com.sun.org.apache.xerces.internal.util.SymbolHash;
  61 import com.sun.org.apache.xerces.internal.util.SymbolTable;
  62 import com.sun.org.apache.xerces.internal.util.URI.MalformedURIException;
  63 import com.sun.org.apache.xerces.internal.util.XMLChar;
  64 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
  65 import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
  66 import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
  67 import com.sun.org.apache.xerces.internal.xni.QName;
  68 import com.sun.org.apache.xerces.internal.xni.XNIException;
  69 import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
  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.grammars.XMLSchemaDescription;
  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.XMLEntityResolver;
  76 import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler;
  77 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
  78 import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException;
  79 import com.sun.org.apache.xerces.internal.xs.StringList;
  80 import com.sun.org.apache.xerces.internal.xs.XSAttributeDeclaration;
  81 import com.sun.org.apache.xerces.internal.xs.XSAttributeGroupDefinition;
  82 import com.sun.org.apache.xerces.internal.xs.XSAttributeUse;
  83 import com.sun.org.apache.xerces.internal.xs.XSConstants;
  84 import com.sun.org.apache.xerces.internal.xs.XSElementDeclaration;
  85 import com.sun.org.apache.xerces.internal.xs.XSModelGroup;
  86 import com.sun.org.apache.xerces.internal.xs.XSModelGroupDefinition;
  87 import com.sun.org.apache.xerces.internal.xs.XSNamedMap;
  88 import com.sun.org.apache.xerces.internal.xs.XSObject;
  89 import com.sun.org.apache.xerces.internal.xs.XSObjectList;
  90 import com.sun.org.apache.xerces.internal.xs.XSParticle;
  91 import com.sun.org.apache.xerces.internal.xs.XSSimpleTypeDefinition;
  92 import com.sun.org.apache.xerces.internal.xs.XSTerm;
  93 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
  94 import com.sun.org.apache.xerces.internal.xs.datatypes.ObjectList;
  95 import java.io.IOException;
  96 import java.io.StringReader;
  97 import java.util.ArrayList;
  98 import java.util.Collections;
  99 import java.util.HashMap;
 100 import java.util.List;
 101 import java.util.Locale;
 102 import java.util.Map;
 103 import java.util.Stack;
 104 import javax.xml.XMLConstants;
 105 import javax.xml.catalog.CatalogFeatures;
 106 import javax.xml.stream.XMLEventReader;
 107 import javax.xml.stream.XMLStreamException;
 108 import javax.xml.stream.XMLStreamReader;
 109 import jdk.xml.internal.JdkXmlUtils;
 110 import jdk.xml.internal.SecuritySupport;
 111 import org.w3c.dom.Document;
 112 import org.w3c.dom.Element;
 113 import org.w3c.dom.Node;
 114 import org.xml.sax.InputSource;
 115 import org.xml.sax.SAXException;
 116 import org.xml.sax.SAXNotRecognizedException;
 117 import org.xml.sax.SAXParseException;
 118 import org.xml.sax.XMLReader;
 119 
 120 /**
 121  * The purpose of this class is to co-ordinate the construction of a
 122  * grammar object corresponding to a schema.  To do this, it must be
 123  * prepared to parse several schema documents (for instance if the
 124  * schema document originally referred to contains <include> or
 125  * <redefined> information items).  If any of the schemas imports a
 126  * schema, other grammars may be constructed as a side-effect.
 127  *
 128  * @xerces.internal
 129  *
 130  * @author Neil Graham, IBM
 131  * @author Pavani Mukthipudi, Sun Microsystems
 132  *
 133  * @LastModified: Apr 2019
 134  */
 135 @SuppressWarnings("deprecation") //org.xml.sax.helpers.XMLReaderFactory
 136 public class XSDHandler {
 137 
 138     /** Feature identifier: validation. */
 139     protected static final String VALIDATION =
 140         Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
 141 
 142     /** feature identifier: XML Schema validation */
 143     protected static final String XMLSCHEMA_VALIDATION =
 144         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
 145 
 146     /** Feature identifier:  allow java encodings */
 147     protected static final String ALLOW_JAVA_ENCODINGS =
 148         Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
 149 
 150     /** Feature identifier:  continue after fatal error */
 151     protected static final String CONTINUE_AFTER_FATAL_ERROR =
 152         Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
 153 
 154     /** Feature identifier:  allow java encodings */
 155     protected static final String STANDARD_URI_CONFORMANT_FEATURE =
 156         Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE;
 157 
 158     /** Feature: disallow doctype*/
 159     protected static final String DISALLOW_DOCTYPE =
 160         Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE;
 161 
 162     /** Feature: generate synthetic annotations */
 163     protected static final String GENERATE_SYNTHETIC_ANNOTATIONS =
 164         Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE;
 165 
 166     /** Feature identifier: validate annotations. */
 167     protected static final String VALIDATE_ANNOTATIONS =
 168         Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATE_ANNOTATIONS_FEATURE;
 169 
 170     /** Feature identifier: honour all schemaLocations */
 171     protected static final String HONOUR_ALL_SCHEMALOCATIONS =
 172       Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE;
 173 
 174     /** Feature identifier: namespace growth */
 175     protected static final String NAMESPACE_GROWTH =
 176       Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE;
 177 
 178     /** Feature identifier: tolerate duplicates */
 179     protected static final String TOLERATE_DUPLICATES =
 180       Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_FEATURE;
 181 
 182     /** Feature identifier: namespace prefixes. */
 183     private static final String NAMESPACE_PREFIXES =
 184         Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE;
 185 
 186     /** Feature identifier: string interning. */
 187     protected static final String STRING_INTERNING =
 188         Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE;
 189 
 190     /** Property identifier: error handler. */
 191     protected static final String ERROR_HANDLER =
 192         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
 193 
 194     /** Property identifier: JAXP schema source. */
 195     protected static final String JAXP_SCHEMA_SOURCE =
 196         Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
 197 
 198     /** Property identifier: entity resolver. */
 199     public static final String ENTITY_RESOLVER =
 200         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
 201 
 202     /** Property identifier: entity manager. */
 203     protected static final String ENTITY_MANAGER =
 204         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
 205 
 206     /** Property identifier: error reporter. */
 207     public static final String ERROR_REPORTER =
 208         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
 209 
 210     /** Property identifier: grammar pool. */
 211     public static final String XMLGRAMMAR_POOL =
 212         Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
 213 
 214     /** Property identifier: symbol table. */
 215     public static final String SYMBOL_TABLE =
 216         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
 217 
 218     /** Property identifier: security manager. */
 219     protected static final String SECURITY_MANAGER =
 220         Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
 221 
 222     /** Property identifier: locale. */
 223     protected static final String LOCALE =
 224         Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY;
 225 
 226     /** Property identifier: Security property manager. */
 227     private static final String XML_SECURITY_PROPERTY_MANAGER =
 228         Constants.XML_SECURITY_PROPERTY_MANAGER;
 229 
 230     protected static final boolean DEBUG_NODE_POOL = false;
 231 
 232     // Data
 233 
 234     // different sorts of declarations; should make lookup and
 235     // traverser calling more efficient/less bulky.
 236     final static int ATTRIBUTE_TYPE          = 1;
 237     final static int ATTRIBUTEGROUP_TYPE     = 2;
 238     final static int ELEMENT_TYPE            = 3;
 239     final static int GROUP_TYPE              = 4;
 240     final static int IDENTITYCONSTRAINT_TYPE = 5;
 241     final static int NOTATION_TYPE           = 6;
 242     final static int TYPEDECL_TYPE           = 7;
 243 
 244     // this string gets appended to redefined names; it's purpose is to be
 245     // as unlikely as possible to cause collisions.
 246     public final static String REDEF_IDENTIFIER = "_fn3dktizrknc9pi";
 247 
 248     //protected data that can be accessible by any traverser
 249 
 250     protected XSDeclarationPool fDeclPool = null;
 251 
 252     // the Security manager in effect.
 253     protected XMLSecurityManager fSecurityManager = null;
 254 
 255     private String fAccessExternalSchema;
 256     private String fAccessExternalDTD;
 257 
 258     // These tables correspond to the symbol spaces defined in the
 259     // spec.
 260     // They are keyed with a QName (that is, String("URI,localpart) and
 261     // their values are nodes corresponding to the given name's decl.
 262     // By asking the node for its ownerDocument and looking in
 263     // XSDocumentInfoRegistry we can easily get the corresponding
 264     // XSDocumentInfo object.
 265     private boolean registryEmpty = true;
 266     private Map<String, Element> fUnparsedAttributeRegistry = new HashMap<>();
 267     private Map<String, Element> fUnparsedAttributeGroupRegistry =  new HashMap<>();
 268     private Map<String, Element> fUnparsedElementRegistry =  new HashMap<>();
 269     private Map<String, Element> fUnparsedGroupRegistry =  new HashMap<>();
 270     private Map<String, Element> fUnparsedIdentityConstraintRegistry =  new HashMap<>();
 271     private Map<String, Element> fUnparsedNotationRegistry =  new HashMap<>();
 272     private Map<String, Element> fUnparsedTypeRegistry =  new HashMap<>();
 273     // Compensation for the above maps to locate XSDocumentInfo,
 274     // Since we may take Schema Element directly, so can not get the
 275     // corresponding XSDocumentInfo object just using above maps.
 276     private Map<String, XSDocumentInfo> fUnparsedAttributeRegistrySub =  new HashMap<>();
 277     private Map<String, XSDocumentInfo> fUnparsedAttributeGroupRegistrySub =  new HashMap<>();
 278     private Map<String, XSDocumentInfo> fUnparsedElementRegistrySub =  new HashMap<>();
 279     private Map<String, XSDocumentInfo> fUnparsedGroupRegistrySub =  new HashMap<>();
 280     private Map<String, XSDocumentInfo> fUnparsedIdentityConstraintRegistrySub =  new HashMap<>();
 281     private Map<String, XSDocumentInfo> fUnparsedNotationRegistrySub =  new HashMap<>();
 282     private Map<String, XSDocumentInfo> fUnparsedTypeRegistrySub =  new HashMap<>();
 283 
 284     // Stores XSDocumentInfo (keyed by component name), to check for duplicate
 285     // components declared within the same xsd document
 286     @SuppressWarnings({"rawtypes", "unchecked"})
 287     private Map<String, XSDocumentInfo> fUnparsedRegistriesExt[] = new HashMap[] {
 288         null,
 289         null, // ATTRIBUTE_TYPE
 290         null, // ATTRIBUTEGROUP_TYPE
 291         null, // ELEMENT_TYPE
 292         null, // GROUP_TYPE
 293         null, // IDENTITYCONSTRAINT_TYPE
 294         null, // NOTATION_TYPE
 295         null, // TYPEDECL_TYPE
 296     };
 297 
 298     // this map is keyed on by XSDocumentInfo objects.  Its values
 299     // are Vectors containing the XSDocumentInfo objects <include>d,
 300     // <import>ed or <redefine>d by the key XSDocumentInfo.
 301     private Map<XSDocumentInfo, List<XSDocumentInfo>> fDependencyMap = new HashMap<>();
 302 
 303     // this map is keyed on by a target namespace.  Its values
 304     // are Vectors containing namespaces imported by schema documents
 305     // with the key target namespace.
 306     // if an imported schema has absent namespace, the value "null" is stored.
 307     private Map<String, List<String>> fImportMap = new HashMap<> ();
 308 
 309     // all namespaces that imports other namespaces
 310     // if the importing schema has absent namespace, empty string is stored.
 311     // (because the key of a map can't be null.)
 312     private List<String> fAllTNSs = new ArrayList<>();
 313 
 314     // stores instance document mappings between namespaces and schema hints
 315     private Map<String, XMLSchemaLoader.LocationArray> fLocationPairs = null;
 316 
 317     // Records which nodes are hidden when the input is a DOMInputSource.
 318     Map<Node, String> fHiddenNodes = null;
 319 
 320     // convenience methods
 321     private String null2EmptyString(String ns) {
 322         return ns == null ? XMLSymbols.EMPTY_STRING : ns;
 323     }
 324     private String emptyString2Null(String ns) {
 325         return ns == XMLSymbols.EMPTY_STRING ? null : ns;
 326     }
 327     // use Schema Element to lookup the SystemId.
 328     private String doc2SystemId(Element ele) {
 329         String documentURI = null;
 330         /**
 331          * REVISIT: Casting until DOM Level 3 interfaces are available. -- mrglavas
 332          */
 333         if(ele.getOwnerDocument() instanceof com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOM){
 334             documentURI = ((com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOM) ele.getOwnerDocument()).getDocumentURI();
 335         }
 336         return documentURI != null ? documentURI : fDoc2SystemId.get(ele);
 337     }
 338 
 339     // This vector stores strings which are combinations of the
 340     // publicId and systemId of the inputSource corresponding to a
 341     // schema document.  This combination is used so that the user's
 342     // EntityResolver can provide a consistent way of identifying a
 343     // schema document that is included in multiple other schemas.
 344     private Map<XSDKey, Element> fTraversed = new HashMap<>();
 345 
 346     // this map contains a mapping from Schema Element to its systemId
 347     // this is useful to resolve a uri relative to the referring document
 348     private Map<Element, String> fDoc2SystemId = new HashMap<>();
 349 
 350     // the primary XSDocumentInfo we were called to parse
 351     private XSDocumentInfo fRoot = null;
 352 
 353     // This map's job is to act as a link between the Schema Element and its
 354     // XSDocumentInfo object.
 355     private Map<Element, XSDocumentInfo> fDoc2XSDocumentMap = new HashMap<>();
 356 
 357     // map between <redefine> elements and the XSDocumentInfo
 358     // objects that correspond to the documents being redefined.
 359     private Map<Element, XSDocumentInfo> fRedefine2XSDMap = null;
 360 
 361     // map between <redefine> elements and the namespace support
 362     private Map<Element, SchemaNamespaceSupport> fRedefine2NSSupport = null;
 363 
 364     // these objects store a mapping between the names of redefining
 365     // groups/attributeGroups and the groups/AttributeGroups which
 366     // they redefine by restriction (implicitly).  It is up to the
 367     // Group and AttributeGroup traversers to check these restrictions for
 368     // validity.
 369     private final Map<String, String> fRedefinedRestrictedAttributeGroupRegistry = new HashMap<>();
 370     private final Map<String, String> fRedefinedRestrictedGroupRegistry = new HashMap<>();
 371 
 372     // a variable storing whether the last schema document
 373     // processed (by getSchema) was a duplicate.
 374     private boolean fLastSchemaWasDuplicate;
 375 
 376     // validate annotations feature
 377     private boolean fValidateAnnotations = false;
 378 
 379     //handle multiple import feature
 380     private boolean fHonourAllSchemaLocations = false;
 381 
 382     //handle namespace growth feature
 383     boolean fNamespaceGrowth = false;
 384 
 385     // handle tolerate duplicates feature
 386     boolean fTolerateDuplicates = false;
 387 
 388     // the XMLErrorReporter
 389     private XMLErrorReporter fErrorReporter;
 390 
 391     // the XMLErrorHandler
 392     private XMLErrorHandler fErrorHandler;
 393 
 394     // the Locale
 395     private Locale fLocale;
 396 
 397     // the XMLEntityManager
 398     private XMLEntityManager fEntityManager;
 399 
 400     // the XSAttributeChecker
 401     private XSAttributeChecker fAttributeChecker;
 402 
 403     // the symbol table
 404     private SymbolTable fSymbolTable;
 405 
 406     // the GrammarResolver
 407     private XSGrammarBucket fGrammarBucket;
 408 
 409     // the Grammar description
 410     private XSDDescription fSchemaGrammarDescription;
 411 
 412     // the Grammar Pool
 413     private XMLGrammarPool fGrammarPool;
 414 
 415     // the security property manager
 416     private XMLSecurityPropertyManager fSecurityPropertyMgr = null;
 417 
 418     /** indicate whether Catalog should be used for resolving external resources */
 419     private boolean fUseCatalog = true;
 420     private String fCatalogFile;
 421     private String fDefer;
 422     private String fPrefer;
 423     private String fResolve;
 424 
 425     private boolean fOverrideDefaultParser;
 426 
 427     //************ Traversers **********
 428     XSDAttributeGroupTraverser fAttributeGroupTraverser;
 429     XSDAttributeTraverser fAttributeTraverser;
 430     XSDComplexTypeTraverser fComplexTypeTraverser;
 431     XSDElementTraverser fElementTraverser;
 432     XSDGroupTraverser fGroupTraverser;
 433     XSDKeyrefTraverser fKeyrefTraverser;
 434     XSDNotationTraverser fNotationTraverser;
 435     XSDSimpleTypeTraverser fSimpleTypeTraverser;
 436     XSDUniqueOrKeyTraverser fUniqueOrKeyTraverser;
 437     XSDWildcardTraverser fWildCardTraverser;
 438 
 439     SchemaDVFactory fDVFactory;
 440     SchemaDOMParser fSchemaParser;
 441     SchemaContentHandler fXSContentHandler;
 442     StAXSchemaParser fStAXSchemaParser;
 443     XML11Configuration fAnnotationValidator;
 444     XSAnnotationGrammarPool fGrammarBucketAdapter;
 445 
 446     // these data members are needed for the deferred traversal
 447     // of local elements.
 448 
 449     // the initial size of the array to store deferred local elements
 450     private static final int INIT_STACK_SIZE = 30;
 451     // the incremental size of the array to store deferred local elements
 452     private static final int INC_STACK_SIZE  = 10;
 453     // current position of the array (# of deferred local elements)
 454     private int fLocalElemStackPos = 0;
 455 
 456     private XSParticleDecl[] fParticle = new XSParticleDecl[INIT_STACK_SIZE];
 457     private Element[] fLocalElementDecl = new Element[INIT_STACK_SIZE];
 458     private XSDocumentInfo[] fLocalElementDecl_schema = new XSDocumentInfo[INIT_STACK_SIZE]; //JACK
 459     private int[] fAllContext = new int[INIT_STACK_SIZE];
 460     private XSObject[] fParent = new XSObject[INIT_STACK_SIZE];
 461     private String [][] fLocalElemNamespaceContext = new String [INIT_STACK_SIZE][1];
 462 
 463     // these data members are needed for the deferred traversal
 464     // of keyrefs.
 465 
 466     // the initial size of the array to store deferred keyrefs
 467     private static final int INIT_KEYREF_STACK = 2;
 468     // the incremental size of the array to store deferred keyrefs
 469     private static final int INC_KEYREF_STACK_AMOUNT = 2;
 470     // current position of the array (# of deferred keyrefs)
 471     private int fKeyrefStackPos = 0;
 472 
 473     private Element [] fKeyrefs = new Element[INIT_KEYREF_STACK];
 474     private XSDocumentInfo [] fKeyrefsMapXSDocumentInfo = new XSDocumentInfo[INIT_KEYREF_STACK];
 475     private XSElementDecl [] fKeyrefElems = new XSElementDecl [INIT_KEYREF_STACK];
 476     private String [][] fKeyrefNamespaceContext = new String[INIT_KEYREF_STACK][1];
 477 
 478     // global decls: map from decl name to decl object
 479     SymbolHash fGlobalAttrDecls = new SymbolHash(12);
 480     SymbolHash fGlobalAttrGrpDecls = new SymbolHash(5);
 481     SymbolHash fGlobalElemDecls = new SymbolHash(25);
 482     SymbolHash fGlobalGroupDecls = new SymbolHash(5);
 483     SymbolHash fGlobalNotationDecls = new SymbolHash(1);
 484     SymbolHash fGlobalIDConstraintDecls = new SymbolHash(3);
 485     SymbolHash fGlobalTypeDecls = new SymbolHash(25);
 486 
 487     // Constructors
 488     public XSDHandler(){
 489         fHiddenNodes = new HashMap<>();
 490         fSchemaParser = new SchemaDOMParser(new SchemaParsingConfig());
 491     }
 492 
 493     // it should be possible to use the same XSDHandler to parse
 494     // multiple schema documents; this will allow one to be
 495     // constructed.
 496     public XSDHandler (XSGrammarBucket gBucket) {
 497         this();
 498         fGrammarBucket = gBucket;
 499 
 500         // Note: don't use SchemaConfiguration internally
 501         //       we will get stack overflaw because
 502         //       XMLSchemaValidator will be instantiating XSDHandler...
 503         fSchemaGrammarDescription = new XSDDescription();
 504     } // end constructor
 505 
 506     /**
 507      * This method initiates the parse of a schema.  It will likely be
 508      * called from the Validator and it will make the
 509      * resulting grammar available; it returns a reference to this object just
 510      * in case.  A reset(XMLComponentManager) must be called before this methods is called.
 511      * @param is
 512      * @param desc
 513      * @param locationPairs
 514      * @return the SchemaGrammar
 515      * @throws IOException
 516      */
 517     public SchemaGrammar parseSchema(XMLInputSource is, XSDDescription desc,
 518             Map<String, XMLSchemaLoader.LocationArray> locationPairs)
 519     throws IOException {
 520         fLocationPairs = locationPairs;
 521         fSchemaParser.resetNodePool();
 522         SchemaGrammar grammar = null;
 523         String schemaNamespace  = null;
 524         short referType = desc.getContextType();
 525 
 526         // if loading using JAXP schemaSource property, or using grammar caching loadGrammar
 527         // the desc.targetNamespace is always null.
 528         // Therefore we should not attempt to find out if
 529         // the schema is already in the bucket, since in the case we have
 530         // no namespace schema in the bucket, findGrammar will always return the
 531         // no namespace schema.
 532         if (referType != XSDDescription.CONTEXT_PREPARSE){
 533             // first try to find it in the bucket/pool, return if one is found
 534             if (fHonourAllSchemaLocations && referType == XSDDescription.CONTEXT_IMPORT && isExistingGrammar(desc, fNamespaceGrowth)) {
 535                 grammar = fGrammarBucket.getGrammar(desc.getTargetNamespace());
 536             }
 537             else {
 538                 grammar = findGrammar(desc, fNamespaceGrowth);
 539             }
 540             if (grammar != null) {
 541                 if (!fNamespaceGrowth) {
 542                     return grammar;
 543                 }
 544                 else {
 545                     try {
 546                         if (grammar.getDocumentLocations().contains(XMLEntityManager.expandSystemId(is.getSystemId(), is.getBaseSystemId(), false))) {
 547                             return grammar;
 548                         }
 549                     }
 550                     catch (MalformedURIException e) {
 551                         //REVISIT: return the grammar?
 552                     }
 553                 }
 554             }
 555 
 556             schemaNamespace = desc.getTargetNamespace();
 557             // handle empty string URI as null
 558             if (schemaNamespace != null) {
 559                 schemaNamespace = fSymbolTable.addSymbol(schemaNamespace);
 560             }
 561         }
 562 
 563         // before parsing a schema, need to clear registries associated with
 564         // parsing schemas
 565         prepareForParse();
 566 
 567         Element schemaRoot = null;
 568         // first phase:  construct trees.
 569         if (is instanceof DOMInputSource) {
 570             schemaRoot = getSchemaDocument(schemaNamespace, (DOMInputSource) is,
 571                     referType == XSDDescription.CONTEXT_PREPARSE,
 572                     referType, null);
 573         } // DOMInputSource
 574         else if (is instanceof SAXInputSource) {
 575                 schemaRoot = getSchemaDocument(schemaNamespace, (SAXInputSource) is,
 576                     referType == XSDDescription.CONTEXT_PREPARSE,
 577                     referType, null);
 578         } // SAXInputSource
 579         else if (is instanceof StAXInputSource) {
 580             schemaRoot = getSchemaDocument(schemaNamespace, (StAXInputSource) is,
 581                     referType == XSDDescription.CONTEXT_PREPARSE,
 582                     referType, null);
 583         } // StAXInputSource
 584         else if (is instanceof XSInputSource) {
 585             schemaRoot = getSchemaDocument((XSInputSource) is, desc);
 586         } // XSInputSource
 587         else {
 588                 schemaRoot = getSchemaDocument(schemaNamespace, is,
 589                   referType == XSDDescription.CONTEXT_PREPARSE,
 590                   referType, null);
 591 
 592         } //is instanceof XMLInputSource
 593 
 594         if (schemaRoot == null) {
 595             if (is instanceof XSInputSource) {
 596                 // Need to return a grammar. If the XSInputSource has a list
 597                 // of grammar objects, then get the first one and return it.
 598                 // If it has a list of components, then get the grammar that
 599                 // contains the first component and return it.
 600                 // If we return null, the XMLSchemaLoader will think nothing
 601                 // was loaded, and will not try to put the grammar objects
 602                 // into the grammar pool.
 603                 XSInputSource xsinput = (XSInputSource)is;
 604                 SchemaGrammar[] grammars = xsinput.getGrammars();
 605                 if (grammars != null && grammars.length > 0) {
 606                     grammar = fGrammarBucket.getGrammar(grammars[0].getTargetNamespace());
 607                 }
 608                 else {
 609                     XSObject[] components = xsinput.getComponents();
 610                     if (components != null && components.length > 0) {
 611                         grammar = fGrammarBucket.getGrammar(components[0].getNamespace());
 612                     }
 613                 }
 614             }
 615             // something went wrong right off the hop
 616             return grammar;
 617         }
 618 
 619         if (referType == XSDDescription.CONTEXT_PREPARSE) {
 620                 Element schemaElem = schemaRoot;
 621             schemaNamespace = DOMUtil.getAttrValue(schemaElem, SchemaSymbols.ATT_TARGETNAMESPACE);
 622             if(schemaNamespace != null && schemaNamespace.length() > 0) {
 623                 // Since now we've discovered a namespace, we need to update xsd key
 624                 // and store this schema in traversed schemas bucket
 625                 schemaNamespace = fSymbolTable.addSymbol(schemaNamespace);
 626                 desc.setTargetNamespace(schemaNamespace);
 627             }
 628             else {
 629                 schemaNamespace = null;
 630             }
 631             grammar = findGrammar(desc, fNamespaceGrowth);
 632             String schemaId = XMLEntityManager.expandSystemId(is.getSystemId(), is.getBaseSystemId(), false);
 633             if (grammar != null) {
 634                 // When namespace growth is enabled and a null location is provided we cannot tell
 635                 // whether we've loaded this schema document before so we must assume that we haven't.
 636                 if (!fNamespaceGrowth || (schemaId != null && grammar.getDocumentLocations().contains(schemaId))) {
 637                     return grammar;
 638                 }
 639             }
 640 
 641             XSDKey key = new XSDKey(schemaId, referType, schemaNamespace);
 642             fTraversed.put(key, schemaRoot);
 643             if (schemaId != null) {
 644                 fDoc2SystemId.put(schemaRoot, schemaId);
 645             }
 646         }
 647 
 648         // before constructing trees and traversing a schema, need to reset
 649         // all traversers and clear all registries
 650         prepareForTraverse();
 651 
 652         fRoot = constructTrees(schemaRoot, is.getSystemId(), desc, grammar != null);
 653         if (fRoot == null) {
 654             return null;
 655         }
 656 
 657         // second phase:  fill global registries.
 658         buildGlobalNameRegistries();
 659 
 660         // third phase:  call traversers
 661         List<Object> annotationInfo = fValidateAnnotations ? new ArrayList<>() : null;
 662         traverseSchemas(annotationInfo);
 663 
 664         // fourth phase: handle local element decls
 665         traverseLocalElements();
 666 
 667         // fifth phase:  handle Keyrefs
 668         resolveKeyRefs();
 669 
 670         // sixth phase:  validate attribute of non-schema namespaces
 671         // REVISIT: skip this for now. we really don't want to do it.
 672         //fAttributeChecker.checkNonSchemaAttributes(fGrammarBucket);
 673 
 674         // seventh phase:  store imported grammars
 675         // for all grammars with <import>s
 676         for (int i = fAllTNSs.size() - 1; i >= 0; i--) {
 677             // get its target namespace
 678             String tns = fAllTNSs.get(i);
 679             // get all namespaces it imports
 680             List<String> ins = fImportMap.get(tns);
 681             List<SchemaGrammar> grammars = new ArrayList<>();
 682             // get the grammar
 683             SchemaGrammar sg = fGrammarBucket.getGrammar(emptyString2Null(tns));
 684             if (sg == null)
 685                 continue;
 686             SchemaGrammar isg;
 687             // for imported namespace
 688             int count = 0;
 689             for (int j = 0; j < ins.size(); j++) {
 690                 // get imported grammar
 691                 isg = fGrammarBucket.getGrammar(ins.get(j));
 692                 // reuse the same vector
 693                 if (isg != null) {
 694                     grammars.add(isg);
 695                 }
 696             }
 697             // set the imported grammars
 698             sg.setImportedGrammars(grammars);
 699         }
 700 
 701         /** validate annotations **/
 702         if (fValidateAnnotations && annotationInfo.size() > 0) {
 703             validateAnnotations(annotationInfo);
 704         }
 705 
 706         // and return.
 707         return fGrammarBucket.getGrammar(fRoot.fTargetNamespace);
 708     } // end parseSchema
 709 
 710     private void validateAnnotations(List<Object> annotationInfo) {
 711         if (fAnnotationValidator == null) {
 712             createAnnotationValidator();
 713         }
 714         final int size = annotationInfo.size();
 715         final XMLInputSource src = new XMLInputSource(null, null, null, false);
 716         fGrammarBucketAdapter.refreshGrammars(fGrammarBucket);
 717         for (int i = 0; i < size; i += 2) {
 718             src.setSystemId((String) annotationInfo.get(i));
 719             XSAnnotationInfo annotation = (XSAnnotationInfo) annotationInfo.get(i+1);
 720             while (annotation != null) {
 721                 src.setCharacterStream(new StringReader(annotation.fAnnotation));
 722                 try {
 723                     fAnnotationValidator.parse(src);
 724                 }
 725                 catch (IOException exc) {}
 726                 annotation = annotation.next;
 727             }
 728         }
 729     }
 730 
 731     private void createAnnotationValidator() {
 732         fAnnotationValidator = new XML11Configuration();
 733         fGrammarBucketAdapter = new XSAnnotationGrammarPool();
 734         fAnnotationValidator.setFeature(VALIDATION, true);
 735         fAnnotationValidator.setFeature(XMLSCHEMA_VALIDATION, true);
 736         fAnnotationValidator.setProperty(XMLGRAMMAR_POOL, fGrammarBucketAdapter);
 737         /** set security manager and XML Security Property Manager **/
 738         fAnnotationValidator.setProperty(SECURITY_MANAGER, (fSecurityManager != null) ? fSecurityManager : new XMLSecurityManager(true));
 739         fAnnotationValidator.setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr);
 740         /** Set error handler. **/
 741         fAnnotationValidator.setProperty(ERROR_HANDLER, (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler());
 742         /** Set locale. **/
 743         fAnnotationValidator.setProperty(LOCALE, fLocale);
 744 
 745         // Passing on the Catalog settings
 746         fAnnotationValidator.setFeature(XMLConstants.USE_CATALOG, fUseCatalog);
 747         fAnnotationValidator.setProperty(JdkXmlUtils.CATALOG_FILES, fCatalogFile);
 748         fAnnotationValidator.setProperty(JdkXmlUtils.CATALOG_DEFER, fDefer);
 749         fAnnotationValidator.setProperty(JdkXmlUtils.CATALOG_PREFER, fPrefer);
 750         fAnnotationValidator.setProperty(JdkXmlUtils.CATALOG_RESOLVE, fResolve);
 751     }
 752 
 753     /**
 754      * Pull the grammar out of the bucket simply using
 755      * its TNS as a key
 756      */
 757     SchemaGrammar getGrammar(String tns) {
 758         return fGrammarBucket.getGrammar(tns);
 759     }
 760 
 761     /**
 762      * First try to find a grammar in the bucket, if failed, consult the
 763      * grammar pool. If a grammar is found in the pool, then add it (and all
 764      * imported ones) into the bucket.
 765      */
 766     protected SchemaGrammar findGrammar(XSDDescription desc, boolean ignoreConflict) {
 767         SchemaGrammar sg = fGrammarBucket.getGrammar(desc.getTargetNamespace());
 768         if (sg == null) {
 769             if (fGrammarPool != null) {
 770                 sg = (SchemaGrammar)fGrammarPool.retrieveGrammar(desc);
 771                 if (sg != null) {
 772                     // put this grammar into the bucket, along with grammars
 773                     // imported by it (directly or indirectly)
 774                     if (!fGrammarBucket.putGrammar(sg, true, ignoreConflict)) {
 775                         // REVISIT: a conflict between new grammar(s) and grammars
 776                         // in the bucket. What to do? A warning? An exception?
 777                         reportSchemaWarning("GrammarConflict", null, null);
 778                         sg = null;
 779                     }
 780                 }
 781             }
 782         }
 783         return sg;
 784     }
 785 
 786     // may wish to have setter methods for ErrorHandler,
 787     // EntityResolver...
 788 
 789     private static final String[][] NS_ERROR_CODES = {
 790             {"src-include.2.1", "src-include.2.1"},
 791             {"src-redefine.3.1", "src-redefine.3.1"},
 792             {"src-import.3.1", "src-import.3.2"},
 793             null,
 794             {"TargetNamespace.1", "TargetNamespace.2"},
 795             {"TargetNamespace.1", "TargetNamespace.2"},
 796             {"TargetNamespace.1", "TargetNamespace.2"},
 797             {"TargetNamespace.1", "TargetNamespace.2"}
 798     };
 799 
 800     private static final String[] ELE_ERROR_CODES = {
 801             "src-include.1", "src-redefine.2", "src-import.2", "schema_reference.4",
 802             "schema_reference.4", "schema_reference.4", "schema_reference.4", "schema_reference.4"
 803     };
 804 
 805     // This method does several things:
 806     // It constructs an instance of an XSDocumentInfo object using the
 807     // schemaRoot node.  Then, for each <include>,
 808     // <redefine>, and <import> children, it attempts to resolve the
 809     // requested schema document, initiates a DOM parse, and calls
 810     // itself recursively on that document's root.  It also records in
 811     // the DependencyMap object what XSDocumentInfo objects its XSDocumentInfo
 812     // depends on.
 813     // It also makes sure the targetNamespace of the schema it was
 814     // called to parse is correct.
 815     protected XSDocumentInfo constructTrees(Element schemaRoot, String locationHint, XSDDescription desc, boolean nsCollision) {
 816         if (schemaRoot == null) return null;
 817         String callerTNS = desc.getTargetNamespace();
 818         short referType = desc.getContextType();
 819 
 820         XSDocumentInfo currSchemaInfo = null;
 821         try {
 822             // note that attributes are freed at end of traverseSchemas()
 823             currSchemaInfo = new XSDocumentInfo(schemaRoot, fAttributeChecker, fSymbolTable);
 824         } catch (XMLSchemaException se) {
 825             reportSchemaError(ELE_ERROR_CODES[referType],
 826                     new Object[]{locationHint},
 827                                           schemaRoot);
 828             return null;
 829         }
 830         // targetNamespace="" is not valid, issue a warning, and ignore it
 831         if (currSchemaInfo.fTargetNamespace != null &&
 832                 currSchemaInfo.fTargetNamespace.length() == 0) {
 833             reportSchemaWarning("EmptyTargetNamespace",
 834                     new Object[]{locationHint},
 835                                         schemaRoot);
 836             currSchemaInfo.fTargetNamespace = null;
 837         }
 838 
 839         if (callerTNS != null) {
 840             // the second index to the NS_ERROR_CODES array
 841             // if the caller/expected NS is not absent, we use the first column
 842             int secondIdx = 0;
 843             // for include and redefine
 844             if (referType == XSDDescription.CONTEXT_INCLUDE ||
 845                     referType == XSDDescription.CONTEXT_REDEFINE) {
 846                 // if the referred document has no targetNamespace,
 847                 // it's a chameleon schema
 848                 if (currSchemaInfo.fTargetNamespace == null) {
 849                     currSchemaInfo.fTargetNamespace = callerTNS;
 850                     currSchemaInfo.fIsChameleonSchema = true;
 851                 }
 852                 // if the referred document has a target namespace differing
 853                 // from the caller, it's an error
 854                 else if (callerTNS != currSchemaInfo.fTargetNamespace) {
 855                     reportSchemaError(NS_ERROR_CODES[referType][secondIdx],
 856                             new Object [] {callerTNS, currSchemaInfo.fTargetNamespace},
 857                                                         schemaRoot);
 858                     return null;
 859                 }
 860             }
 861             // for instance and import, the two NS's must be the same
 862             else if (referType != XSDDescription.CONTEXT_PREPARSE && callerTNS != currSchemaInfo.fTargetNamespace) {
 863                 reportSchemaError(NS_ERROR_CODES[referType][secondIdx],
 864                         new Object [] {callerTNS, currSchemaInfo.fTargetNamespace},
 865                                                 schemaRoot);
 866                 return null;
 867             }
 868         }
 869         // now there is no caller/expected NS, it's an error for the referred
 870         // document to have a target namespace, unless we are preparsing a schema
 871         else if (currSchemaInfo.fTargetNamespace != null) {
 872             // set the target namespace of the description
 873             if (referType == XSDDescription.CONTEXT_PREPARSE) {
 874                 desc.setTargetNamespace(currSchemaInfo.fTargetNamespace);
 875                 callerTNS = currSchemaInfo.fTargetNamespace;
 876             }
 877             else {
 878                 // the second index to the NS_ERROR_CODES array
 879                 // if the caller/expected NS is absent, we use the second column
 880                 int secondIdx = 1;
 881                 reportSchemaError(NS_ERROR_CODES[referType][secondIdx],
 882                         new Object [] {callerTNS, currSchemaInfo.fTargetNamespace},
 883                                                 schemaRoot);
 884                 return null;
 885             }
 886         }
 887         // the other cases (callerTNS == currSchemaInfo.fTargetNamespce == null)
 888         // are valid
 889 
 890         // a schema document can always access it's own target namespace
 891         currSchemaInfo.addAllowedNS(currSchemaInfo.fTargetNamespace);
 892 
 893         SchemaGrammar sg = null;
 894 
 895         // we have a namespace collision
 896         if (nsCollision) {
 897             SchemaGrammar sg2 = fGrammarBucket.getGrammar(currSchemaInfo.fTargetNamespace);
 898             if (sg2.isImmutable()) {
 899                 sg = new SchemaGrammar(sg2);
 900                 fGrammarBucket.putGrammar(sg);
 901                 // update all the grammars in the bucket to point to the new grammar.
 902                 updateImportListWith(sg);
 903             }
 904             else {
 905                 sg = sg2;
 906             }
 907 
 908             // update import list of the new grammar
 909             updateImportListFor(sg);
 910         }
 911         else if (referType == XSDDescription.CONTEXT_INCLUDE ||
 912                 referType == XSDDescription.CONTEXT_REDEFINE) {
 913             sg = fGrammarBucket.getGrammar(currSchemaInfo.fTargetNamespace);
 914         }
 915         else if(fHonourAllSchemaLocations && referType == XSDDescription.CONTEXT_IMPORT) {
 916             sg = findGrammar(desc, false);
 917             if(sg == null) {
 918                 sg = new SchemaGrammar(currSchemaInfo.fTargetNamespace, desc.makeClone(), fSymbolTable);
 919                 fGrammarBucket.putGrammar(sg);
 920             }
 921         }
 922         else {
 923             sg = new SchemaGrammar(currSchemaInfo.fTargetNamespace, desc.makeClone(), fSymbolTable);
 924             fGrammarBucket.putGrammar(sg);
 925         }
 926 
 927         // store the document and its location
 928         // REVISIT: don't expose the DOM tree
 929         sg.addDocument(null, fDoc2SystemId.get(currSchemaInfo.fSchemaElement));
 930 
 931         fDoc2XSDocumentMap.put(schemaRoot, currSchemaInfo);
 932         List<XSDocumentInfo> dependencies = new ArrayList<>();
 933         Element rootNode = schemaRoot;
 934 
 935         Element newSchemaRoot = null;
 936         for (Element child = DOMUtil.getFirstChildElement(rootNode);
 937         child != null;
 938         child = DOMUtil.getNextSiblingElement(child)) {
 939             String schemaNamespace=null;
 940             String schemaHint=null;
 941             String localName = DOMUtil.getLocalName(child);
 942 
 943             short refType = -1;
 944             boolean importCollision = false;
 945 
 946             if (localName.equals(SchemaSymbols.ELT_ANNOTATION))
 947                 continue;
 948             else if (localName.equals(SchemaSymbols.ELT_IMPORT)) {
 949                 refType = XSDDescription.CONTEXT_IMPORT;
 950                 // have to handle some validation here too!
 951                 // call XSAttributeChecker to fill in attrs
 952                 Object[] importAttrs = fAttributeChecker.checkAttributes(child, true, currSchemaInfo);
 953                 schemaHint = (String)importAttrs[XSAttributeChecker.ATTIDX_SCHEMALOCATION];
 954                 schemaNamespace = (String)importAttrs[XSAttributeChecker.ATTIDX_NAMESPACE];
 955                 if (schemaNamespace != null)
 956                     schemaNamespace = fSymbolTable.addSymbol(schemaNamespace);
 957 
 958                 // check contents and process optional annotations
 959                 Element importChild = DOMUtil.getFirstChildElement(child);
 960                 if(importChild != null ) {
 961                     String importComponentType = DOMUtil.getLocalName(importChild);
 962                     if (importComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) {
 963                         // promoting annotations to parent component
 964                         sg.addAnnotation(
 965                                 fElementTraverser.traverseAnnotationDecl(importChild, importAttrs, true, currSchemaInfo));
 966                     } else {
 967                         reportSchemaError("s4s-elt-must-match.1", new Object [] {localName, "annotation?", importComponentType}, child);
 968                     }
 969                     if(DOMUtil.getNextSiblingElement(importChild) != null) {
 970                         reportSchemaError("s4s-elt-must-match.1", new Object [] {localName, "annotation?", DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(importChild))}, child);
 971                     }
 972                 }
 973                 else {
 974                     String text = DOMUtil.getSyntheticAnnotation(child);
 975                     if (text != null) {
 976                         sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, importAttrs, true, currSchemaInfo));
 977                     }
 978                 }
 979                 fAttributeChecker.returnAttrArray(importAttrs, currSchemaInfo);
 980 
 981                 // a document can't import another document with the same namespace
 982                 if (schemaNamespace == currSchemaInfo.fTargetNamespace) {
 983                     reportSchemaError(schemaNamespace != null ?
 984                             "src-import.1.1" : "src-import.1.2", new Object [] {schemaNamespace}, child);
 985                     continue;
 986                 }
 987 
 988                 // if this namespace has not been imported by this document,
 989                 //  then import if multiple imports support is enabled.
 990                 if(currSchemaInfo.isAllowedNS(schemaNamespace)) {
 991                     if(!fHonourAllSchemaLocations && !fNamespaceGrowth)
 992                         continue;
 993                 }
 994                 else  {
 995                     currSchemaInfo.addAllowedNS(schemaNamespace);
 996                 }
 997                 // also record the fact that one namespace imports another one
 998                 // convert null to ""
 999                 String tns = null2EmptyString(currSchemaInfo.fTargetNamespace);
1000                 // get all namespaces imported by this one
1001                List<String> ins = fImportMap.get(tns);
1002                 // if no namespace was imported, create new ArrayList<>
1003                 if (ins == null) {
1004                     // record that this one imports other(s)
1005                     fAllTNSs.add(tns);
1006                     ins = new ArrayList<>();
1007                     fImportMap.put(tns, ins);
1008                     ins.add(schemaNamespace);
1009                 }
1010                 else if (!ins.contains(schemaNamespace)){
1011                     ins.add(schemaNamespace);
1012                 }
1013 
1014                 fSchemaGrammarDescription.reset();
1015                 fSchemaGrammarDescription.setContextType(XSDDescription.CONTEXT_IMPORT);
1016                 fSchemaGrammarDescription.setBaseSystemId(doc2SystemId(schemaRoot));
1017                 fSchemaGrammarDescription.setLiteralSystemId(schemaHint);
1018                 fSchemaGrammarDescription.setLocationHints(new String[]{schemaHint});
1019                 fSchemaGrammarDescription.setTargetNamespace(schemaNamespace);
1020 
1021                 // if a grammar with the same namespace and location exists (or being
1022                 // built), ignore this one (don't traverse it).
1023                 SchemaGrammar isg = findGrammar(fSchemaGrammarDescription, fNamespaceGrowth);
1024                 if (isg != null) {
1025                     if (fNamespaceGrowth) {
1026                         try {
1027                             if (isg.getDocumentLocations().contains(XMLEntityManager.expandSystemId(schemaHint, fSchemaGrammarDescription.getBaseSystemId(), false))) {
1028                                 continue;
1029                             }
1030                             else {
1031                                 importCollision = true;
1032                             }
1033                         }
1034                         catch (MalformedURIException e) {
1035                         }
1036                     }
1037                     else if (!fHonourAllSchemaLocations || isExistingGrammar(fSchemaGrammarDescription, false)) {
1038                         continue;
1039                     }
1040                 }
1041                 //if ((!fHonourAllSchemaLocations && findGrammar(fSchemaGrammarDescription) != null) || isExistingGrammar(fSchemaGrammarDescription))
1042                 //    continue;
1043 
1044                 // If "findGrammar" returns a grammar, then this is not the
1045                 // the first time we see a location for a given namespace.
1046                 // Don't consult the location pair map in this case,
1047                 // otherwise the location will be ignored because it'll get
1048                 // resolved to the same location as the first hint.
1049                 newSchemaRoot = resolveSchema(fSchemaGrammarDescription, false, child, isg == null);
1050             }
1051             else if ((localName.equals(SchemaSymbols.ELT_INCLUDE)) ||
1052                     (localName.equals(SchemaSymbols.ELT_REDEFINE))) {
1053                 // validation for redefine/include will be the same here; just
1054                 // make sure TNS is right (don't care about redef contents
1055                 // yet).
1056                 Object[] includeAttrs = fAttributeChecker.checkAttributes(child, true, currSchemaInfo);
1057                 schemaHint = (String)includeAttrs[XSAttributeChecker.ATTIDX_SCHEMALOCATION];
1058                 // store the namespace decls of the redefine element
1059                 if (localName.equals(SchemaSymbols.ELT_REDEFINE)) {
1060                     if (fRedefine2NSSupport == null) fRedefine2NSSupport = new HashMap<>();
1061                     fRedefine2NSSupport.put(child, new SchemaNamespaceSupport(currSchemaInfo.fNamespaceSupport));
1062                 }
1063 
1064                 // check annotations.  Must do this here to avoid having to
1065                 // re-parse attributes later
1066                 if(localName.equals(SchemaSymbols.ELT_INCLUDE)) {
1067                     Element includeChild = DOMUtil.getFirstChildElement(child);
1068                     if(includeChild != null ) {
1069                         String includeComponentType = DOMUtil.getLocalName(includeChild);
1070                         if (includeComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) {
1071                             // promoting annotations to parent component
1072                             sg.addAnnotation(
1073                                     fElementTraverser.traverseAnnotationDecl(includeChild, includeAttrs, true, currSchemaInfo));
1074                         } else {
1075                             reportSchemaError("s4s-elt-must-match.1",
1076                                     new Object [] {localName, "annotation?", includeComponentType}, child);
1077                         }
1078                         if(DOMUtil.getNextSiblingElement(includeChild) != null) {
1079                             reportSchemaError("s4s-elt-must-match.1",
1080                                     new Object [] {localName, "annotation?",
1081                                         DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(includeChild))}, child);
1082                         }
1083                     }
1084                     else {
1085                         String text = DOMUtil.getSyntheticAnnotation(child);
1086                         if (text != null) {
1087                             sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, includeAttrs, true, currSchemaInfo));
1088                         }
1089                     }
1090                 }
1091                 else {
1092                     for (Element redefinedChild = DOMUtil.getFirstChildElement(child);
1093                     redefinedChild != null;
1094                     redefinedChild = DOMUtil.getNextSiblingElement(redefinedChild)) {
1095                         String redefinedComponentType = DOMUtil.getLocalName(redefinedChild);
1096                         if (redefinedComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) {
1097                             // promoting annotations to parent component
1098                             sg.addAnnotation(
1099                                     fElementTraverser.traverseAnnotationDecl(redefinedChild, includeAttrs, true, currSchemaInfo));
1100                             DOMUtil.setHidden(redefinedChild, fHiddenNodes);
1101                         }
1102                         else {
1103                             String text = DOMUtil.getSyntheticAnnotation(child);
1104                             if (text != null) {
1105                                 sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, includeAttrs, true, currSchemaInfo));
1106                             }
1107                         }
1108                         // catch all other content errors later
1109                     }
1110                 }
1111                 fAttributeChecker.returnAttrArray(includeAttrs, currSchemaInfo);
1112                 // schemaLocation is required on <include> and <redefine>
1113                 if (schemaHint == null) {
1114                     reportSchemaError("s4s-att-must-appear", new Object [] {
1115                             "<include> or <redefine>", "schemaLocation"},
1116                             child);
1117                 }
1118                 // pass the systemId of the current document as the base systemId
1119                 boolean mustResolve = false;
1120                 refType = XSDDescription.CONTEXT_INCLUDE;
1121                 if(localName.equals(SchemaSymbols.ELT_REDEFINE)) {
1122                     mustResolve = nonAnnotationContent(child);
1123                     refType = XSDDescription.CONTEXT_REDEFINE;
1124                 }
1125                 fSchemaGrammarDescription.reset();
1126                 fSchemaGrammarDescription.setContextType(refType);
1127                 fSchemaGrammarDescription.setBaseSystemId(doc2SystemId(schemaRoot));
1128                 fSchemaGrammarDescription.setLocationHints(new String[]{schemaHint});
1129                 fSchemaGrammarDescription.setTargetNamespace(callerTNS);
1130 
1131                 boolean alreadyTraversed = false;
1132                 XMLInputSource schemaSource =
1133                         resolveSchemaSource(fSchemaGrammarDescription, mustResolve, child, true);
1134                 if (fNamespaceGrowth && refType == XSDDescription.CONTEXT_INCLUDE) {
1135                     try {
1136                         final String schemaId = XMLEntityManager.expandSystemId(
1137                                 schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false);
1138                         alreadyTraversed = sg.getDocumentLocations().contains(schemaId);
1139                     }
1140                     catch(MalformedURIException e) {
1141 
1142                     }
1143                 }
1144 
1145                 if (!alreadyTraversed) {
1146                     newSchemaRoot = resolveSchema(schemaSource, fSchemaGrammarDescription, mustResolve, child);
1147                     schemaNamespace = currSchemaInfo.fTargetNamespace;
1148                 }
1149                 else {
1150                     fLastSchemaWasDuplicate = true;
1151                 }
1152             }
1153             else {
1154                 // no more possibility of schema references in well-formed
1155                 // schema...
1156                 break;
1157             }
1158 
1159             // If the schema is duplicate, we needn't call constructTrees() again.
1160             // To handle mutual <include>s
1161             XSDocumentInfo newSchemaInfo = null;
1162             if (fLastSchemaWasDuplicate) {
1163                 newSchemaInfo = newSchemaRoot == null ? null : fDoc2XSDocumentMap.get(newSchemaRoot);
1164             }
1165             else {
1166                 newSchemaInfo = constructTrees(newSchemaRoot, schemaHint,
1167                         fSchemaGrammarDescription, importCollision);
1168             }
1169 
1170             if (localName.equals(SchemaSymbols.ELT_REDEFINE) &&
1171                     newSchemaInfo != null) {
1172                 // must record which schema we're redefining so that we can
1173                 // rename the right things later!
1174                 if (fRedefine2XSDMap == null) fRedefine2XSDMap = new HashMap<>();
1175                 fRedefine2XSDMap.put(child, newSchemaInfo);
1176             }
1177             if (newSchemaRoot != null) {
1178                 if (newSchemaInfo != null)
1179                     dependencies.add(newSchemaInfo);
1180                 newSchemaRoot = null;
1181             }
1182         }
1183 
1184         fDependencyMap.put(currSchemaInfo, dependencies);
1185         return currSchemaInfo;
1186     } // end constructTrees
1187 
1188     private boolean isExistingGrammar(XSDDescription desc, boolean ignoreConflict) {
1189         SchemaGrammar sg = fGrammarBucket.getGrammar(desc.getTargetNamespace());
1190         if (sg == null) {
1191             return findGrammar(desc, ignoreConflict) != null;
1192         }
1193         else if (sg.isImmutable()) {
1194             return true;
1195         }
1196         else {
1197             try {
1198                 return sg.getDocumentLocations().contains(XMLEntityManager.expandSystemId(desc.getLiteralSystemId(), desc.getBaseSystemId(), false));
1199             }
1200             catch (MalformedURIException e) {
1201                 return false;
1202             }
1203         }
1204     }
1205 
1206     /**
1207      * Namespace growth
1208      *
1209      * Go through the import list of a given grammar and for each imported
1210      * grammar, check to see if the grammar bucket has a newer version.
1211      * If a new instance is found, we update the import list with the
1212      * newer version.
1213      */
1214     private void updateImportListFor(SchemaGrammar grammar) {
1215        List<SchemaGrammar> importedGrammars = grammar.getImportedGrammars();
1216         if (importedGrammars != null) {
1217             for (int i=0; i<importedGrammars.size(); i++) {
1218                 SchemaGrammar isg1 = importedGrammars.get(i);
1219                 SchemaGrammar isg2 = fGrammarBucket.getGrammar(isg1.getTargetNamespace());
1220                 if (isg2 != null && isg1 != isg2) {
1221                     importedGrammars.set(i, isg2);
1222                 }
1223             }
1224         }
1225     }
1226 
1227     /**
1228      * Namespace growth
1229      *
1230      * Go throuth the grammar bucket, and for each grammar in the bucket
1231      * check the import list. If there exists a grammar in import list
1232      * that has the same namespace as newGrammar, but a different instance,
1233      * then update the import list and replace the old grammar instance with
1234      * the new one
1235      */
1236     private void updateImportListWith(SchemaGrammar newGrammar) {
1237         SchemaGrammar[] schemaGrammars = fGrammarBucket.getGrammars();
1238         for (int i = 0; i < schemaGrammars.length; ++i) {
1239             SchemaGrammar sg = schemaGrammars[i];
1240             if (sg != newGrammar) {
1241                 List<SchemaGrammar> importedGrammars = sg.getImportedGrammars();
1242                 if (importedGrammars != null) {
1243                     for (int j=0; j<importedGrammars.size(); j++) {
1244                         SchemaGrammar isg = importedGrammars.get(j);
1245                         if (null2EmptyString(isg.getTargetNamespace()).equals(
1246                                 null2EmptyString(newGrammar.getTargetNamespace()))) {
1247                             if (isg != newGrammar) {
1248                                 importedGrammars.set(j, newGrammar);
1249                             }
1250                             break;
1251                         }
1252                     }
1253                 }
1254             }
1255         }
1256     }
1257 
1258     // This method builds registries for all globally-referenceable
1259     // names.  A registry will be built for each symbol space defined
1260     // by the spec.  It is also this method's job to rename redefined
1261     // components, and to record which components redefine others (so
1262     // that implicit redefinitions of groups and attributeGroups can be handled).
1263     protected void buildGlobalNameRegistries() {
1264 
1265         registryEmpty = false;
1266         // Starting with fRoot, we examine each child of the schema
1267         // element.  Skipping all imports and includes, we record the names
1268         // of all other global components (and children of <redefine>).  We
1269         // also put <redefine> names in a registry that we look through in
1270         // case something needs renaming.  Once we're done with a schema we
1271         // set its Document node to hidden so that we don't try to traverse
1272         // it again; then we look to its Dependency map entry.  We keep a
1273         // stack of schemas that we haven't yet finished processing; this
1274         // is a depth-first traversal.
1275 
1276         Stack<XSDocumentInfo> schemasToProcess = new Stack<>();
1277         schemasToProcess.push(fRoot);
1278 
1279         while (!schemasToProcess.empty()) {
1280             XSDocumentInfo currSchemaDoc = schemasToProcess.pop();
1281             Element currDoc = currSchemaDoc.fSchemaElement;
1282             if(DOMUtil.isHidden(currDoc, fHiddenNodes)){
1283                 // must have processed this already!
1284                 continue;
1285             }
1286 
1287             Element currRoot = currDoc;
1288             // process this schema's global decls
1289             boolean dependenciesCanOccur = true;
1290             for (Element globalComp =
1291                 DOMUtil.getFirstChildElement(currRoot);
1292             globalComp != null;
1293             globalComp = DOMUtil.getNextSiblingElement(globalComp)) {
1294                 // this loop makes sure the <schema> element ordering is
1295                 // also valid.
1296                 if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_ANNOTATION)) {
1297                     //skip it; traverse it later
1298                     continue;
1299                 }
1300                 else if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_INCLUDE) ||
1301                         DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_IMPORT)) {
1302                     if (!dependenciesCanOccur) {
1303                         reportSchemaError("s4s-elt-invalid-content.3", new Object [] {DOMUtil.getLocalName(globalComp)}, globalComp);
1304                     }
1305                     DOMUtil.setHidden(globalComp, fHiddenNodes);
1306                 }
1307                 else if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_REDEFINE)) {
1308                     if (!dependenciesCanOccur) {
1309                         reportSchemaError("s4s-elt-invalid-content.3", new Object [] {DOMUtil.getLocalName(globalComp)}, globalComp);
1310                     }
1311                     for (Element redefineComp = DOMUtil.getFirstChildElement(globalComp);
1312                     redefineComp != null;
1313                     redefineComp = DOMUtil.getNextSiblingElement(redefineComp)) {
1314                         String lName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME);
1315                         if (lName.length() == 0) // an error we'll catch later
1316                             continue;
1317                         String qName = currSchemaDoc.fTargetNamespace == null ?
1318                                 ","+lName:
1319                                     currSchemaDoc.fTargetNamespace +","+lName;
1320                         qName = XMLChar.trim(qName);
1321                         String componentType = DOMUtil.getLocalName(redefineComp);
1322                         if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
1323                             checkForDuplicateNames(qName, ATTRIBUTEGROUP_TYPE, fUnparsedAttributeGroupRegistry, fUnparsedAttributeGroupRegistrySub, redefineComp, currSchemaDoc);
1324                             // the check will have changed our name;
1325                             String targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME)+REDEF_IDENTIFIER;
1326                             // and all we need to do is error-check+rename our kkids:
1327                             renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_ATTRIBUTEGROUP,
1328                                     lName, targetLName);
1329                         }
1330                         else if ((componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) ||
1331                                 (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE))) {
1332                             checkForDuplicateNames(qName, TYPEDECL_TYPE, fUnparsedTypeRegistry, fUnparsedTypeRegistrySub, redefineComp, currSchemaDoc);
1333                             // the check will have changed our name;
1334                             String targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME) + REDEF_IDENTIFIER;
1335                             // and all we need to do is error-check+rename our kkids:
1336                             if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
1337                                 renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_COMPLEXTYPE,
1338                                         lName, targetLName);
1339                             }
1340                             else { // must be simpleType
1341                                 renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_SIMPLETYPE,
1342                                         lName, targetLName);
1343                             }
1344                         }
1345                         else if (componentType.equals(SchemaSymbols.ELT_GROUP)) {
1346                             checkForDuplicateNames(qName, GROUP_TYPE, fUnparsedGroupRegistry, fUnparsedGroupRegistrySub, redefineComp, currSchemaDoc);
1347                             // the check will have changed our name;
1348                             String targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME)+REDEF_IDENTIFIER;
1349                             // and all we need to do is error-check+rename our kids:
1350                             renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_GROUP,
1351                                     lName, targetLName);
1352                         }
1353                     } // end march through <redefine> children
1354                     // and now set as traversed
1355                     //DOMUtil.setHidden(globalComp);
1356                 }
1357                 else {
1358                     dependenciesCanOccur = false;
1359                     String lName = DOMUtil.getAttrValue(globalComp, SchemaSymbols.ATT_NAME);
1360                     if (lName.length() == 0) // an error we'll catch later
1361                         continue;
1362                     String qName = currSchemaDoc.fTargetNamespace == null?
1363                             ","+lName:
1364                                 currSchemaDoc.fTargetNamespace +","+lName;
1365                     qName = XMLChar.trim(qName);
1366                     String componentType = DOMUtil.getLocalName(globalComp);
1367 
1368                     if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTE)) {
1369                         checkForDuplicateNames(qName, ATTRIBUTE_TYPE, fUnparsedAttributeRegistry, fUnparsedAttributeRegistrySub, globalComp, currSchemaDoc);
1370                     }
1371                     else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
1372                         checkForDuplicateNames(qName, ATTRIBUTEGROUP_TYPE, fUnparsedAttributeGroupRegistry, fUnparsedAttributeGroupRegistrySub, globalComp, currSchemaDoc);
1373                     }
1374                     else if ((componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) ||
1375                             (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE))) {
1376                         checkForDuplicateNames(qName, TYPEDECL_TYPE, fUnparsedTypeRegistry, fUnparsedTypeRegistrySub, globalComp, currSchemaDoc);
1377                     }
1378                     else if (componentType.equals(SchemaSymbols.ELT_ELEMENT)) {
1379                         checkForDuplicateNames(qName, ELEMENT_TYPE, fUnparsedElementRegistry, fUnparsedElementRegistrySub, globalComp, currSchemaDoc);
1380                     }
1381                     else if (componentType.equals(SchemaSymbols.ELT_GROUP)) {
1382                         checkForDuplicateNames(qName, GROUP_TYPE, fUnparsedGroupRegistry, fUnparsedGroupRegistrySub, globalComp, currSchemaDoc);
1383                     }
1384                     else if (componentType.equals(SchemaSymbols.ELT_NOTATION)) {
1385                         checkForDuplicateNames(qName, NOTATION_TYPE, fUnparsedNotationRegistry, fUnparsedNotationRegistrySub, globalComp, currSchemaDoc);
1386                     }
1387                 }
1388             } // end for
1389 
1390             // now we're done with this one!
1391             DOMUtil.setHidden(currDoc, fHiddenNodes);
1392             // now add the schemas this guy depends on
1393             List<XSDocumentInfo> currSchemaDepends = fDependencyMap.get(currSchemaDoc);
1394             for (XSDocumentInfo currSchemaDepend : currSchemaDepends) {
1395                 schemasToProcess.push(currSchemaDepend);
1396             }
1397         } // while
1398 
1399     } // end buildGlobalNameRegistries
1400 
1401     // Beginning at the first schema processing was requested for
1402     // (fRoot), this method
1403     // examines each child (global schema information item) of each
1404     // schema document (and of each <redefine> element)
1405     // corresponding to an XSDocumentInfo object.  If the
1406     // readOnly field on that node has not been set, it calls an
1407     // appropriate traverser to traverse it.  Once all global decls in
1408     // an XSDocumentInfo object have been traversed, it marks that object
1409     // as traversed (or hidden) in order to avoid infinite loops.  It completes
1410     // when it has visited all XSDocumentInfo objects in the
1411     // DependencyMap and marked them as traversed.
1412     protected void traverseSchemas(List<Object> annotationInfo) {
1413         // the process here is very similar to that in
1414         // buildGlobalRegistries, except we can't set our schemas as
1415         // hidden for a second time; so make them all visible again
1416         // first!
1417         setSchemasVisible(fRoot);
1418         Stack<XSDocumentInfo> schemasToProcess = new Stack<>();
1419         schemasToProcess.push(fRoot);
1420         while (!schemasToProcess.empty()) {
1421             XSDocumentInfo currSchemaDoc = schemasToProcess.pop();
1422             Element currDoc = currSchemaDoc.fSchemaElement;
1423 
1424             SchemaGrammar currSG = fGrammarBucket.getGrammar(currSchemaDoc.fTargetNamespace);
1425 
1426             if(DOMUtil.isHidden(currDoc, fHiddenNodes)) {
1427                 // must have processed this already!
1428                 continue;
1429             }
1430             Element currRoot = currDoc;
1431             boolean sawAnnotation = false;
1432             // traverse this schema's global decls
1433             for (Element globalComp =
1434                 DOMUtil.getFirstVisibleChildElement(currRoot, fHiddenNodes);
1435             globalComp != null;
1436             globalComp = DOMUtil.getNextVisibleSiblingElement(globalComp, fHiddenNodes)) {
1437                 DOMUtil.setHidden(globalComp, fHiddenNodes);
1438                 String componentType = DOMUtil.getLocalName(globalComp);
1439                 // includes and imports will not show up here!
1440                 if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_REDEFINE)) {
1441                     // use the namespace decls for the redefine, instead of for the parent <schema>
1442                     currSchemaDoc.backupNSSupport((fRedefine2NSSupport!=null) ?
1443                             fRedefine2NSSupport.get(globalComp) : null);
1444                     for (Element redefinedComp = DOMUtil.getFirstVisibleChildElement(globalComp, fHiddenNodes);
1445                     redefinedComp != null;
1446                     redefinedComp = DOMUtil.getNextVisibleSiblingElement(redefinedComp, fHiddenNodes)) {
1447                         String redefinedComponentType = DOMUtil.getLocalName(redefinedComp);
1448                         DOMUtil.setHidden(redefinedComp, fHiddenNodes);
1449                         if (redefinedComponentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
1450                             fAttributeGroupTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG);
1451                         }
1452                         else if (redefinedComponentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
1453                             fComplexTypeTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG);
1454                         }
1455                         else if (redefinedComponentType.equals(SchemaSymbols.ELT_GROUP)) {
1456                             fGroupTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG);
1457                         }
1458                         else if (redefinedComponentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
1459                             fSimpleTypeTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG);
1460                         }
1461                         // annotations will have been processed already; this is now
1462                         // unnecessary
1463                         //else if (redefinedComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) {
1464                         //    fElementTraverser.traverseAnnotationDecl(redefinedComp, null, true, currSchemaDoc);
1465                         //}
1466                         else {
1467                             reportSchemaError("s4s-elt-must-match.1", new Object [] {DOMUtil.getLocalName(globalComp), "(annotation | (simpleType | complexType | group | attributeGroup))*", redefinedComponentType}, redefinedComp);
1468                         }
1469                     } // end march through <redefine> children
1470                     currSchemaDoc.restoreNSSupport();
1471                 }
1472                 else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTE)) {
1473                     fAttributeTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG);
1474                 }
1475                 else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
1476                     fAttributeGroupTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG);
1477                 }
1478                 else if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
1479                     fComplexTypeTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG);
1480                 }
1481                 else if (componentType.equals(SchemaSymbols.ELT_ELEMENT)) {
1482                     fElementTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG);
1483                 }
1484                 else if (componentType.equals(SchemaSymbols.ELT_GROUP)) {
1485                     fGroupTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG);
1486                 }
1487                 else if (componentType.equals(SchemaSymbols.ELT_NOTATION)) {
1488                     fNotationTraverser.traverse(globalComp, currSchemaDoc, currSG);
1489                 }
1490                 else if (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
1491                     fSimpleTypeTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG);
1492                 }
1493                 else if (componentType.equals(SchemaSymbols.ELT_ANNOTATION)) {
1494                     currSG.addAnnotation(fElementTraverser.traverseAnnotationDecl(globalComp, currSchemaDoc.getSchemaAttrs(), true, currSchemaDoc));
1495                     sawAnnotation = true;
1496                 }
1497                 else {
1498                     reportSchemaError("s4s-elt-invalid-content.1", new Object [] {SchemaSymbols.ELT_SCHEMA, DOMUtil.getLocalName(globalComp)}, globalComp);
1499                 }
1500             } // end for
1501 
1502             if (!sawAnnotation) {
1503                 String text = DOMUtil.getSyntheticAnnotation(currRoot);
1504                 if (text != null) {
1505                     currSG.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(currRoot, text, currSchemaDoc.getSchemaAttrs(), true, currSchemaDoc));
1506                 }
1507             }
1508 
1509             /** Collect annotation information for validation. **/
1510             if (annotationInfo != null) {
1511                 XSAnnotationInfo info = currSchemaDoc.getAnnotations();
1512                 /** Only add annotations to the list if there were any in this document. **/
1513                 if (info != null) {
1514                     annotationInfo.add(doc2SystemId(currDoc));
1515                     annotationInfo.add(info);
1516                 }
1517             }
1518             // now we're done with this one!
1519             currSchemaDoc.returnSchemaAttrs();
1520             DOMUtil.setHidden(currDoc, fHiddenNodes);
1521 
1522             // now add the schemas this guy depends on
1523             List<XSDocumentInfo> currSchemaDepends = fDependencyMap.get(currSchemaDoc);
1524             for (XSDocumentInfo currSchemaDepend : currSchemaDepends) {
1525                 schemasToProcess.push(currSchemaDepend);
1526             }
1527         } // while
1528     } // end traverseSchemas
1529 
1530     // store whether we have reported an error about that no grammar
1531     // is found for the given namespace uri
1532     private List<String> fReportedTNS = null;
1533     // check whether we need to report an error against the given uri.
1534     // if we have reported an error, then we don't need to report again;
1535     // otherwise we reported the error, and remember this fact.
1536     private final boolean needReportTNSError(String uri) {
1537         if (fReportedTNS == null)
1538             fReportedTNS = new ArrayList<>();
1539         else if (fReportedTNS.contains(uri))
1540             return false;
1541         fReportedTNS.add(uri);
1542         return true;
1543     }
1544 
1545     private static final String[] COMP_TYPE = {
1546             null,               // index 0
1547             "attribute declaration",
1548             "attribute group",
1549             "element declaration",
1550             "group",
1551             "identity constraint",
1552             "notation",
1553             "type definition",
1554     };
1555 
1556     private static final String[] CIRCULAR_CODES = {
1557             "Internal-Error",
1558             "Internal-Error",
1559             "src-attribute_group.3",
1560             "e-props-correct.6",
1561             "mg-props-correct.2",
1562             "Internal-Error",
1563             "Internal-Error",
1564             "st-props-correct.2",       //or ct-props-correct.3
1565     };
1566 
1567     // add a global attribute decl from a current schema load (only if no existing decl is found)
1568     void addGlobalAttributeDecl(XSAttributeDecl decl) {
1569         final String namespace = decl.getNamespace();
1570         final String declKey = (namespace == null || namespace.length() == 0)
1571             ? "," + decl.getName() : namespace + "," + decl.getName();
1572 
1573         if (fGlobalAttrDecls.get(declKey) == null) {
1574             fGlobalAttrDecls.put(declKey, decl);
1575         }
1576     }
1577 
1578     // add a global attribute group decl from a current schema load (only if no existing decl is found)
1579     void addGlobalAttributeGroupDecl(XSAttributeGroupDecl decl) {
1580         final String namespace = decl.getNamespace();
1581         final String declKey = (namespace == null || namespace.length() == 0)
1582             ? "," + decl.getName() : namespace + "," + decl.getName();
1583 
1584         if (fGlobalAttrGrpDecls.get(declKey) == null) {
1585             fGlobalAttrGrpDecls.put(declKey, decl);
1586         }
1587     }
1588 
1589     // add a global element decl from a current schema load (only if no existing decl is found)
1590     void addGlobalElementDecl(XSElementDecl decl) {
1591         final String namespace = decl.getNamespace();
1592         final String declKey = (namespace == null || namespace.length() == 0)
1593             ? "," + decl.getName() : namespace + "," + decl.getName();
1594 
1595         if (fGlobalElemDecls.get(declKey) == null) {
1596             fGlobalElemDecls.put(declKey, decl);
1597         }
1598     }
1599 
1600     // add a global group decl from a current schema load (only if no existing decl is found)
1601     void addGlobalGroupDecl(XSGroupDecl decl) {
1602         final String namespace = decl.getNamespace();
1603         final String declKey = (namespace == null || namespace.length() == 0)
1604             ? "," + decl.getName() : namespace + "," + decl.getName();
1605 
1606         if (fGlobalGroupDecls.get(declKey) == null) {
1607             fGlobalGroupDecls.put(declKey, decl);
1608         }
1609     }
1610 
1611     // add a global notation decl from a current schema load (only if no existing decl is found)
1612     void addGlobalNotationDecl(XSNotationDecl decl) {
1613         final String namespace = decl.getNamespace();
1614         final String declKey = (namespace == null || namespace.length() == 0)
1615             ? "," + decl.getName() : namespace + "," + decl.getName();
1616 
1617         if (fGlobalNotationDecls.get(declKey) == null) {
1618             fGlobalNotationDecls.put(declKey, decl);
1619         }
1620     }
1621 
1622     // add a global type decl from a current schema load (only if no existing decl is found)
1623     void addGlobalTypeDecl(XSTypeDefinition decl) {
1624         final String namespace = decl.getNamespace();
1625         final String declKey = (namespace == null || namespace.length() == 0)
1626             ? "," + decl.getName() : namespace + "," + decl.getName();
1627 
1628         if (fGlobalTypeDecls.get(declKey) == null) {
1629             fGlobalTypeDecls.put(declKey, decl);
1630         }
1631     }
1632 
1633     // add a identity constraint decl from a current schema load (only if no existing decl is found)
1634     void addIDConstraintDecl(IdentityConstraint decl) {
1635         final String namespace = decl.getNamespace();
1636         final String declKey = (namespace == null || namespace.length() == 0)
1637             ? "," + decl.getIdentityConstraintName() : namespace + "," + decl.getIdentityConstraintName();
1638 
1639         if (fGlobalIDConstraintDecls.get(declKey) == null) {
1640             fGlobalIDConstraintDecls.put(declKey, decl);
1641         }
1642     }
1643 
1644     private XSAttributeDecl getGlobalAttributeDecl(String declKey) {
1645         return (XSAttributeDecl)fGlobalAttrDecls.get(declKey);
1646     }
1647 
1648     private XSAttributeGroupDecl getGlobalAttributeGroupDecl(String declKey) {
1649         return (XSAttributeGroupDecl)fGlobalAttrGrpDecls.get(declKey);
1650     }
1651 
1652     private XSElementDecl getGlobalElementDecl(String declKey) {
1653         return (XSElementDecl)fGlobalElemDecls.get(declKey);
1654     }
1655 
1656     private XSGroupDecl getGlobalGroupDecl(String declKey) {
1657         return (XSGroupDecl)fGlobalGroupDecls.get(declKey);
1658     }
1659 
1660     private XSNotationDecl getGlobalNotationDecl(String declKey) {
1661         return (XSNotationDecl)fGlobalNotationDecls.get(declKey);
1662     }
1663 
1664     private XSTypeDefinition getGlobalTypeDecl(String declKey) {
1665         return (XSTypeDefinition)fGlobalTypeDecls.get(declKey);
1666     }
1667 
1668     private IdentityConstraint getIDConstraintDecl(String declKey) {
1669         return (IdentityConstraint)fGlobalIDConstraintDecls.get(declKey);
1670     }
1671 
1672     // since it is forbidden for traversers to talk to each other
1673     // directly (except wen a traverser encounters a local declaration),
1674     // this provides a generic means for a traverser to call
1675     // for the traversal of some declaration.  An XSDocumentInfo is
1676     // required because the XSDocumentInfo that the traverser is traversing
1677     // may bear no relation to the one the handler is operating on.
1678     // This method will:
1679     // 1.  See if a global definition matching declToTraverse exists;
1680     // 2. if so, determine if there is a path from currSchema to the
1681     // schema document where declToTraverse lives (i.e., do a lookup
1682     // in DependencyMap);
1683     // 3. depending on declType (which will be relevant to step 1 as
1684     // well), call the appropriate traverser with the appropriate
1685     // XSDocumentInfo object.
1686     // This method returns whatever the traverser it called returned;
1687     // this will be an Object of some kind
1688     // that lives in the Grammar.
1689     protected Object getGlobalDecl(XSDocumentInfo currSchema,
1690             int declType,
1691             QName declToTraverse,
1692             Element elmNode) {
1693 
1694         if (DEBUG_NODE_POOL) {
1695             System.out.println("TRAVERSE_GL: "+declToTraverse.toString());
1696         }
1697 
1698         // from the schema spec, all built-in types are present in all schemas,
1699         // so if the requested component is a type, and could be found in the
1700         // default schema grammar, we should return that type.
1701         // otherwise (since we would support user-defined schema grammar) we'll
1702         // use the normal way to get the decl
1703         if (declToTraverse.uri != null &&
1704                 declToTraverse.uri == SchemaSymbols.URI_SCHEMAFORSCHEMA) {
1705             if (declType == TYPEDECL_TYPE) {
1706                 Object retObj = SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(declToTraverse.localpart);
1707                 if (retObj != null)
1708                     return retObj;
1709             }
1710         }
1711 
1712         // now check whether this document can access the requsted namespace
1713         if (!currSchema.isAllowedNS(declToTraverse.uri)) {
1714             // cannot get to this schema from the one containing the requesting decl
1715             if (currSchema.needReportTNSError(declToTraverse.uri)) {
1716                 String code = declToTraverse.uri == null ? "src-resolve.4.1" : "src-resolve.4.2";
1717                 reportSchemaError(code, new Object[]{fDoc2SystemId.get(currSchema.fSchemaElement), declToTraverse.uri, declToTraverse.rawname}, elmNode);
1718             }
1719             // Recover and continue to look for the component.
1720             // return null;
1721         }
1722 
1723         // check whether there is grammar for the requested namespace
1724         SchemaGrammar sGrammar = fGrammarBucket.getGrammar(declToTraverse.uri);
1725         if (sGrammar == null) {
1726             if (needReportTNSError(declToTraverse.uri))
1727                 reportSchemaError("src-resolve", new Object[]{declToTraverse.rawname, COMP_TYPE[declType]}, elmNode);
1728             return null;
1729         }
1730 
1731         // if there is such grammar, check whether the requested component is in the grammar
1732         Object retObj = getGlobalDeclFromGrammar(sGrammar, declType, declToTraverse.localpart);
1733         String declKey = declToTraverse.uri == null? ","+declToTraverse.localpart:
1734             declToTraverse.uri+","+declToTraverse.localpart;
1735 
1736         // if the component is parsed, return it
1737         if (!fTolerateDuplicates) {
1738             if (retObj != null) {
1739                 return retObj;
1740             }
1741         }
1742         else {
1743             Object retObj2 = getGlobalDecl(declKey, declType);
1744             if (retObj2 != null) {
1745                 return retObj2;
1746             }
1747         }
1748 
1749         XSDocumentInfo schemaWithDecl = null;
1750         Element decl = null;
1751         XSDocumentInfo declDoc = null;
1752 
1753         // the component is not parsed, try to find a DOM element for it
1754         switch (declType) {
1755         case ATTRIBUTE_TYPE :
1756             decl = getElementFromMap(fUnparsedAttributeRegistry, declKey);
1757             declDoc = getDocInfoFromMap(fUnparsedAttributeRegistrySub, declKey);
1758             break;
1759         case ATTRIBUTEGROUP_TYPE :
1760             decl = getElementFromMap(fUnparsedAttributeGroupRegistry, declKey);
1761             declDoc = getDocInfoFromMap(fUnparsedAttributeGroupRegistrySub, declKey);
1762             break;
1763         case ELEMENT_TYPE :
1764             decl = getElementFromMap(fUnparsedElementRegistry, declKey);
1765             declDoc = getDocInfoFromMap(fUnparsedElementRegistrySub, declKey);
1766             break;
1767         case GROUP_TYPE :
1768             decl = getElementFromMap(fUnparsedGroupRegistry, declKey);
1769             declDoc = getDocInfoFromMap(fUnparsedGroupRegistrySub, declKey);
1770             break;
1771         case IDENTITYCONSTRAINT_TYPE :
1772             decl = getElementFromMap(fUnparsedIdentityConstraintRegistry, declKey);
1773             declDoc = getDocInfoFromMap(fUnparsedIdentityConstraintRegistrySub, declKey);
1774             break;
1775         case NOTATION_TYPE :
1776             decl = getElementFromMap(fUnparsedNotationRegistry, declKey);
1777             declDoc = getDocInfoFromMap(fUnparsedNotationRegistrySub, declKey);
1778             break;
1779         case TYPEDECL_TYPE :
1780             decl = getElementFromMap(fUnparsedTypeRegistry, declKey);
1781             declDoc = getDocInfoFromMap(fUnparsedTypeRegistrySub, declKey);
1782             break;
1783         default:
1784             reportSchemaError("Internal-Error", new Object [] {"XSDHandler asked to locate component of type " + declType + "; it does not recognize this type!"}, elmNode);
1785         }
1786 
1787         // no DOM element found, so the component can't be located
1788         if (decl == null) {
1789             if (retObj == null) {
1790                 reportSchemaError("src-resolve", new Object[]{declToTraverse.rawname, COMP_TYPE[declType]}, elmNode);
1791             }
1792             return retObj;
1793         }
1794 
1795         // get the schema doc containing the component to be parsed
1796         // it should always return non-null value, but since null-checking
1797         // comes for free, let's be safe and check again
1798         schemaWithDecl = findXSDocumentForDecl(currSchema, decl, declDoc);
1799         if (schemaWithDecl == null) {
1800             // cannot get to this schema from the one containing the requesting decl
1801             if (retObj == null) {
1802                 String code = declToTraverse.uri == null ? "src-resolve.4.1" : "src-resolve.4.2";
1803                 reportSchemaError(code, new Object[]{fDoc2SystemId.get(currSchema.fSchemaElement), declToTraverse.uri, declToTraverse.rawname}, elmNode);
1804             }
1805             return retObj;
1806         }
1807 
1808         // a component is hidden, meaning either it's traversed, or being traversed.
1809         // but we didn't find it in the grammar, so it's the latter case, and
1810         // a circular reference. error!
1811         if (DOMUtil.isHidden(decl, fHiddenNodes)) {
1812             if (retObj == null) {
1813                 String code = CIRCULAR_CODES[declType];
1814                 if (declType == TYPEDECL_TYPE) {
1815                     if (SchemaSymbols.ELT_COMPLEXTYPE.equals(DOMUtil.getLocalName(decl))) {
1816                         code = "ct-props-correct.3";
1817                     }
1818                 }
1819                 // decl must not be null if we're here...
1820                 reportSchemaError(code, new Object [] {declToTraverse.prefix+":"+declToTraverse.localpart}, elmNode);
1821             }
1822             return retObj;
1823         }
1824 
1825         return traverseGlobalDecl(declType, decl, schemaWithDecl, sGrammar);
1826     } // getGlobalDecl(XSDocumentInfo, int, QName):  Object
1827 
1828     // If we are tolerating duplicate declarations and allowing namespace growth
1829     // use the declaration from the current schema load (if it exists)
1830     protected Object getGlobalDecl(String declKey, int declType) {
1831         Object retObj = null;
1832 
1833         switch (declType) {
1834         case ATTRIBUTE_TYPE :
1835             retObj = getGlobalAttributeDecl(declKey);
1836             break;
1837         case ATTRIBUTEGROUP_TYPE :
1838             retObj = getGlobalAttributeGroupDecl(declKey);
1839             break;
1840         case ELEMENT_TYPE :
1841             retObj = getGlobalElementDecl(declKey);
1842             break;
1843         case GROUP_TYPE :
1844             retObj = getGlobalGroupDecl(declKey);
1845             break;
1846         case IDENTITYCONSTRAINT_TYPE :
1847             retObj = getIDConstraintDecl(declKey);
1848             break;
1849         case NOTATION_TYPE :
1850             retObj = getGlobalNotationDecl(declKey);
1851             break;
1852         case TYPEDECL_TYPE :
1853             retObj = getGlobalTypeDecl(declKey);
1854             break;
1855         }
1856 
1857         return retObj;
1858     }
1859 
1860     protected Object getGlobalDeclFromGrammar(SchemaGrammar sGrammar, int declType, String localpart) {
1861         Object retObj = null;
1862 
1863         switch (declType) {
1864         case ATTRIBUTE_TYPE :
1865             retObj = sGrammar.getGlobalAttributeDecl(localpart);
1866             break;
1867         case ATTRIBUTEGROUP_TYPE :
1868             retObj = sGrammar.getGlobalAttributeGroupDecl(localpart);
1869             break;
1870         case ELEMENT_TYPE :
1871             retObj = sGrammar.getGlobalElementDecl(localpart);
1872             break;
1873         case GROUP_TYPE :
1874             retObj = sGrammar.getGlobalGroupDecl(localpart);
1875             break;
1876         case IDENTITYCONSTRAINT_TYPE :
1877             retObj = sGrammar.getIDConstraintDecl(localpart);
1878             break;
1879         case NOTATION_TYPE :
1880             retObj = sGrammar.getGlobalNotationDecl(localpart);
1881             break;
1882         case TYPEDECL_TYPE :
1883             retObj = sGrammar.getGlobalTypeDecl(localpart);
1884             break;
1885         }
1886 
1887         return retObj;
1888     }
1889 
1890     protected Object getGlobalDeclFromGrammar(SchemaGrammar sGrammar, int declType, String localpart, String schemaLoc) {
1891         Object retObj = null;
1892 
1893         switch (declType) {
1894         case ATTRIBUTE_TYPE :
1895             retObj = sGrammar.getGlobalAttributeDecl(localpart, schemaLoc);
1896             break;
1897         case ATTRIBUTEGROUP_TYPE :
1898             retObj = sGrammar.getGlobalAttributeGroupDecl(localpart, schemaLoc);
1899             break;
1900         case ELEMENT_TYPE :
1901             retObj = sGrammar.getGlobalElementDecl(localpart, schemaLoc);
1902             break;
1903         case GROUP_TYPE :
1904             retObj = sGrammar.getGlobalGroupDecl(localpart, schemaLoc);
1905             break;
1906         case IDENTITYCONSTRAINT_TYPE :
1907             retObj = sGrammar.getIDConstraintDecl(localpart, schemaLoc);
1908             break;
1909         case NOTATION_TYPE :
1910             retObj = sGrammar.getGlobalNotationDecl(localpart, schemaLoc);
1911             break;
1912         case TYPEDECL_TYPE :
1913             retObj = sGrammar.getGlobalTypeDecl(localpart, schemaLoc);
1914             break;
1915         }
1916 
1917         return retObj;
1918     }
1919 
1920     protected Object traverseGlobalDecl(int declType, Element decl,
1921             XSDocumentInfo schemaDoc, SchemaGrammar grammar) {
1922         Object retObj = null;
1923 
1924         DOMUtil.setHidden(decl, fHiddenNodes);
1925         SchemaNamespaceSupport nsSupport = null;
1926         // if the parent is <redefine> use the namespace delcs for it.
1927         Element parent = DOMUtil.getParent(decl);
1928         if (DOMUtil.getLocalName(parent).equals(SchemaSymbols.ELT_REDEFINE))
1929             nsSupport = (fRedefine2NSSupport!=null) ? fRedefine2NSSupport.get(parent) : null;
1930         // back up the current SchemaNamespaceSupport, because we need to provide
1931         // a fresh one to the traverseGlobal methods.
1932         schemaDoc.backupNSSupport(nsSupport);
1933 
1934         // traverse the referenced global component
1935         switch (declType) {
1936         case TYPEDECL_TYPE :
1937             if (DOMUtil.getLocalName(decl).equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
1938                 retObj = fComplexTypeTraverser.traverseGlobal(decl, schemaDoc, grammar);
1939             }
1940             else {
1941                 retObj = fSimpleTypeTraverser.traverseGlobal(decl, schemaDoc, grammar);
1942             }
1943             break;
1944         case ATTRIBUTE_TYPE :
1945             retObj = fAttributeTraverser.traverseGlobal(decl, schemaDoc, grammar);
1946             break;
1947         case ELEMENT_TYPE :
1948             retObj = fElementTraverser.traverseGlobal(decl, schemaDoc, grammar);
1949             break;
1950         case ATTRIBUTEGROUP_TYPE :
1951             retObj = fAttributeGroupTraverser.traverseGlobal(decl, schemaDoc, grammar);
1952             break;
1953         case GROUP_TYPE :
1954             retObj = fGroupTraverser.traverseGlobal(decl, schemaDoc, grammar);
1955             break;
1956         case NOTATION_TYPE :
1957             retObj = fNotationTraverser.traverse(decl, schemaDoc, grammar);
1958             break;
1959         case IDENTITYCONSTRAINT_TYPE :
1960             // identity constraints should have been parsed already...
1961             // we should never get here
1962             break;
1963         }
1964 
1965         // restore the previous SchemaNamespaceSupport, so that the caller can get
1966         // proper namespace binding.
1967         schemaDoc.restoreNSSupport();
1968 
1969         return retObj;
1970     }
1971 
1972     public String schemaDocument2SystemId(XSDocumentInfo schemaDoc) {
1973         return fDoc2SystemId.get(schemaDoc.fSchemaElement);
1974     }
1975 
1976     // This method determines whether there is a group
1977     // (attributeGroup) which the given one has redefined by
1978     // restriction.  If so, it returns it; else it returns null.
1979     // @param type:  whether what's been redefined is an
1980     // attributeGroup or a group;
1981     // @param name:  the QName of the component doing the redefining.
1982     // @param currSchema:  schema doc in which the redefining component lives.
1983     // @return:  Object representing decl redefined if present, null
1984     // otherwise.
1985     Object getGrpOrAttrGrpRedefinedByRestriction(int type, QName name, XSDocumentInfo currSchema, Element elmNode) {
1986         String realName = name.uri != null?name.uri+","+name.localpart:
1987             ","+name.localpart;
1988         String nameToFind = null;
1989         switch (type) {
1990         case ATTRIBUTEGROUP_TYPE:
1991             nameToFind = fRedefinedRestrictedAttributeGroupRegistry.get(realName);
1992             break;
1993         case GROUP_TYPE:
1994             nameToFind = fRedefinedRestrictedGroupRegistry.get(realName);
1995             break;
1996         default:
1997             return null;
1998         }
1999         if (nameToFind == null) return null;
2000         int commaPos = nameToFind.indexOf(",");
2001         QName qNameToFind = new QName(XMLSymbols.EMPTY_STRING, nameToFind.substring(commaPos+1),
2002                 nameToFind.substring(commaPos), (commaPos == 0)? null : nameToFind.substring(0, commaPos));
2003         Object retObj = getGlobalDecl(currSchema, type, qNameToFind, elmNode);
2004         if(retObj == null) {
2005             switch (type) {
2006             case ATTRIBUTEGROUP_TYPE:
2007                 reportSchemaError("src-redefine.7.2.1", new Object []{name.localpart}, elmNode);
2008                 break;
2009             case GROUP_TYPE:
2010                 reportSchemaError("src-redefine.6.2.1", new Object []{name.localpart}, elmNode);
2011                 break;
2012             }
2013             return null;
2014         }
2015         return retObj;
2016     } // getGrpOrAttrGrpRedefinedByRestriction(int, QName, XSDocumentInfo):  Object
2017 
2018     // Since ID constraints can occur in local elements, unless we
2019     // wish to completely traverse all our DOM trees looking for ID
2020     // constraints while we're building our global name registries,
2021     // which seems terribly inefficient, we need to resolve keyrefs
2022     // after all parsing is complete.  This we can simply do by running through
2023     // fIdentityConstraintRegistry and calling traverseKeyRef on all
2024     // of the KeyRef nodes.  This unfortunately removes this knowledge
2025     // from the elementTraverser class (which must ignore keyrefs),
2026     // but there seems to be no efficient way around this...
2027     protected void resolveKeyRefs() {
2028         for (int i=0; i<fKeyrefStackPos; i++) {
2029             XSDocumentInfo keyrefSchemaDoc = fKeyrefsMapXSDocumentInfo[i];
2030             keyrefSchemaDoc.fNamespaceSupport.makeGlobal();
2031             keyrefSchemaDoc.fNamespaceSupport.setEffectiveContext( fKeyrefNamespaceContext[i] );
2032             SchemaGrammar keyrefGrammar = fGrammarBucket.getGrammar(keyrefSchemaDoc.fTargetNamespace);
2033             // need to set <keyref> to hidden before traversing it,
2034             // because it has global scope
2035                 DOMUtil.setHidden(fKeyrefs[i], fHiddenNodes);
2036             fKeyrefTraverser.traverse(fKeyrefs[i], fKeyrefElems[i], keyrefSchemaDoc, keyrefGrammar);
2037         }
2038     } // end resolveKeyRefs
2039 
2040     // an accessor method.  Just makes sure callers
2041     // who want the Identity constraint registry vaguely know what they're about.
2042     protected Map<String, Element> getIDRegistry() {
2043         return fUnparsedIdentityConstraintRegistry;
2044     }
2045     // an accessor method.
2046     protected Map<String, XSDocumentInfo> getIDRegistry_sub() {
2047         return fUnparsedIdentityConstraintRegistrySub;
2048     }
2049 
2050 
2051 
2052     // This method squirrels away <keyref> declarations--along with the element
2053     // decls and namespace bindings they might find handy.
2054     protected void storeKeyRef (Element keyrefToStore, XSDocumentInfo schemaDoc,
2055             XSElementDecl currElemDecl) {
2056         String keyrefName = DOMUtil.getAttrValue(keyrefToStore, SchemaSymbols.ATT_NAME);
2057         if (keyrefName.length() != 0) {
2058             String keyrefQName = schemaDoc.fTargetNamespace == null?
2059                     "," + keyrefName: schemaDoc.fTargetNamespace+","+keyrefName;
2060             checkForDuplicateNames(keyrefQName, IDENTITYCONSTRAINT_TYPE, fUnparsedIdentityConstraintRegistry, fUnparsedIdentityConstraintRegistrySub, keyrefToStore, schemaDoc);
2061         }
2062         // now set up all the registries we'll need...
2063 
2064         // check array sizes
2065         if (fKeyrefStackPos == fKeyrefs.length) {
2066             Element [] elemArray = new Element [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT];
2067             System.arraycopy(fKeyrefs, 0, elemArray, 0, fKeyrefStackPos);
2068             fKeyrefs = elemArray;
2069             XSElementDecl [] declArray = new XSElementDecl [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT];
2070             System.arraycopy(fKeyrefElems, 0, declArray, 0, fKeyrefStackPos);
2071             fKeyrefElems = declArray;
2072             String[][] stringArray = new String [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT][];
2073             System.arraycopy(fKeyrefNamespaceContext, 0, stringArray, 0, fKeyrefStackPos);
2074             fKeyrefNamespaceContext = stringArray;
2075 
2076             XSDocumentInfo [] xsDocumentInfo = new XSDocumentInfo [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT];
2077             System.arraycopy(fKeyrefsMapXSDocumentInfo, 0, xsDocumentInfo, 0, fKeyrefStackPos);
2078             fKeyrefsMapXSDocumentInfo = xsDocumentInfo;
2079 
2080         }
2081         fKeyrefs[fKeyrefStackPos] = keyrefToStore;
2082         fKeyrefElems[fKeyrefStackPos] = currElemDecl;
2083         fKeyrefNamespaceContext[fKeyrefStackPos] = schemaDoc.fNamespaceSupport.getEffectiveLocalContext();
2084 
2085         fKeyrefsMapXSDocumentInfo[fKeyrefStackPos++] = schemaDoc;
2086     } // storeKeyref (Element, XSDocumentInfo, XSElementDecl): void
2087 
2088 
2089     /**
2090      * resolveSchema method is responsible for resolving location of the schema (using XMLEntityResolver),
2091      * and if it was successfully resolved getting the schema Document.
2092      * @param desc
2093      * @param mustResolve
2094      * @param referElement
2095      * @return A schema Element or null.
2096      */
2097     private Element resolveSchema(XSDDescription desc, boolean mustResolve,
2098                                   Element referElement, boolean usePairs) {
2099         XMLInputSource schemaSource = null;
2100         try {
2101             Map<String, XMLSchemaLoader.LocationArray> pairs = usePairs ? fLocationPairs : Collections.emptyMap();
2102             schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityManager);
2103         }
2104         catch (IOException ex) {
2105             if (mustResolve) {
2106                 reportSchemaError("schema_reference.4",
2107                         new Object[]{desc.getLocationHints()[0]},
2108                         referElement);
2109             }
2110             else {
2111                 reportSchemaWarning("schema_reference.4",
2112                         new Object[]{desc.getLocationHints()[0]},
2113                         referElement);
2114             }
2115         }
2116         if (schemaSource instanceof DOMInputSource) {
2117             return getSchemaDocument(desc.getTargetNamespace(), (DOMInputSource) schemaSource, mustResolve, desc.getContextType(), referElement);
2118         } // DOMInputSource
2119         else if (schemaSource instanceof SAXInputSource) {
2120             return getSchemaDocument(desc.getTargetNamespace(), (SAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement);
2121         } // SAXInputSource
2122         else if (schemaSource instanceof StAXInputSource) {
2123             return getSchemaDocument(desc.getTargetNamespace(), (StAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement);
2124         } // StAXInputSource
2125         else if (schemaSource instanceof XSInputSource) {
2126             return getSchemaDocument((XSInputSource) schemaSource, desc);
2127         } // XSInputSource
2128         return getSchemaDocument(desc.getTargetNamespace(), schemaSource, mustResolve, desc.getContextType(), referElement);
2129     } // getSchema(String, String, String, boolean, short):  Document
2130 
2131     private Element resolveSchema(XMLInputSource schemaSource, XSDDescription desc,
2132             boolean mustResolve, Element referElement) {
2133 
2134         if (schemaSource instanceof DOMInputSource) {
2135             return getSchemaDocument(desc.getTargetNamespace(), (DOMInputSource) schemaSource, mustResolve, desc.getContextType(), referElement);
2136         } // DOMInputSource
2137         else if (schemaSource instanceof SAXInputSource) {
2138             return getSchemaDocument(desc.getTargetNamespace(), (SAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement);
2139         } // SAXInputSource
2140         else if (schemaSource instanceof StAXInputSource) {
2141             return getSchemaDocument(desc.getTargetNamespace(), (StAXInputSource) schemaSource, mustResolve, desc.getContextType(), referElement);
2142         } // StAXInputSource
2143         else if (schemaSource instanceof XSInputSource) {
2144             return getSchemaDocument((XSInputSource) schemaSource, desc);
2145         } // XSInputSource
2146         return getSchemaDocument(desc.getTargetNamespace(), schemaSource, mustResolve, desc.getContextType(), referElement);
2147     }
2148 
2149     private XMLInputSource resolveSchemaSource(XSDDescription desc, boolean mustResolve,
2150             Element referElement, boolean usePairs) {
2151 
2152         XMLInputSource schemaSource = null;
2153         try {
2154             Map<String, XMLSchemaLoader.LocationArray> pairs = usePairs ? fLocationPairs : Collections.emptyMap();
2155             schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityManager);
2156         }
2157         catch (IOException ex) {
2158             if (mustResolve) {
2159                 reportSchemaError("schema_reference.4",
2160                         new Object[]{desc.getLocationHints()[0]},
2161                         referElement);
2162             }
2163             else {
2164                 reportSchemaWarning("schema_reference.4",
2165                         new Object[]{desc.getLocationHints()[0]},
2166                         referElement);
2167             }
2168         }
2169 
2170         return schemaSource;
2171     }
2172 
2173     /**
2174      * getSchemaDocument method uses XMLInputSource to parse a schema document.
2175      * @param schemaNamespace
2176      * @param schemaSource
2177      * @param mustResolve
2178      * @param referType
2179      * @param referElement
2180      * @return A schema Element.
2181      */
2182     private Element getSchemaDocument(String schemaNamespace, XMLInputSource schemaSource,
2183             boolean mustResolve, short referType, Element referElement) {
2184 
2185         boolean hasInput = true;
2186         IOException exception = null;
2187         // contents of this method will depend on the system we adopt for entity resolution--i.e., XMLEntityHandler, EntityHandler, etc.
2188         Element schemaElement = null;
2189         try {
2190             // when the system id and byte stream and character stream
2191             // of the input source are all null, it's
2192             // impossible to find the schema document. so we skip in
2193             // this case. otherwise we'll receive some NPE or
2194             // file not found errors. but schemaHint=="" is perfectly
2195             // legal for import.
2196             if (schemaSource != null &&
2197                     (schemaSource.getSystemId() != null ||
2198                             schemaSource.getByteStream() != null ||
2199                             schemaSource.getCharacterStream() != null)) {
2200 
2201                 // When the system id of the input source is used, first try to
2202                 // expand it, and check whether the same document has been
2203                 // parsed before. If so, return the document corresponding to
2204                 // that system id.
2205                 XSDKey key = null;
2206                 String schemaId = null;
2207                 if (referType != XSDDescription.CONTEXT_PREPARSE){
2208                     schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false);
2209                     key = new XSDKey(schemaId, referType, schemaNamespace);
2210                     if((schemaElement = fTraversed.get(key)) != null) {
2211                         fLastSchemaWasDuplicate = true;
2212                         return schemaElement;
2213                     }
2214                     if ((!schemaSource.isCreatedByResolver()) &&
2215                             (referType == XSDDescription.CONTEXT_IMPORT || referType == XSDDescription.CONTEXT_INCLUDE
2216                             || referType == XSDDescription.CONTEXT_REDEFINE)) {
2217                         String accessError = SecuritySupport.checkAccess(schemaId, fAccessExternalSchema, Constants.ACCESS_EXTERNAL_ALL);
2218                         if (accessError != null) {
2219                             reportSchemaFatalError("schema_reference.access",
2220                                     new Object[] { SecuritySupport.sanitizePath(schemaId), accessError },
2221                                     referElement);
2222                         }
2223                     }
2224                 }
2225 
2226                 fSchemaParser.parse(schemaSource);
2227                 Document schemaDocument = fSchemaParser.getDocument();
2228                 schemaElement = schemaDocument != null ? DOMUtil.getRoot(schemaDocument) : null;
2229                 return getSchemaDocument0(key, schemaId, schemaElement);
2230             }
2231             else {
2232                 hasInput = false;
2233             }
2234         }
2235         catch (IOException ex) {
2236             exception = ex;
2237         }
2238         return getSchemaDocument1(mustResolve, hasInput, schemaSource, referElement, exception);
2239     } // getSchemaDocument(String, XMLInputSource, boolean, short, Element): Element
2240 
2241     /**
2242      * getSchemaDocument method uses SAXInputSource to parse a schema document.
2243      * @param schemaNamespace
2244      * @param schemaSource
2245      * @param mustResolve
2246      * @param referType
2247      * @param referElement
2248      * @return A schema Element.
2249      */
2250     private Element getSchemaDocument(String schemaNamespace, SAXInputSource schemaSource,
2251             boolean mustResolve, short referType, Element referElement) {
2252         XMLReader parser = schemaSource.getXMLReader();
2253         InputSource inputSource = schemaSource.getInputSource();
2254         boolean hasInput = true;
2255         IOException exception = null;
2256         Element schemaElement = null;
2257         try {
2258             if (inputSource != null &&
2259                     (inputSource.getSystemId() != null ||
2260                      inputSource.getByteStream() != null ||
2261                      inputSource.getCharacterStream() != null)) {
2262 
2263                 // check whether the same document has been parsed before.
2264                 // If so, return the document corresponding to that system id.
2265                 XSDKey key = null;
2266                 String schemaId = null;
2267                 if (referType != XSDDescription.CONTEXT_PREPARSE) {
2268                     schemaId = XMLEntityManager.expandSystemId(inputSource.getSystemId(),
2269                             schemaSource.getBaseSystemId(), false);
2270                     key = new XSDKey(schemaId, referType, schemaNamespace);
2271                     if ((schemaElement = fTraversed.get(key)) != null) {
2272                         fLastSchemaWasDuplicate = true;
2273                         return schemaElement;
2274                     }
2275                 }
2276 
2277                 boolean namespacePrefixes = false;
2278                 if (parser != null) {
2279                     try {
2280                         namespacePrefixes = parser.getFeature(NAMESPACE_PREFIXES);
2281                     }
2282                     catch (SAXException se) {}
2283                 }
2284                 else {
2285                     parser = JdkXmlUtils.getXMLReader(fOverrideDefaultParser,
2286                             fSecurityManager.isSecureProcessing());
2287 
2288                     try {
2289                         parser.setFeature(NAMESPACE_PREFIXES, true);
2290                         namespacePrefixes = true;
2291                         // If this is a Xerces SAX parser set the security manager if there is one
2292                         if (parser instanceof SAXParser) {
2293                             if (fSecurityManager != null) {
2294                                 parser.setProperty(SECURITY_MANAGER, fSecurityManager);
2295                             }
2296                         }
2297                     }
2298                     catch (SAXException se) {}
2299 
2300                     try {
2301                         parser.setProperty(XMLConstants.ACCESS_EXTERNAL_DTD, fAccessExternalDTD);
2302                     } catch (SAXNotRecognizedException exc) {
2303                         XMLSecurityManager.printWarning(parser.getClass().getName(),
2304                                 XMLConstants.ACCESS_EXTERNAL_DTD, exc);
2305                     }
2306                 }
2307                 // If XML names and Namespace URIs are already internalized we
2308                 // can avoid running them through the SymbolTable.
2309                 boolean stringsInternalized = false;
2310                 try {
2311                     stringsInternalized = parser.getFeature(STRING_INTERNING);
2312                 }
2313                 catch (SAXException exc) {
2314                     // The feature isn't recognized or getting it is not supported.
2315                     // In either case, assume that strings are not internalized.
2316                 }
2317                 if (fXSContentHandler == null) {
2318                     fXSContentHandler = new SchemaContentHandler();
2319                 }
2320                 fXSContentHandler.reset(fSchemaParser, fSymbolTable,
2321                         namespacePrefixes, stringsInternalized);
2322                 parser.setContentHandler(fXSContentHandler);
2323                 parser.setErrorHandler(fErrorReporter.getSAXErrorHandler());
2324 
2325                 parser.parse(inputSource);
2326                 // Disconnect the schema loader and other objects from the XMLReader
2327                 try {
2328                     parser.setContentHandler(null);
2329                     parser.setErrorHandler(null);
2330                 }
2331                 // Ignore any exceptions thrown by the XMLReader. Old versions of SAX
2332                 // required an XMLReader to throw a NullPointerException if an attempt
2333                 // to set a handler to null was made.
2334                 catch (Exception e) {}
2335 
2336                 Document schemaDocument = fXSContentHandler.getDocument();
2337                 schemaElement = schemaDocument != null ? DOMUtil.getRoot(schemaDocument) : null;
2338                 return getSchemaDocument0(key, schemaId, schemaElement);
2339             }
2340             else {
2341                 hasInput = false;
2342             }
2343         }
2344         catch (SAXParseException spe) {
2345             throw SAX2XNIUtil.createXMLParseException0(spe);
2346         }
2347         catch (SAXException se) {
2348             throw SAX2XNIUtil.createXNIException0(se);
2349         }
2350         catch (IOException ioe) {
2351             exception = ioe;
2352         }
2353         return getSchemaDocument1(mustResolve, hasInput, schemaSource, referElement, exception);
2354     } // getSchemaDocument(String, SAXInputSource, boolean, short, Element): Element
2355 
2356     /**
2357      * getSchemaDocument method uses DOMInputSource to parse a schema document.
2358      * @param schemaNamespace
2359      * @param schemaSource
2360      * @param mustResolve
2361      * @param referType
2362      * @param referElement
2363      * @return A schema Element.
2364      */
2365     private Element getSchemaDocument(String schemaNamespace, DOMInputSource schemaSource,
2366             boolean mustResolve, short referType, Element referElement) {
2367         boolean hasInput = true;
2368         IOException exception = null;
2369         Element schemaElement = null;
2370         Element schemaRootElement = null;
2371 
2372         final Node node = schemaSource.getNode();
2373         short nodeType = -1;
2374         if (node != null) {
2375             nodeType = node.getNodeType();
2376             if (nodeType == Node.DOCUMENT_NODE) {
2377                 schemaRootElement = DOMUtil.getRoot((Document) node);
2378             }
2379             else if (nodeType == Node.ELEMENT_NODE) {
2380                 schemaRootElement = (Element) node;
2381             }
2382         }
2383 
2384         try {
2385             if (schemaRootElement != null) {
2386                 // check whether the same document has been parsed before.
2387                 // If so, return the document corresponding to that system id.
2388                 XSDKey key = null;
2389                 String schemaId = null;
2390                 if (referType != XSDDescription.CONTEXT_PREPARSE) {
2391                     schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false);
2392                     boolean isDocument = (nodeType == Node.DOCUMENT_NODE);
2393                     if (!isDocument) {
2394                         Node parent = schemaRootElement.getParentNode();
2395                         if (parent != null) {
2396                             isDocument = (parent.getNodeType() == Node.DOCUMENT_NODE);
2397                         }
2398                     }
2399                     if (isDocument) {
2400                         key = new XSDKey(schemaId, referType, schemaNamespace);
2401                         if ((schemaElement = fTraversed.get(key)) != null) {
2402                             fLastSchemaWasDuplicate = true;
2403                             return schemaElement;
2404                         }
2405                     }
2406                 }
2407 
2408                 schemaElement = schemaRootElement;
2409                 return getSchemaDocument0(key, schemaId, schemaElement);
2410             }
2411             else {
2412                 hasInput = false;
2413             }
2414         }
2415         catch (IOException ioe) {
2416             exception = ioe;
2417         }
2418         return getSchemaDocument1(mustResolve, hasInput, schemaSource, referElement, exception);
2419     } // getSchemaDocument(String, DOMInputSource, boolean, short, Element): Element
2420 
2421     /**
2422      * getSchemaDocument method uses StAXInputSource to parse a schema document.
2423      * @param schemaNamespace
2424      * @param schemaSource
2425      * @param mustResolve
2426      * @param referType
2427      * @param referElement
2428      * @return A schema Element.
2429      */
2430     private Element getSchemaDocument(String schemaNamespace, StAXInputSource schemaSource,
2431             boolean mustResolve, short referType, Element referElement) {
2432         IOException exception = null;
2433         Element schemaElement = null;
2434         try {
2435             final boolean consumeRemainingContent = schemaSource.shouldConsumeRemainingContent();
2436             final XMLStreamReader streamReader = schemaSource.getXMLStreamReader();
2437             final XMLEventReader eventReader = schemaSource.getXMLEventReader();
2438 
2439             // check whether the same document has been parsed before.
2440             // If so, return the document corresponding to that system id.
2441             XSDKey key = null;
2442             String schemaId = null;
2443             if (referType != XSDDescription.CONTEXT_PREPARSE) {
2444                 schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false);
2445                 boolean isDocument = consumeRemainingContent;
2446                 if (!isDocument) {
2447                     if (streamReader != null) {
2448                         isDocument = (streamReader.getEventType() == XMLStreamReader.START_DOCUMENT);
2449                     }
2450                     else {
2451                         isDocument = eventReader.peek().isStartDocument();
2452                     }
2453                 }
2454                 if (isDocument) {
2455                     key = new XSDKey(schemaId, referType, schemaNamespace);
2456                     if ((schemaElement = fTraversed.get(key)) != null) {
2457                         fLastSchemaWasDuplicate = true;
2458                         return schemaElement;
2459                     }
2460                 }
2461             }
2462 
2463             if (fStAXSchemaParser == null) {
2464                 fStAXSchemaParser = new StAXSchemaParser();
2465             }
2466             fStAXSchemaParser.reset(fSchemaParser, fSymbolTable);
2467 
2468             if (streamReader != null) {
2469                 fStAXSchemaParser.parse(streamReader);
2470                 if (consumeRemainingContent) {
2471                     while (streamReader.hasNext()) {
2472                         streamReader.next();
2473                     }
2474                 }
2475             }
2476             else {
2477                 fStAXSchemaParser.parse(eventReader);
2478                 if (consumeRemainingContent) {
2479                     while (eventReader.hasNext()) {
2480                         eventReader.nextEvent();
2481                     }
2482                 }
2483             }
2484             Document schemaDocument = fStAXSchemaParser.getDocument();
2485             schemaElement = schemaDocument != null ? DOMUtil.getRoot(schemaDocument) : null;
2486             return getSchemaDocument0(key, schemaId, schemaElement);
2487         }
2488         catch (XMLStreamException e) {
2489             Throwable t = e.getNestedException();
2490             if (t instanceof IOException) {
2491                 exception = (IOException) t;
2492             }
2493             else {
2494                 StAXLocationWrapper slw = new StAXLocationWrapper();
2495                 slw.setLocation(e.getLocation());
2496                 throw new XMLParseException(slw, e.getMessage(), e);
2497             }
2498         }
2499         catch (IOException e) {
2500             exception = e;
2501         }
2502         return getSchemaDocument1(mustResolve, true, schemaSource, referElement, exception);
2503     } // getSchemaDocument(String, StAXInputSource, boolean, short, Element): Element
2504 
2505     /**
2506      * Code shared between the various getSchemaDocument() methods which
2507      * stores mapping information for the document.
2508      */
2509     private Element getSchemaDocument0(XSDKey key, String schemaId, Element schemaElement) {
2510         // now we need to store the mapping information from system id
2511         // to the document. also from the document to the system id.
2512         if (key != null) {
2513             fTraversed.put(key, schemaElement);
2514         }
2515         if (schemaId != null) {
2516             fDoc2SystemId.put(schemaElement, schemaId);
2517         }
2518         fLastSchemaWasDuplicate = false;
2519         return schemaElement;
2520     } // getSchemaDocument0(XSDKey, String, Element): Element
2521 
2522     /**
2523      * Error handling code shared between the various getSchemaDocument() methods.
2524      */
2525     private Element getSchemaDocument1(boolean mustResolve, boolean hasInput,
2526             XMLInputSource schemaSource, Element referElement, IOException ioe) {
2527         // either an error occured (exception), or empty input source was
2528         // returned, we need to report an error or a warning
2529         if (mustResolve) {
2530             if (hasInput) {
2531                 reportSchemaError("schema_reference.4",
2532                         new Object[]{schemaSource.getSystemId()},
2533                         referElement, ioe);
2534             }
2535             else {
2536                 reportSchemaError("schema_reference.4",
2537                         new Object[]{schemaSource == null ? "" : schemaSource.getSystemId()},
2538                         referElement, ioe);
2539             }
2540         }
2541         else if (hasInput) {
2542             reportSchemaWarning("schema_reference.4",
2543                     new Object[]{schemaSource.getSystemId()},
2544                     referElement, ioe);
2545         }
2546 
2547         fLastSchemaWasDuplicate = false;
2548         return null;
2549     } // getSchemaDocument1(boolean, boolean, XMLInputSource, Element): Element
2550 
2551     /**
2552      * getSchemaDocument method uses XMLInputSource to parse a schema document.
2553      * @param schemaNamespace
2554      * @param schemaSource
2555      * @param mustResolve
2556      * @param referType
2557      * @param referElement
2558      * @return A schema Element.
2559      */
2560     private Element getSchemaDocument(XSInputSource schemaSource, XSDDescription desc) {
2561 
2562         SchemaGrammar[] grammars = schemaSource.getGrammars();
2563         short referType = desc.getContextType();
2564 
2565         if (grammars != null && grammars.length > 0) {
2566            List<SchemaGrammar> expandedGrammars = expandGrammars(grammars);
2567             // check for existing grammars in our bucket
2568             // and if there exist any, and namespace growth is
2569             // not enabled - we do nothing
2570             if (fNamespaceGrowth || !existingGrammars(expandedGrammars)) {
2571                 addGrammars(expandedGrammars);
2572                 if (referType == XSDDescription.CONTEXT_PREPARSE) {
2573                     desc.setTargetNamespace(grammars[0].getTargetNamespace());
2574                 }
2575             }
2576         }
2577         else {
2578             XSObject[] components = schemaSource.getComponents();
2579             if (components != null && components.length > 0) {
2580                 Map<String, List<String>> importDependencies = new HashMap<>();
2581                 List<XSObject> expandedComponents = expandComponents(components, importDependencies);
2582                 if (fNamespaceGrowth || canAddComponents(expandedComponents)) {
2583                     addGlobalComponents(expandedComponents, importDependencies);
2584                     if (referType == XSDDescription.CONTEXT_PREPARSE) {
2585                         desc.setTargetNamespace(components[0].getNamespace());
2586                     }
2587                 }
2588             }
2589         }
2590         return null;
2591     } // getSchemaDocument(String, XSInputSource, boolean, short, Element): Element
2592 
2593     private List<SchemaGrammar> expandGrammars(SchemaGrammar[] grammars) {
2594         List<SchemaGrammar> currGrammars = new ArrayList<>();
2595 
2596         for (int i=0; i<grammars.length; i++) {
2597             if (!currGrammars.contains(grammars[i])) {
2598                 currGrammars.add(grammars[i]);
2599             }
2600         }
2601 
2602         // for all (recursively) imported grammars
2603         SchemaGrammar sg1, sg2;
2604         List<SchemaGrammar> gs;
2605         for (int i = 0; i < currGrammars.size(); i++) {
2606             // get the grammar
2607             sg1 = currGrammars.get(i);
2608             // we need to add grammars imported by sg1 too
2609             gs = sg1.getImportedGrammars();
2610             // for all grammars imported by sg2, but not in the vector
2611             // we add them to the vector
2612             if (gs == null) {
2613                 continue;
2614             }
2615 
2616             for (int j = gs.size() - 1; j >= 0; j--) {
2617                 sg2 = gs.get(j);
2618                 if (!currGrammars.contains(sg2)) {
2619                     currGrammars.add(sg2);
2620                 }
2621             }
2622         }
2623 
2624         return currGrammars;
2625     }
2626 
2627     private boolean existingGrammars(List<SchemaGrammar> grammars) {
2628         int length = grammars.size();
2629         final XSDDescription desc = new XSDDescription();
2630 
2631         for (int i=0; i < length; i++) {
2632             final SchemaGrammar sg1 = grammars.get(i);
2633             desc.setNamespace(sg1.getTargetNamespace());
2634 
2635             final SchemaGrammar sg2 = findGrammar(desc, false);
2636             if (sg2 != null) {
2637                 return true;
2638             }
2639         }
2640 
2641         return false;
2642     }
2643 
2644     private boolean canAddComponents(List<XSObject> components) {
2645         final int size = components.size();
2646         final XSDDescription desc = new XSDDescription();
2647         for (int i=0; i<size; i++) {
2648             XSObject component = components.get(i);
2649             if (!canAddComponent(component, desc)) {
2650                 return false;
2651             }
2652         }
2653         return true;
2654     }
2655 
2656     private boolean canAddComponent(XSObject component, XSDDescription desc) {
2657         desc.setNamespace(component.getNamespace());
2658 
2659         final SchemaGrammar sg = findGrammar(desc, false);
2660         if (sg == null) {
2661             return true;
2662         }
2663         else if (sg.isImmutable()) {
2664             return false;
2665         }
2666 
2667         short componentType = component.getType();
2668         final String name = component.getName();
2669 
2670         switch (componentType) {
2671         case XSConstants.TYPE_DEFINITION :
2672             if (sg.getGlobalTypeDecl(name) == component) {
2673                 return true;
2674             }
2675             break;
2676         case XSConstants.ATTRIBUTE_DECLARATION :
2677             if (sg.getGlobalAttributeDecl(name) == component) {
2678                 return true;
2679             }
2680             break;
2681         case XSConstants.ATTRIBUTE_GROUP :
2682             if (sg.getGlobalAttributeDecl(name) == component) {
2683                 return true;
2684             }
2685             break;
2686         case XSConstants.ELEMENT_DECLARATION :
2687             if (sg.getGlobalElementDecl(name) == component) {
2688                 return true;
2689             }
2690             break;
2691         case XSConstants.MODEL_GROUP_DEFINITION :
2692             if (sg.getGlobalGroupDecl(name) == component) {
2693                 return true;
2694             }
2695             break;
2696         case XSConstants.NOTATION_DECLARATION :
2697             if (sg.getGlobalNotationDecl(name) == component) {
2698                 return true;
2699             }
2700             break;
2701         case XSConstants.IDENTITY_CONSTRAINT :
2702         case XSConstants.ATTRIBUTE_USE :
2703         default :
2704             return true;
2705         }
2706         return false;
2707     }
2708 
2709     private void addGrammars(List<SchemaGrammar> grammars) {
2710         int length = grammars.size();
2711         XSDDescription desc = new XSDDescription();
2712 
2713         for (int i=0; i < length; i++) {
2714             final SchemaGrammar sg1 = grammars.get(i);
2715             desc.setNamespace(sg1.getTargetNamespace());
2716 
2717             final SchemaGrammar sg2 = findGrammar(desc, fNamespaceGrowth);
2718             if (sg1 != sg2) {
2719                 addGrammarComponents(sg1, sg2);
2720             }
2721         }
2722     }
2723 
2724     private void addGrammarComponents(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) {
2725         if (dstGrammar == null) {
2726             createGrammarFrom(srcGrammar);
2727             return;
2728         }
2729 
2730         SchemaGrammar tmpGrammar = dstGrammar;
2731         if (tmpGrammar.isImmutable()) {
2732             tmpGrammar = createGrammarFrom(dstGrammar);
2733         }
2734 
2735         // add any new locations
2736         addNewGrammarLocations(srcGrammar, tmpGrammar);
2737 
2738         // add any new imported grammars
2739         addNewImportedGrammars(srcGrammar, tmpGrammar);
2740 
2741         // add any new global components
2742         addNewGrammarComponents(srcGrammar, tmpGrammar);
2743     }
2744 
2745     private SchemaGrammar createGrammarFrom(SchemaGrammar grammar) {
2746         SchemaGrammar newGrammar = new SchemaGrammar(grammar);
2747         fGrammarBucket.putGrammar(newGrammar);
2748         // update all the grammars in the bucket to point to the new grammar.
2749         updateImportListWith(newGrammar);
2750         // update import list of the new grammar
2751         updateImportListFor(newGrammar);
2752         return newGrammar;
2753     }
2754 
2755     private void addNewGrammarLocations(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) {
2756         final StringList locations = srcGrammar.getDocumentLocations();
2757         final int locSize = locations.size();
2758         final StringList locations2 = dstGrammar.getDocumentLocations();
2759 
2760         for (int i=0; i<locSize; i++) {
2761             String loc = locations.item(i);
2762             if (!locations2.contains(loc)) {
2763                 dstGrammar.addDocument(null, loc);
2764             }
2765         }
2766     }
2767 
2768     @SuppressWarnings("unchecked")
2769     private void addNewImportedGrammars(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) {
2770         final ArrayList<SchemaGrammar> src = (ArrayList<SchemaGrammar>)srcGrammar.getImportedGrammars();
2771         if (src != null) {
2772             ArrayList<SchemaGrammar> dst = (ArrayList<SchemaGrammar>)dstGrammar.getImportedGrammars();
2773             if (dst == null) {
2774                 dst = new ArrayList<>();
2775                 dstGrammar.setImportedGrammars(dst);
2776             }
2777             for (SchemaGrammar sg :src) {
2778                 // Can't use the object from the source import list directly.
2779                 // It's possible there is already a grammar with the same
2780                 // namespace in the bucket but a different object.
2781                 // This can happen if the bucket has grammar A1, and we try
2782                 // to add B and A2, where A2 imports B. When B is added, we
2783                 // create a new object B' and store it in the bucket. Then we
2784                 // try to merge A2 and A1. We can't use B. Need to get B' from
2785                 // the bucket and store it in A's import list.
2786                 SchemaGrammar sg1 = fGrammarBucket.getGrammar(sg.getTargetNamespace());
2787                 if (sg1 != null) {
2788                     sg = sg1;
2789                 }
2790                 if (!containedImportedGrammar(dst, sg)) {
2791                     dst.add(sg);
2792                 }
2793             }
2794         }
2795     }
2796 
2797     private void updateImportList(List<SchemaGrammar> importedSrc, List<SchemaGrammar> importedDst)
2798     {
2799         final int size = importedSrc.size();
2800 
2801         for (int i=0; i<size; i++) {
2802             final SchemaGrammar sg =  importedSrc.get(i);
2803             if (!containedImportedGrammar(importedDst, sg)) {
2804                 importedDst.add(sg);
2805             }
2806         }
2807     }
2808 
2809     private void addNewGrammarComponents(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) {
2810         dstGrammar.resetComponents();
2811         addGlobalElementDecls(srcGrammar, dstGrammar);
2812         addGlobalAttributeDecls(srcGrammar, dstGrammar);
2813         addGlobalAttributeGroupDecls(srcGrammar, dstGrammar);
2814         addGlobalGroupDecls(srcGrammar, dstGrammar);
2815         addGlobalTypeDecls(srcGrammar, dstGrammar);
2816         addGlobalNotationDecls(srcGrammar, dstGrammar);
2817     }
2818 
2819     private void addGlobalElementDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) {
2820         XSNamedMap components = srcGrammar.getComponents(XSConstants.ELEMENT_DECLARATION);
2821         int len = components.getLength();
2822         XSElementDecl srcDecl, dstDecl;
2823 
2824         // add global components
2825         for (int i=0; i<len; i++) {
2826             srcDecl = (XSElementDecl) components.item(i);
2827             dstDecl = dstGrammar.getGlobalElementDecl(srcDecl.getName());
2828             if (dstDecl == null) {
2829                 dstGrammar.addGlobalElementDecl(srcDecl);
2830             }
2831             else if (dstDecl != srcDecl){
2832                 // TODO: if not tolerating duplicate, generate an error message
2833             }
2834         }
2835 
2836         // add any extended (duplicate) global components
2837         ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.ELEMENT_DECLARATION);
2838         len = componentsExt.getLength();
2839 
2840         for (int i=0; i<len; i+= 2) {
2841             final String key = (String) componentsExt.item(i);
2842             final int index = key.indexOf(',');
2843             final String location = key.substring(0, index);
2844             final String name = key.substring(index + 1, key.length());
2845 
2846             srcDecl = (XSElementDecl)componentsExt.item(i+1);
2847             dstDecl = dstGrammar.getGlobalElementDecl(name, location);
2848             if ( dstDecl == null) {
2849                 dstGrammar.addGlobalElementDecl(srcDecl, location);
2850             }
2851             else if (dstDecl != srcDecl){
2852                 // TODO: if not tolerating duplicate, generate an error message
2853             }
2854         }
2855     }
2856 
2857     private void addGlobalAttributeDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) {
2858         XSNamedMap components = srcGrammar.getComponents(XSConstants.ATTRIBUTE_DECLARATION);
2859         int len = components.getLength();
2860         XSAttributeDecl srcDecl, dstDecl;
2861 
2862         // add global components
2863         for (int i=0; i<len; i++) {
2864             srcDecl = (XSAttributeDecl) components.item(i);
2865             dstDecl = dstGrammar.getGlobalAttributeDecl(srcDecl.getName());
2866             if (dstDecl == null) {
2867                 dstGrammar.addGlobalAttributeDecl(srcDecl);
2868             }
2869             else if (dstDecl != srcDecl && !fTolerateDuplicates) {
2870                 reportSharingError(srcDecl.getNamespace(), srcDecl.getName());
2871             }
2872         }
2873 
2874         // add any extended (duplicate) global components
2875         ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.ATTRIBUTE_DECLARATION);
2876         len = componentsExt.getLength();
2877 
2878         for (int i=0; i<len; i+= 2) {
2879             final String key = (String) componentsExt.item(i);
2880             final int index = key.indexOf(',');
2881             final String location = key.substring(0, index);
2882             final String name = key.substring(index + 1, key.length());
2883 
2884             srcDecl = (XSAttributeDecl)componentsExt.item(i+1);
2885             dstDecl = dstGrammar.getGlobalAttributeDecl(name, location);
2886             if (dstDecl == null) {
2887                 dstGrammar.addGlobalAttributeDecl(srcDecl, location);
2888             }
2889             // REVISIT - do we report an error?
2890             else if (dstDecl != srcDecl) {
2891             }
2892         }
2893     }
2894 
2895     private void addGlobalAttributeGroupDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) {
2896         XSNamedMap components = srcGrammar.getComponents(XSConstants.ATTRIBUTE_GROUP);
2897         int len = components.getLength();
2898         XSAttributeGroupDecl srcDecl, dstDecl;
2899 
2900         // add global components
2901         for (int i=0; i<len; i++) {
2902             srcDecl = (XSAttributeGroupDecl) components.item(i);
2903             dstDecl = dstGrammar.getGlobalAttributeGroupDecl(srcDecl.getName());
2904             if (dstDecl == null) {
2905                 dstGrammar.addGlobalAttributeGroupDecl(srcDecl);
2906             }
2907             else if (dstDecl != srcDecl && !fTolerateDuplicates) {
2908                 reportSharingError(srcDecl.getNamespace(), srcDecl.getName());
2909             }
2910         }
2911 
2912         // add any extended (duplicate) global components
2913         ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.ATTRIBUTE_GROUP);
2914         len = componentsExt.getLength();
2915 
2916         for (int i=0; i<len; i+= 2) {
2917             final String key = (String) componentsExt.item(i);
2918             final int index = key.indexOf(',');
2919             final String location = key.substring(0, index);
2920             final String name = key.substring(index + 1, key.length());
2921 
2922             srcDecl = (XSAttributeGroupDecl)componentsExt.item(i+1);
2923             dstDecl = dstGrammar.getGlobalAttributeGroupDecl(name, location);
2924             if (dstDecl == null) {
2925                 dstGrammar.addGlobalAttributeGroupDecl(srcDecl, location);
2926             }
2927             // REVISIT - do we report an error?
2928             else if (dstDecl != srcDecl) {
2929             }
2930         }
2931     }
2932 
2933     private void addGlobalNotationDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) {
2934         XSNamedMap components = srcGrammar.getComponents(XSConstants.NOTATION_DECLARATION);
2935         int len = components.getLength();
2936         XSNotationDecl srcDecl, dstDecl;
2937 
2938         // add global components
2939         for (int i=0; i<len; i++) {
2940             srcDecl = (XSNotationDecl) components.item(i);
2941             dstDecl = dstGrammar.getGlobalNotationDecl(srcDecl.getName());
2942             if (dstDecl == null) {
2943                 dstGrammar.addGlobalNotationDecl(srcDecl);
2944             }
2945             else if (dstDecl != srcDecl && !fTolerateDuplicates) {
2946                 reportSharingError(srcDecl.getNamespace(), srcDecl.getName());
2947             }
2948         }
2949 
2950         // add any extended (duplicate) global components
2951         ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.NOTATION_DECLARATION);
2952         len = componentsExt.getLength();
2953 
2954         for (int i=0; i<len; i+= 2) {
2955             final String key = (String) componentsExt.item(i);
2956             final int index = key.indexOf(',');
2957             final String location = key.substring(0, index);
2958             final String name = key.substring(index + 1, key.length());
2959 
2960             srcDecl = (XSNotationDecl)componentsExt.item(i+1);
2961             dstDecl = dstGrammar.getGlobalNotationDecl(name, location);
2962             if (dstDecl == null) {
2963                 dstGrammar.addGlobalNotationDecl(srcDecl, location);
2964             }
2965             // REVISIT - do we report an error?
2966             else if (dstDecl != srcDecl) {
2967             }
2968         }
2969     }
2970 
2971     private void addGlobalGroupDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) {
2972         XSNamedMap components = srcGrammar.getComponents(XSConstants.MODEL_GROUP_DEFINITION);
2973         int len = components.getLength();
2974         XSGroupDecl srcDecl, dstDecl;
2975 
2976         // add global components
2977         for (int i=0; i<len; i++) {
2978             srcDecl = (XSGroupDecl) components.item(i);
2979             dstDecl = dstGrammar.getGlobalGroupDecl(srcDecl.getName());
2980             if (dstDecl == null) {
2981                 dstGrammar.addGlobalGroupDecl(srcDecl);
2982             }
2983             else if (srcDecl != dstDecl && !fTolerateDuplicates) {
2984                 reportSharingError(srcDecl.getNamespace(), srcDecl.getName());
2985             }
2986         }
2987 
2988         // add any extended (duplicate) global components
2989         ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.MODEL_GROUP_DEFINITION);
2990         len = componentsExt.getLength();
2991 
2992         for (int i=0; i<len; i+= 2) {
2993             final String key = (String) componentsExt.item(i);
2994             final int index = key.indexOf(',');
2995             final String location = key.substring(0, index);
2996             final String name = key.substring(index + 1, key.length());
2997 
2998             srcDecl = (XSGroupDecl)componentsExt.item(i+1);
2999             dstDecl = dstGrammar.getGlobalGroupDecl(name, location);
3000             if (dstDecl == null) {
3001                 dstGrammar.addGlobalGroupDecl(srcDecl, location);
3002             }
3003             // REVIST - do we report an error?
3004             else if (dstDecl != srcDecl) {
3005             }
3006         }
3007     }
3008 
3009     private void addGlobalTypeDecls(SchemaGrammar srcGrammar, SchemaGrammar dstGrammar) {
3010         XSNamedMap components = srcGrammar.getComponents(XSConstants.TYPE_DEFINITION);
3011         int len = components.getLength();
3012         XSTypeDefinition srcDecl, dstDecl;
3013 
3014         // add global components
3015         for (int i=0; i<len; i++) {
3016             srcDecl = (XSTypeDefinition) components.item(i);
3017             dstDecl = dstGrammar.getGlobalTypeDecl(srcDecl.getName());
3018             if (dstDecl == null) {
3019                 dstGrammar.addGlobalTypeDecl(srcDecl);
3020             }
3021             else if (dstDecl != srcDecl && !fTolerateDuplicates) {
3022                 reportSharingError(srcDecl.getNamespace(), srcDecl.getName());
3023             }
3024         }
3025 
3026         // add any extended (duplicate) global components
3027         ObjectList componentsExt = srcGrammar.getComponentsExt(XSConstants.TYPE_DEFINITION);
3028         len = componentsExt.getLength();
3029 
3030         for (int i=0; i<len; i+= 2) {
3031             final String key = (String) componentsExt.item(i);
3032             final int index = key.indexOf(',');
3033             final String location = key.substring(0, index);
3034             final String name = key.substring(index + 1, key.length());
3035 
3036             srcDecl = (XSTypeDefinition)componentsExt.item(i+1);
3037             dstDecl = dstGrammar.getGlobalTypeDecl(name, location);
3038             if (dstDecl == null) {
3039                 dstGrammar.addGlobalTypeDecl(srcDecl, location);
3040             }
3041             // REVISIT - do we report an error?
3042             else if (dstDecl != srcDecl) {
3043             }
3044         }
3045     }
3046 
3047     private List<XSObject> expandComponents(XSObject[] components, Map<String, List<String>> dependencies) {
3048         List<XSObject> newComponents = new ArrayList<>();
3049 
3050         for (int i=0; i<components.length; i++) {
3051             if (!newComponents.contains(components[i])) {
3052                 newComponents.add(components[i]);
3053             }
3054         }
3055 
3056         for (int i=0; i<newComponents.size(); i++) {
3057             final XSObject component = newComponents.get(i);
3058             expandRelatedComponents(component, newComponents, dependencies);
3059         }
3060 
3061         return newComponents;
3062     }
3063 
3064     @SuppressWarnings("fallthrough")
3065     private void expandRelatedComponents(XSObject component,List<XSObject>componentList, Map<String, List<String>> dependencies) {
3066         short componentType = component.getType();
3067         switch (componentType) {
3068         case XSConstants.TYPE_DEFINITION :
3069             expandRelatedTypeComponents((XSTypeDefinition) component, componentList, component.getNamespace(), dependencies);
3070             break;
3071         case XSConstants.ATTRIBUTE_DECLARATION :
3072             expandRelatedAttributeComponents((XSAttributeDeclaration) component, componentList, component.getNamespace(), dependencies);
3073             break;
3074         case XSConstants.ATTRIBUTE_GROUP :
3075             expandRelatedAttributeGroupComponents((XSAttributeGroupDefinition) component, componentList, component.getNamespace(), dependencies);
3076         case XSConstants.ELEMENT_DECLARATION :
3077             expandRelatedElementComponents((XSElementDeclaration) component, componentList, component.getNamespace(), dependencies);
3078             break;
3079         case XSConstants.MODEL_GROUP_DEFINITION :
3080             expandRelatedModelGroupDefinitionComponents((XSModelGroupDefinition) component, componentList, component.getNamespace(), dependencies);
3081         case XSConstants.ATTRIBUTE_USE :
3082             //expandRelatedAttributeUseComponents((XSAttributeUse)component, componentList, dependencies);
3083         case XSConstants.NOTATION_DECLARATION :
3084         case XSConstants.IDENTITY_CONSTRAINT :
3085         default :
3086             break;
3087         }
3088     }
3089 
3090     private void expandRelatedAttributeComponents(XSAttributeDeclaration decl, List<XSObject> componentList, String namespace, Map<String, List<String>> dependencies) {
3091         addRelatedType(decl.getTypeDefinition(), componentList, namespace, dependencies);
3092 
3093         /*final XSComplexTypeDefinition enclosingType = decl.getEnclosingCTDefinition();
3094         if (enclosingType != null) {
3095             addRelatedType(enclosingType, componentList, namespace, dependencies);
3096         }*/
3097     }
3098 
3099     private void expandRelatedElementComponents(XSElementDeclaration decl, List<XSObject> componentList, String namespace, Map<String, List<String>> dependencies) {
3100         addRelatedType(decl.getTypeDefinition(), componentList, namespace, dependencies);
3101 
3102         /*final XSTypeDefinition enclosingType = decl.getEnclosingCTDefinition();
3103         if (enclosingType != null) {
3104             addRelatedType(enclosingType, componentList, namespace, dependencies);
3105         }*/
3106 
3107         final XSElementDeclaration subElemDecl = decl.getSubstitutionGroupAffiliation();
3108         if (subElemDecl != null) {
3109             addRelatedElement(subElemDecl, componentList, namespace, dependencies);
3110         }
3111     }
3112 
3113     private void expandRelatedTypeComponents(XSTypeDefinition type, List<XSObject> componentList, String namespace, Map<String, List<String>> dependencies) {
3114         if (type instanceof XSComplexTypeDecl) {
3115             expandRelatedComplexTypeComponents((XSComplexTypeDecl) type, componentList, namespace, dependencies);
3116         }
3117         else if (type instanceof XSSimpleTypeDecl) {
3118             expandRelatedSimpleTypeComponents((XSSimpleTypeDefinition) type, componentList, namespace, dependencies);
3119         }
3120     }
3121 
3122     private void expandRelatedModelGroupDefinitionComponents(XSModelGroupDefinition modelGroupDef, List<XSObject>componentList,
3123             String namespace, Map<String, List<String>> dependencies) {
3124         expandRelatedModelGroupComponents(modelGroupDef.getModelGroup(), componentList, namespace, dependencies);
3125     }
3126 
3127     private void expandRelatedAttributeGroupComponents(XSAttributeGroupDefinition attrGroup, List<XSObject> componentList
3128             , String namespace, Map<String, List<String>> dependencies) {
3129         expandRelatedAttributeUsesComponents(attrGroup.getAttributeUses(), componentList, namespace, dependencies);
3130     }
3131 
3132     private void expandRelatedComplexTypeComponents(XSComplexTypeDecl type, List<XSObject> componentList, String namespace, Map<String, List<String>> dependencies) {
3133         addRelatedType(type.getBaseType(), componentList, namespace, dependencies);
3134         expandRelatedAttributeUsesComponents(type.getAttributeUses(), componentList, namespace, dependencies);
3135         final XSParticle particle = type.getParticle();
3136         if (particle != null) {
3137             expandRelatedParticleComponents(particle, componentList, namespace, dependencies);
3138         }
3139     }
3140 
3141     private void expandRelatedSimpleTypeComponents(XSSimpleTypeDefinition type, List<XSObject> componentList, String namespace, Map<String, List<String>> dependencies) {
3142         final XSTypeDefinition baseType = type.getBaseType();
3143         if (baseType != null) {
3144             addRelatedType(baseType, componentList, namespace, dependencies);
3145         }
3146 
3147         final XSTypeDefinition itemType = type.getItemType();
3148         if (itemType != null) {
3149             addRelatedType(itemType, componentList, namespace, dependencies);
3150         }
3151 
3152         final XSTypeDefinition primitiveType = type.getPrimitiveType();
3153         if (primitiveType != null) {
3154             addRelatedType(primitiveType, componentList, namespace, dependencies);
3155         }
3156 
3157         final XSObjectList memberTypes = type.getMemberTypes();
3158         if (memberTypes.size() > 0) {
3159             for (int i=0; i<memberTypes.size(); i++) {
3160                 addRelatedType((XSTypeDefinition)memberTypes.item(i), componentList, namespace, dependencies);
3161             }
3162         }
3163     }
3164 
3165     private void expandRelatedAttributeUsesComponents(XSObjectList attrUses, List<XSObject> componentList,
3166             String namespace, Map<String, List<String>> dependencies) {
3167         final int attrUseSize = (attrUses == null) ? 0 : attrUses.size();
3168         for (int i=0; i<attrUseSize; i++) {
3169             expandRelatedAttributeUseComponents((XSAttributeUse)attrUses.item(i), componentList, namespace, dependencies);
3170         }
3171     }
3172 
3173     private void expandRelatedAttributeUseComponents(XSAttributeUse component, List<XSObject> componentList,
3174             String namespace, Map<String, List<String>> dependencies) {
3175         addRelatedAttribute(component.getAttrDeclaration(), componentList, namespace, dependencies);
3176     }
3177 
3178     private void expandRelatedParticleComponents(XSParticle component, List<XSObject> componentList,
3179             String namespace, Map<String, List<String>> dependencies) {
3180         XSTerm term = component.getTerm();
3181         switch (term.getType()) {
3182         case XSConstants.ELEMENT_DECLARATION :
3183             addRelatedElement((XSElementDeclaration) term, componentList, namespace, dependencies);
3184             break;
3185         case XSConstants.MODEL_GROUP :
3186             expandRelatedModelGroupComponents((XSModelGroup) term, componentList, namespace, dependencies);
3187             break;
3188         default:
3189             break;
3190         }
3191     }
3192 
3193     private void expandRelatedModelGroupComponents(XSModelGroup modelGroup, List<XSObject> componentList,
3194             String namespace, Map<String, List<String>> dependencies) {
3195         XSObjectList particles = modelGroup.getParticles();
3196         final int length = (particles == null) ? 0 : particles.getLength();
3197         for (int i=0; i<length; i++) {
3198             expandRelatedParticleComponents((XSParticle)particles.item(i), componentList, namespace, dependencies);
3199         }
3200     }
3201 
3202     private void addRelatedType(XSTypeDefinition type, List<XSObject> componentList, String namespace, Map<String, List<String>> dependencies) {
3203         if (!type.getAnonymous()) {
3204             if (!SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(type.getNamespace())) { //REVISIT - do we use == instead
3205                 if (!componentList.contains(type)) {
3206                     final List<String> importedNamespaces = findDependentNamespaces(namespace, dependencies);
3207                     addNamespaceDependency(namespace, type.getNamespace(), importedNamespaces);
3208                     componentList.add(type);
3209                 }
3210             }
3211         }
3212         else {
3213             expandRelatedTypeComponents(type, componentList, namespace, dependencies);
3214         }
3215     }
3216 
3217     private void addRelatedElement(XSElementDeclaration decl, List<XSObject> componentList, String namespace, Map<String, List<String>> dependencies) {
3218         if (decl.getScope() == XSConstants.SCOPE_GLOBAL) {
3219             if (!componentList.contains(decl)) {
3220                List<String> importedNamespaces = findDependentNamespaces(namespace, dependencies);
3221                 addNamespaceDependency(namespace, decl.getNamespace(), importedNamespaces);
3222                 componentList.add(decl);
3223             }
3224         }
3225         else {
3226             expandRelatedElementComponents(decl, componentList, namespace, dependencies);
3227         }
3228     }
3229 
3230     private void addRelatedAttribute(XSAttributeDeclaration decl, List<XSObject> componentList, String namespace, Map<String, List<String>> dependencies) {
3231         if (decl.getScope() == XSConstants.SCOPE_GLOBAL) {
3232             if (!componentList.contains(decl)) {
3233                 List<String> importedNamespaces = findDependentNamespaces(namespace, dependencies);
3234                 addNamespaceDependency(namespace, decl.getNamespace(), importedNamespaces);
3235                 componentList.add(decl);
3236             }
3237         }
3238         else {
3239             expandRelatedAttributeComponents(decl, componentList, namespace, dependencies);
3240         }
3241     }
3242 
3243     private void addGlobalComponents(List<XSObject> components, Map<String, List<String>> importDependencies) {
3244         final XSDDescription desc = new XSDDescription();
3245         final int size = components.size();
3246 
3247         for (int i=0; i<size; i++) {
3248             addGlobalComponent(components.get(i), desc);
3249         }
3250         updateImportDependencies(importDependencies);
3251     }
3252 
3253     private void addGlobalComponent(XSObject component, XSDDescription desc) {
3254         final String namespace = component.getNamespace();
3255 
3256         desc.setNamespace(namespace);
3257         final SchemaGrammar sg = getSchemaGrammar(desc);
3258 
3259         short componentType = component.getType();
3260         final String name = component.getName();
3261 
3262         switch (componentType) {
3263         case XSConstants.TYPE_DEFINITION :
3264             if (!((XSTypeDefinition) component).getAnonymous()) {
3265                 if (sg.getGlobalTypeDecl(name) == null) {
3266                     sg.addGlobalTypeDecl((XSTypeDefinition) component);
3267                 }
3268                 // store the declaration in the extended map, using an empty location
3269                 if (sg.getGlobalTypeDecl(name, "") == null) {
3270                     sg.addGlobalTypeDecl((XSTypeDefinition) component, "");
3271                 }
3272             }
3273             break;
3274         case XSConstants.ATTRIBUTE_DECLARATION :
3275             if (((XSAttributeDecl) component).getScope() == XSAttributeDecl.SCOPE_GLOBAL) {
3276                 if (sg.getGlobalAttributeDecl(name) == null) {
3277                     sg.addGlobalAttributeDecl((XSAttributeDecl) component);
3278                 }
3279                 // store the declaration in the extended map, using an empty location
3280                 if (sg.getGlobalAttributeDecl(name, "") == null) {
3281                     sg.addGlobalAttributeDecl((XSAttributeDecl) component, "");
3282                 }
3283             }
3284             break;
3285         case XSConstants.ATTRIBUTE_GROUP :
3286             if (sg.getGlobalAttributeDecl(name) == null) {
3287                 sg.addGlobalAttributeGroupDecl((XSAttributeGroupDecl) component);
3288             }
3289             // store the declaration in the extended map, using an empty location
3290             if (sg.getGlobalAttributeDecl(name, "") == null) {
3291                 sg.addGlobalAttributeGroupDecl((XSAttributeGroupDecl) component, "");
3292             }
3293             break;
3294         case XSConstants.ELEMENT_DECLARATION :
3295             if (((XSElementDecl) component).getScope() == XSElementDecl.SCOPE_GLOBAL) {
3296                 sg.addGlobalElementDeclAll((XSElementDecl) component);
3297 
3298                 if (sg.getGlobalElementDecl(name) == null) {
3299                     sg.addGlobalElementDecl((XSElementDecl) component);
3300                 }
3301                 // store the declaration in the extended map, using an empty location
3302                 if (sg.getGlobalElementDecl(name, "") == null) {
3303                     sg.addGlobalElementDecl((XSElementDecl) component, "");
3304                 }
3305             }
3306             break;
3307         case XSConstants.MODEL_GROUP_DEFINITION :
3308             if (sg.getGlobalGroupDecl(name) == null) {
3309                 sg.addGlobalGroupDecl((XSGroupDecl) component);
3310             }
3311             // store the declaration in the extended map, using an empty location
3312             if (sg.getGlobalGroupDecl(name, "") == null) {
3313                 sg.addGlobalGroupDecl((XSGroupDecl) component, "");
3314             }
3315             break;
3316         case XSConstants.NOTATION_DECLARATION :
3317             if (sg.getGlobalNotationDecl(name) == null) {
3318                 sg.addGlobalNotationDecl((XSNotationDecl) component);
3319             }
3320             // store the declaration in the extended map, using an empty location
3321             if (sg.getGlobalNotationDecl(name, "") == null) {
3322                 sg.addGlobalNotationDecl((XSNotationDecl) component, "");
3323             }
3324             break;
3325         case XSConstants.IDENTITY_CONSTRAINT :
3326         case XSConstants.ATTRIBUTE_USE :
3327         default :
3328             break;
3329         }
3330     }
3331 
3332     private void updateImportDependencies(Map<String, List<String>> table) {
3333         if (table == null) return;
3334         String namespace;
3335         List<String> importList;
3336 
3337         for(Map.Entry<String, List<String>> entry : table.entrySet()){
3338             namespace = entry.getKey();
3339             importList = entry.getValue();
3340             if (importList.size() > 0) {
3341                 expandImportList(namespace, importList);
3342             }
3343         }
3344     }
3345 
3346     private void expandImportList(String namespace, List<String> namespaceList) {
3347         SchemaGrammar sg = fGrammarBucket.getGrammar(namespace);
3348         // shouldn't be null
3349         if (sg != null) {
3350             List<SchemaGrammar> isgs = sg.getImportedGrammars();
3351             if (isgs == null) {
3352                 isgs = new ArrayList<>();
3353                 addImportList(sg, isgs, namespaceList);
3354                 sg.setImportedGrammars(isgs);
3355             }
3356             else {
3357                 updateImportList(sg, isgs, namespaceList);
3358             }
3359         }
3360     }
3361 
3362     private void addImportList(SchemaGrammar sg, List<SchemaGrammar> importedGrammars, List<String> namespaceList) {
3363         final int size = namespaceList.size();
3364         SchemaGrammar isg;
3365 
3366         for (int i=0; i<size; i++) {
3367             isg = fGrammarBucket.getGrammar(namespaceList.get(i));
3368             if (isg != null) {
3369                 importedGrammars.add(isg);
3370             }
3371             else {
3372                 //REVIST: report an error message
3373             }
3374         }
3375     }
3376 
3377     private void updateImportList(SchemaGrammar sg, List<SchemaGrammar> importedGrammars,
3378             List<String> namespaceList) {
3379         final int size = namespaceList.size();
3380         SchemaGrammar isg;
3381 
3382         for (int i=0; i<size; i++) {
3383             isg = fGrammarBucket.getGrammar(namespaceList.get(i));
3384             if (isg != null) {
3385                 if (!containedImportedGrammar(importedGrammars, isg)) {
3386                     importedGrammars.add(isg);
3387                 }
3388             }
3389             else {
3390                 //REVIST: report an error message
3391             }
3392         }
3393     }
3394 
3395     private boolean containedImportedGrammar(List<SchemaGrammar> importedGrammar, SchemaGrammar grammar) {
3396         final int size = importedGrammar.size();
3397         SchemaGrammar sg;
3398 
3399         for (int i=0; i<size; i++) {
3400             sg =  importedGrammar.get(i);
3401             if (null2EmptyString(sg.getTargetNamespace()).equals(null2EmptyString(grammar.getTargetNamespace()))) {
3402                 return true;
3403             }
3404         }
3405         return false;
3406     }
3407 
3408     // NOTE: always assuming that fNamespaceGrowth is enabled
3409     //       otherwise the grammar should have existed
3410     private SchemaGrammar getSchemaGrammar(XSDDescription desc) {
3411         SchemaGrammar sg = findGrammar(desc, fNamespaceGrowth);
3412 
3413         if (sg == null) {
3414             sg = new SchemaGrammar(desc.getNamespace(), desc.makeClone(), fSymbolTable);
3415             fGrammarBucket.putGrammar(sg);
3416         }
3417         else if (sg.isImmutable()){
3418             sg = createGrammarFrom(sg);
3419         }
3420 
3421         return sg;
3422     }
3423 
3424     private List<String> findDependentNamespaces(String namespace,
3425             Map<String, List<String>> table) {
3426         final String ns = null2EmptyString(namespace);
3427         List<String> namespaceList = getFromMap(table, ns);
3428 
3429         if (namespaceList == null) {
3430             namespaceList = new ArrayList<>();
3431             table.put(ns, namespaceList);
3432         }
3433 
3434         return namespaceList;
3435     }
3436 
3437     private void addNamespaceDependency(String namespace1, String namespace2, List<String> list) {
3438         final String ns1 = null2EmptyString(namespace1);
3439         final String ns2 = null2EmptyString(namespace2);
3440         if (!ns1.equals(ns2)) {
3441             if (!list.contains(ns2)) {
3442                 list.add(ns2);
3443             }
3444         }
3445     }
3446 
3447     private void reportSharingError(String namespace, String name) {
3448         final String qName = (namespace == null)
3449             ? "," + name : namespace + "," + name;
3450 
3451         reportSchemaError("sch-props-correct.2", new Object [] {qName}, null);
3452     }
3453 
3454     // initialize all the traversers.
3455     // this should only need to be called once during the construction
3456     // of this object; it creates the traversers that will be used to
3457 
3458     // construct schemaGrammars.
3459     private void createTraversers() {
3460         fAttributeChecker = new XSAttributeChecker(this);
3461         fAttributeGroupTraverser = new XSDAttributeGroupTraverser(this, fAttributeChecker);
3462         fAttributeTraverser = new XSDAttributeTraverser(this, fAttributeChecker);
3463         fComplexTypeTraverser = new XSDComplexTypeTraverser(this, fAttributeChecker);
3464         fElementTraverser = new XSDElementTraverser(this, fAttributeChecker);
3465         fGroupTraverser = new XSDGroupTraverser(this, fAttributeChecker);
3466         fKeyrefTraverser = new XSDKeyrefTraverser(this, fAttributeChecker);
3467         fNotationTraverser = new XSDNotationTraverser(this, fAttributeChecker);
3468         fSimpleTypeTraverser = new XSDSimpleTypeTraverser(this, fAttributeChecker);
3469         fUniqueOrKeyTraverser = new XSDUniqueOrKeyTraverser(this, fAttributeChecker);
3470         fWildCardTraverser = new XSDWildcardTraverser(this, fAttributeChecker);
3471     } // createTraversers()
3472 
3473     // before parsing a schema, need to clear registries associated with
3474     // parsing schemas
3475     void prepareForParse() {
3476         fTraversed.clear();
3477         fDoc2SystemId.clear();
3478         fHiddenNodes.clear();
3479         fLastSchemaWasDuplicate = false;
3480     }
3481 
3482     // before traversing a schema's parse tree, need to reset all traversers and
3483     // clear all registries
3484     void prepareForTraverse() {
3485         if (!registryEmpty) {
3486         fUnparsedAttributeRegistry.clear();
3487         fUnparsedAttributeGroupRegistry.clear();
3488         fUnparsedElementRegistry.clear();
3489         fUnparsedGroupRegistry.clear();
3490         fUnparsedIdentityConstraintRegistry.clear();
3491         fUnparsedNotationRegistry.clear();
3492         fUnparsedTypeRegistry.clear();
3493 
3494         fUnparsedAttributeRegistrySub.clear();
3495         fUnparsedAttributeGroupRegistrySub.clear();
3496         fUnparsedElementRegistrySub.clear();
3497         fUnparsedGroupRegistrySub.clear();
3498         fUnparsedIdentityConstraintRegistrySub.clear();
3499         fUnparsedNotationRegistrySub.clear();
3500         fUnparsedTypeRegistrySub.clear();
3501         }
3502 
3503         for (int i=1; i<= TYPEDECL_TYPE; i++) {
3504             if (fUnparsedRegistriesExt[i] != null)
3505                 fUnparsedRegistriesExt[i].clear();
3506         }
3507 
3508         fDependencyMap.clear();
3509         fDoc2XSDocumentMap.clear();
3510         if (fRedefine2XSDMap != null) fRedefine2XSDMap.clear();
3511         if (fRedefine2NSSupport != null) fRedefine2NSSupport.clear();
3512         fAllTNSs.clear();
3513         fImportMap.clear();
3514         fRoot = null;
3515 
3516         // clear local element stack
3517         for (int i = 0; i < fLocalElemStackPos; i++) {
3518             fParticle[i] = null;
3519             fLocalElementDecl[i] = null;
3520             fLocalElementDecl_schema[i] = null;
3521             fLocalElemNamespaceContext[i] = null;
3522         }
3523         fLocalElemStackPos = 0;
3524 
3525         // and do same for keyrefs.
3526         for (int i = 0; i < fKeyrefStackPos; i++) {
3527             fKeyrefs[i] = null;
3528             fKeyrefElems[i] = null;
3529             fKeyrefNamespaceContext[i] = null;
3530             fKeyrefsMapXSDocumentInfo[i] = null;
3531         }
3532         fKeyrefStackPos = 0;
3533 
3534         // create traversers if necessary
3535         if (fAttributeChecker == null) {
3536             createTraversers();
3537         }
3538 
3539         // reset traversers
3540         Locale locale = fErrorReporter.getLocale();
3541         fAttributeChecker.reset(fSymbolTable);
3542         fAttributeGroupTraverser.reset(fSymbolTable, fValidateAnnotations, locale);
3543         fAttributeTraverser.reset(fSymbolTable, fValidateAnnotations, locale);
3544         fComplexTypeTraverser.reset(fSymbolTable, fValidateAnnotations, locale);
3545         fElementTraverser.reset(fSymbolTable, fValidateAnnotations, locale);
3546         fGroupTraverser.reset(fSymbolTable, fValidateAnnotations, locale);
3547         fKeyrefTraverser.reset(fSymbolTable, fValidateAnnotations, locale);
3548         fNotationTraverser.reset(fSymbolTable, fValidateAnnotations, locale);
3549         fSimpleTypeTraverser.reset(fSymbolTable, fValidateAnnotations, locale);
3550         fUniqueOrKeyTraverser.reset(fSymbolTable, fValidateAnnotations, locale);
3551         fWildCardTraverser.reset(fSymbolTable, fValidateAnnotations, locale);
3552 
3553         fRedefinedRestrictedAttributeGroupRegistry.clear();
3554         fRedefinedRestrictedGroupRegistry.clear();
3555 
3556         fGlobalAttrDecls.clear();
3557         fGlobalAttrGrpDecls.clear();
3558         fGlobalElemDecls.clear();
3559         fGlobalGroupDecls.clear();
3560         fGlobalNotationDecls.clear();
3561         fGlobalIDConstraintDecls.clear();
3562         fGlobalTypeDecls.clear();
3563     }
3564     public void setDeclPool (XSDeclarationPool declPool){
3565         fDeclPool = declPool;
3566     }
3567     public void setDVFactory(SchemaDVFactory dvFactory){
3568         fDVFactory = dvFactory;
3569     }
3570     public SchemaDVFactory getDVFactory(){
3571         return fDVFactory;
3572     }
3573 
3574     public void reset(XMLComponentManager componentManager) {
3575 
3576         // set symbol table
3577         fSymbolTable = (SymbolTable) componentManager.getProperty(SYMBOL_TABLE);
3578 
3579         // set security manager
3580         fSecurityManager = (XMLSecurityManager) componentManager.getProperty(SECURITY_MANAGER, null);
3581 
3582         //set entity manager
3583         fEntityManager = (XMLEntityManager) componentManager.getProperty(ENTITY_MANAGER);
3584 
3585         //set entity resolver
3586         XMLEntityResolver er = (XMLEntityResolver)componentManager.getProperty(ENTITY_RESOLVER);
3587         if (er != null)
3588             fSchemaParser.setEntityResolver(er);
3589 
3590         // set error reporter
3591         fErrorReporter = (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER);
3592         fErrorHandler = fErrorReporter.getErrorHandler();
3593         fLocale = fErrorReporter.getLocale();
3594 
3595         fValidateAnnotations = componentManager.getFeature(VALIDATE_ANNOTATIONS, false);
3596         fHonourAllSchemaLocations = componentManager.getFeature(HONOUR_ALL_SCHEMALOCATIONS, false);
3597         fNamespaceGrowth = componentManager.getFeature(NAMESPACE_GROWTH, false);
3598         fTolerateDuplicates = componentManager.getFeature(TOLERATE_DUPLICATES, false);
3599 
3600         try {
3601             // Setting a parser property can be much more expensive
3602             // than checking its value.  Don't set the ERROR_HANDLER
3603             // or LOCALE properties unless they've actually changed.
3604             if (fErrorHandler != fSchemaParser.getProperty(ERROR_HANDLER)) {
3605                 fSchemaParser.setProperty(ERROR_HANDLER,
3606                         (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler());
3607                 if (fAnnotationValidator != null) {
3608                     fAnnotationValidator.setProperty(ERROR_HANDLER,
3609                             (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler());
3610                 }
3611             }
3612             if (fLocale != fSchemaParser.getProperty(LOCALE)) {
3613                 fSchemaParser.setProperty(LOCALE, fLocale);
3614                 if (fAnnotationValidator != null) {
3615                     fAnnotationValidator.setProperty(LOCALE, fLocale);
3616                 }
3617             }
3618         }
3619         catch (XMLConfigurationException e) {}
3620 
3621         try {
3622             fSchemaParser.setFeature(CONTINUE_AFTER_FATAL_ERROR,
3623                     fErrorReporter.getFeature(CONTINUE_AFTER_FATAL_ERROR));
3624         } catch (XMLConfigurationException e) {}
3625 
3626         try {
3627             if (componentManager.getFeature(ALLOW_JAVA_ENCODINGS, false)) {
3628                 fSchemaParser.setFeature(ALLOW_JAVA_ENCODINGS, true);
3629             }
3630         } catch (XMLConfigurationException e) {}
3631 
3632         try {
3633             if (componentManager.getFeature(STANDARD_URI_CONFORMANT_FEATURE, false)) {
3634                 fSchemaParser.setFeature(STANDARD_URI_CONFORMANT_FEATURE, true);
3635             }
3636         } catch (XMLConfigurationException e) {}
3637 
3638         try {
3639             fGrammarPool = (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL);
3640         } catch (XMLConfigurationException e) {
3641             fGrammarPool = null;
3642         }
3643 
3644         // security features
3645         try {
3646             if (componentManager.getFeature(DISALLOW_DOCTYPE, false)) {
3647                 fSchemaParser.setFeature(DISALLOW_DOCTYPE, true);
3648             }
3649         } catch (XMLConfigurationException e) {}
3650 
3651         try {
3652             if (fSecurityManager != null) {
3653                 fSchemaParser.setProperty(SECURITY_MANAGER, fSecurityManager);
3654             }
3655         } catch (XMLConfigurationException e) {}
3656 
3657         fSecurityPropertyMgr = (XMLSecurityPropertyManager)
3658                 componentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER);
3659 
3660         //Passing on the setting to the parser
3661         fSchemaParser.setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr);
3662 
3663         fAccessExternalDTD = fSecurityPropertyMgr.getValue(
3664                 XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD);
3665         fAccessExternalSchema = fSecurityPropertyMgr.getValue(
3666                 XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA);
3667 
3668         fOverrideDefaultParser = componentManager.getFeature(JdkXmlUtils.OVERRIDE_PARSER);
3669         fSchemaParser.setFeature(JdkXmlUtils.OVERRIDE_PARSER, fOverrideDefaultParser);
3670         fEntityManager.setFeature(JdkXmlUtils.OVERRIDE_PARSER, fOverrideDefaultParser);
3671         // Passing the Catalog settings to the parser
3672         fUseCatalog = componentManager.getFeature(XMLConstants.USE_CATALOG);
3673         fSchemaParser.setFeature(XMLConstants.USE_CATALOG, fUseCatalog);
3674         fEntityManager.setFeature(XMLConstants.USE_CATALOG, fUseCatalog);
3675 
3676         fCatalogFile = (String)componentManager.getProperty(JdkXmlUtils.CATALOG_FILES);
3677         fDefer = (String)componentManager.getProperty(JdkXmlUtils.CATALOG_DEFER);
3678         fPrefer = (String)componentManager.getProperty(JdkXmlUtils.CATALOG_PREFER);
3679         fResolve = (String)componentManager.getProperty(JdkXmlUtils.CATALOG_RESOLVE);
3680 
3681         for( CatalogFeatures.Feature f : CatalogFeatures.Feature.values()) {
3682             fSchemaParser.setProperty(f.getPropertyName(),
3683                     componentManager.getProperty(f.getPropertyName()));
3684             fEntityManager.setProperty(f.getPropertyName(),
3685                     componentManager.getProperty(f.getPropertyName()));
3686         }
3687 
3688         fSchemaParser.setProperty(JdkXmlUtils.CDATA_CHUNK_SIZE,
3689                 componentManager.getProperty(JdkXmlUtils.CDATA_CHUNK_SIZE));
3690         fEntityManager.setProperty(JdkXmlUtils.CDATA_CHUNK_SIZE,
3691                 componentManager.getProperty(JdkXmlUtils.CDATA_CHUNK_SIZE));
3692     } // reset(XMLComponentManager)
3693 
3694 
3695     /**
3696      * Traverse all the deferred local elements. This method should be called
3697      * by traverseSchemas after we've done with all the global declarations.
3698      */
3699     void traverseLocalElements() {
3700         fElementTraverser.fDeferTraversingLocalElements = false;
3701 
3702         for (int i = 0; i < fLocalElemStackPos; i++) {
3703             Element currElem = fLocalElementDecl[i];
3704             XSDocumentInfo currSchema = fLocalElementDecl_schema[i];
3705             SchemaGrammar currGrammar = fGrammarBucket.getGrammar(currSchema.fTargetNamespace);
3706             fElementTraverser.traverseLocal (fParticle[i], currElem, currSchema,
3707                     currGrammar, fAllContext[i], fParent[i], fLocalElemNamespaceContext[i]);
3708             // If it's an empty particle, remove it from the containing component.
3709             if (fParticle[i].fType == XSParticleDecl.PARTICLE_EMPTY) {
3710                 XSModelGroupImpl group = null;
3711                 if (fParent[i] instanceof XSComplexTypeDecl) {
3712                     XSParticle p = ((XSComplexTypeDecl)fParent[i]).getParticle();
3713                     if (p != null)
3714                         group = (XSModelGroupImpl)p.getTerm();
3715                 }
3716                 else {
3717                     group = ((XSGroupDecl)fParent[i]).fModelGroup;
3718                 }
3719                 if (group != null)
3720                     removeParticle(group, fParticle[i]);
3721             }
3722         }
3723     }
3724 
3725     private boolean removeParticle(XSModelGroupImpl group, XSParticleDecl particle) {
3726         XSParticleDecl member;
3727         for (int i = 0; i < group.fParticleCount; i++) {
3728             member = group.fParticles[i];
3729             if (member == particle) {
3730                 for (int j = i; j < group.fParticleCount-1; j++)
3731                     group.fParticles[j] = group.fParticles[j+1];
3732                 group.fParticleCount--;
3733                 return true;
3734             }
3735             if (member.fType == XSParticleDecl.PARTICLE_MODELGROUP) {
3736                 if (removeParticle((XSModelGroupImpl)member.fValue, particle))
3737                     return true;
3738             }
3739         }
3740         return false;
3741     }
3742 
3743     // the purpose of this method is to keep up-to-date structures
3744     // we'll need for the feferred traversal of local elements.
3745     void fillInLocalElemInfo(Element elmDecl,
3746             XSDocumentInfo schemaDoc,
3747             int allContextFlags,
3748             XSObject parent,
3749             XSParticleDecl particle) {
3750 
3751         // if the stack is full, increase the size
3752         if (fParticle.length == fLocalElemStackPos) {
3753             // increase size
3754             XSParticleDecl[] newStackP = new XSParticleDecl[fLocalElemStackPos+INC_STACK_SIZE];
3755             System.arraycopy(fParticle, 0, newStackP, 0, fLocalElemStackPos);
3756             fParticle = newStackP;
3757             Element[] newStackE = new Element[fLocalElemStackPos+INC_STACK_SIZE];
3758             System.arraycopy(fLocalElementDecl, 0, newStackE, 0, fLocalElemStackPos);
3759             fLocalElementDecl = newStackE;
3760             XSDocumentInfo [] newStackE_schema = new XSDocumentInfo[fLocalElemStackPos+INC_STACK_SIZE];
3761             System.arraycopy(fLocalElementDecl_schema, 0, newStackE_schema, 0, fLocalElemStackPos);
3762             fLocalElementDecl_schema = newStackE_schema;
3763             int[] newStackI = new int[fLocalElemStackPos+INC_STACK_SIZE];
3764             System.arraycopy(fAllContext, 0, newStackI, 0, fLocalElemStackPos);
3765             fAllContext = newStackI;
3766             XSObject[] newStackC = new XSObject[fLocalElemStackPos+INC_STACK_SIZE];
3767             System.arraycopy(fParent, 0, newStackC, 0, fLocalElemStackPos);
3768             fParent = newStackC;
3769             String [][] newStackN = new String [fLocalElemStackPos+INC_STACK_SIZE][];
3770             System.arraycopy(fLocalElemNamespaceContext, 0, newStackN, 0, fLocalElemStackPos);
3771             fLocalElemNamespaceContext = newStackN;
3772         }
3773 
3774         fParticle[fLocalElemStackPos] = particle;
3775         fLocalElementDecl[fLocalElemStackPos] = elmDecl;
3776         fLocalElementDecl_schema[fLocalElemStackPos] = schemaDoc;
3777         fAllContext[fLocalElemStackPos] = allContextFlags;
3778         fParent[fLocalElemStackPos] = parent;
3779         fLocalElemNamespaceContext[fLocalElemStackPos++] = schemaDoc.fNamespaceSupport.getEffectiveLocalContext();
3780     } // end fillInLocalElemInfo(...)
3781 
3782     /** This method makes sure that
3783      * if this component is being redefined that it lives in the
3784      * right schema.  It then renames the component correctly.  If it
3785      * detects a collision--a duplicate definition--then it complains.
3786      * Note that redefines must be handled carefully:  if there
3787      * is a collision, it may be because we're redefining something we know about
3788      * or because we've found the thing we're redefining.
3789      */
3790     void checkForDuplicateNames(String qName, int declType,
3791             Map<String,Element> registry, Map<String,XSDocumentInfo> registry_sub, Element currComp,
3792             XSDocumentInfo currSchema) {
3793         Object objElem = null;
3794         // REVISIT:  when we add derivation checking, we'll have to make
3795         // sure that ID constraint collisions don't necessarily result in error messages.
3796         if ((objElem = registry.get(qName)) == null) {
3797             // need to check whether we have a global declaration in the corresponding
3798             // grammar
3799             if (fNamespaceGrowth && !fTolerateDuplicates) {
3800                 checkForDuplicateNames(qName, declType, currComp);
3801             }
3802             // just add it in!
3803             registry.put(qName, currComp);
3804             registry_sub.put(qName, currSchema);
3805         }
3806         else {
3807             Element collidingElem = (Element)objElem;
3808             XSDocumentInfo collidingElemSchema = registry_sub.get(qName);
3809             if (collidingElem == currComp) return;
3810             Element elemParent = null;
3811             XSDocumentInfo redefinedSchema = null;
3812             // case where we've collided with a redefining element
3813             // (the parent of the colliding element is a redefine)
3814             boolean collidedWithRedefine = true;
3815             if ((DOMUtil.getLocalName((elemParent = DOMUtil.getParent(collidingElem))).equals(SchemaSymbols.ELT_REDEFINE))) {
3816                 redefinedSchema = (fRedefine2XSDMap != null)? fRedefine2XSDMap.get(elemParent) : null;
3817                 // case where we're a redefining element.
3818             }
3819             else if ((DOMUtil.getLocalName(DOMUtil.getParent(currComp)).equals(SchemaSymbols.ELT_REDEFINE))) {
3820                 redefinedSchema = collidingElemSchema;
3821                 collidedWithRedefine = false;
3822             }
3823             if (redefinedSchema != null) { //redefinition involved somehow
3824                 // If both components belong to the same document then
3825                 // report an error and return.
3826                 if(collidingElemSchema == currSchema){
3827                     reportSchemaError("sch-props-correct.2", new Object[]{qName}, currComp);
3828                     return;
3829                 }
3830 
3831                 String newName = qName.substring(qName.lastIndexOf(',')+1)+REDEF_IDENTIFIER;
3832                 if (redefinedSchema == currSchema) { // object comp. okay here
3833                     // now have to do some renaming...
3834                     currComp.setAttribute(SchemaSymbols.ATT_NAME, newName);
3835                     if (currSchema.fTargetNamespace == null){
3836                         registry.put(","+newName, currComp);
3837                         registry_sub.put(","+newName, currSchema);
3838                     }
3839                     else{
3840                         registry.put(currSchema.fTargetNamespace+","+newName, currComp);
3841                         registry_sub.put(currSchema.fTargetNamespace+","+newName, currSchema);
3842                     }
3843                     // and take care of nested redefines by calling recursively:
3844                     if (currSchema.fTargetNamespace == null)
3845                         checkForDuplicateNames(","+newName, declType, registry, registry_sub, currComp, currSchema);
3846                     else
3847                         checkForDuplicateNames(currSchema.fTargetNamespace+","+newName, declType, registry, registry_sub, currComp, currSchema);
3848                 }
3849                 else { // we may be redefining the wrong schema
3850                     if (collidedWithRedefine) {
3851                         if (currSchema.fTargetNamespace == null)
3852                             checkForDuplicateNames(","+newName, declType, registry, registry_sub, currComp, currSchema);
3853                         else
3854                             checkForDuplicateNames(currSchema.fTargetNamespace+","+newName, declType, registry, registry_sub, currComp, currSchema);
3855                     }
3856                     else {
3857                         // error that redefined element in wrong schema
3858                         reportSchemaError("sch-props-correct.2", new Object [] {qName}, currComp);
3859                     }
3860                 }
3861             }
3862             else {
3863                 // we've just got a flat-out collision (we tolerate duplicate
3864                 // declarations, only if they are defined in different schema
3865                 // documents)
3866                 if (!fTolerateDuplicates) {
3867                     reportSchemaError("sch-props-correct.2", new Object []{qName}, currComp);
3868                 } else if (fUnparsedRegistriesExt[declType] != null) {
3869                     if (fUnparsedRegistriesExt[declType].get(qName) == currSchema) {
3870                         reportSchemaError("sch-props-correct.2", new Object []{qName}, currComp);
3871                     }
3872                 }
3873             }
3874         }
3875 
3876         // store the lastest current document info
3877         if (fTolerateDuplicates) {
3878             if (fUnparsedRegistriesExt[declType] == null)
3879                 fUnparsedRegistriesExt[declType] = new HashMap<>();
3880             fUnparsedRegistriesExt[declType].put(qName, currSchema);
3881         }
3882 
3883     } // checkForDuplicateNames(String, Map, Element, XSDocumentInfo):void
3884 
3885     void checkForDuplicateNames(String qName, int declType, Element currComp) {
3886         int namespaceEnd = qName.indexOf(',');
3887         String namespace = qName.substring(0, namespaceEnd);
3888         SchemaGrammar grammar = fGrammarBucket.getGrammar(emptyString2Null(namespace));
3889 
3890         if (grammar != null) {
3891             Object obj = getGlobalDeclFromGrammar(grammar, declType, qName.substring(namespaceEnd + 1));
3892             if (obj != null) {
3893                 reportSchemaError("sch-props-correct.2", new Object []{qName}, currComp);
3894             }
3895         }
3896     }
3897 
3898     // the purpose of this method is to take the component of the
3899     // specified type and rename references to itself so that they
3900     // refer to the object being redefined.  It takes special care of
3901     // <group>s and <attributeGroup>s to ensure that information
3902     // relating to implicit restrictions is preserved for those
3903     // traversers.
3904     private void renameRedefiningComponents(XSDocumentInfo currSchema,
3905             Element child, String componentType,
3906             String oldName, String newName) {
3907         if (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
3908             Element grandKid = DOMUtil.getFirstChildElement(child);
3909             if (grandKid == null) {
3910                 reportSchemaError("src-redefine.5.a.a", null, child);
3911             }
3912             else {
3913                 String grandKidName = DOMUtil.getLocalName(grandKid);
3914                 if (grandKidName.equals(SchemaSymbols.ELT_ANNOTATION)) {
3915                     grandKid = DOMUtil.getNextSiblingElement(grandKid);
3916                 }
3917                 if (grandKid == null) {
3918                     reportSchemaError("src-redefine.5.a.a", null, child);
3919                 }
3920                 else {
3921                     grandKidName = DOMUtil.getLocalName(grandKid);
3922                     if (!grandKidName.equals(SchemaSymbols.ELT_RESTRICTION)) {
3923                         reportSchemaError("src-redefine.5.a.b", new Object[]{grandKidName}, child);
3924                     }
3925                     else {
3926                         Object[] attrs = fAttributeChecker.checkAttributes(grandKid, false, currSchema);
3927                         QName derivedBase = (QName)attrs[XSAttributeChecker.ATTIDX_BASE];
3928                         if (derivedBase == null ||
3929                                 derivedBase.uri != currSchema.fTargetNamespace ||
3930                                 !derivedBase.localpart.equals(oldName)) {
3931                             reportSchemaError("src-redefine.5.a.c",
3932                                     new Object[]{grandKidName,
3933                                     (currSchema.fTargetNamespace==null?"":currSchema.fTargetNamespace)
3934                                     + "," + oldName},
3935                                     child);
3936                         }
3937                         else {
3938                             // now we have to do the renaming...
3939                             if (derivedBase.prefix != null && derivedBase.prefix.length() > 0)
3940                                 grandKid.setAttribute( SchemaSymbols.ATT_BASE,
3941                                         derivedBase.prefix + ":" + newName );
3942                             else
3943                                 grandKid.setAttribute( SchemaSymbols.ATT_BASE, newName );
3944                             //                            return true;
3945                         }
3946                         fAttributeChecker.returnAttrArray(attrs, currSchema);
3947                     }
3948                 }
3949             }
3950         }
3951         else if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
3952             Element grandKid = DOMUtil.getFirstChildElement(child);
3953             if (grandKid == null) {
3954                 reportSchemaError("src-redefine.5.b.a", null, child);
3955             }
3956             else {
3957                 if (DOMUtil.getLocalName(grandKid).equals(SchemaSymbols.ELT_ANNOTATION)) {
3958                     grandKid = DOMUtil.getNextSiblingElement(grandKid);
3959                 }
3960                 if (grandKid == null) {
3961                     reportSchemaError("src-redefine.5.b.a", null, child);
3962                 }
3963                 else {
3964                     // have to go one more level down; let another pass worry whether complexType is valid.
3965                     Element greatGrandKid = DOMUtil.getFirstChildElement(grandKid);
3966                     if (greatGrandKid == null) {
3967                         reportSchemaError("src-redefine.5.b.b", null, grandKid);
3968                     }
3969                     else {
3970                         String greatGrandKidName = DOMUtil.getLocalName(greatGrandKid);
3971                         if (greatGrandKidName.equals(SchemaSymbols.ELT_ANNOTATION)) {
3972                             greatGrandKid = DOMUtil.getNextSiblingElement(greatGrandKid);
3973                         }
3974                         if (greatGrandKid == null) {
3975                             reportSchemaError("src-redefine.5.b.b", null, grandKid);
3976                         }
3977                         else {
3978                             greatGrandKidName = DOMUtil.getLocalName(greatGrandKid);
3979                             if (!greatGrandKidName.equals(SchemaSymbols.ELT_RESTRICTION) &&
3980                                     !greatGrandKidName.equals(SchemaSymbols.ELT_EXTENSION)) {
3981                                 reportSchemaError("src-redefine.5.b.c", new Object[]{greatGrandKidName}, greatGrandKid);
3982                             }
3983                             else {
3984                                 Object[] attrs = fAttributeChecker.checkAttributes(greatGrandKid, false, currSchema);
3985                                 QName derivedBase = (QName)attrs[XSAttributeChecker.ATTIDX_BASE];
3986                                 if (derivedBase == null ||
3987                                         derivedBase.uri != currSchema.fTargetNamespace ||
3988                                         !derivedBase.localpart.equals(oldName)) {
3989                                     reportSchemaError("src-redefine.5.b.d",
3990                                             new Object[]{greatGrandKidName,
3991                                             (currSchema.fTargetNamespace==null?"":currSchema.fTargetNamespace)
3992                                             + "," + oldName},
3993                                             greatGrandKid);
3994                                 }
3995                                 else {
3996                                     // now we have to do the renaming...
3997                                     if (derivedBase.prefix != null && derivedBase.prefix.length() > 0)
3998                                         greatGrandKid.setAttribute( SchemaSymbols.ATT_BASE,
3999                                                 derivedBase.prefix + ":" + newName );
4000                                     else
4001                                         greatGrandKid.setAttribute( SchemaSymbols.ATT_BASE,
4002                                                 newName );
4003                                     //                                    return true;
4004                                 }
4005                             }
4006                         }
4007                     }
4008                 }
4009             }
4010         }
4011         else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
4012             String processedBaseName = (currSchema.fTargetNamespace == null)?
4013                     ","+oldName:currSchema.fTargetNamespace+","+oldName;
4014             int attGroupRefsCount = changeRedefineGroup(processedBaseName, componentType, newName, child, currSchema);
4015             if (attGroupRefsCount > 1) {
4016                 reportSchemaError("src-redefine.7.1", new Object []{new Integer(attGroupRefsCount)}, child);
4017             }
4018             else if (attGroupRefsCount == 1) {
4019                 //                return true;
4020             }
4021             else
4022                 if (currSchema.fTargetNamespace == null)
4023                     fRedefinedRestrictedAttributeGroupRegistry.put(processedBaseName, ","+newName);
4024                 else
4025                     fRedefinedRestrictedAttributeGroupRegistry.put(processedBaseName, currSchema.fTargetNamespace+","+newName);
4026         }
4027         else if (componentType.equals(SchemaSymbols.ELT_GROUP)) {
4028             String processedBaseName = (currSchema.fTargetNamespace == null)?
4029                     ","+oldName:currSchema.fTargetNamespace+","+oldName;
4030             int groupRefsCount = changeRedefineGroup(processedBaseName, componentType, newName, child, currSchema);
4031             if (groupRefsCount > 1) {
4032                 reportSchemaError("src-redefine.6.1.1", new Object []{new Integer(groupRefsCount)}, child);
4033             }
4034             else if (groupRefsCount == 1) {
4035                 //                return true;
4036             }
4037             else {
4038                 if (currSchema.fTargetNamespace == null)
4039                     fRedefinedRestrictedGroupRegistry.put(processedBaseName, ","+newName);
4040                 else
4041                     fRedefinedRestrictedGroupRegistry.put(processedBaseName, currSchema.fTargetNamespace+","+newName);
4042             }
4043         }
4044         else {
4045             reportSchemaError("Internal-Error", new Object [] {"could not handle this particular <redefine>; please submit your schemas and instance document in a bug report!"}, child);
4046         }
4047         // if we get here then we must have reported an error and failed somewhere...
4048         //        return false;
4049     } // renameRedefiningComponents(XSDocumentInfo, Element, String, String, String):void
4050 
4051     // this method takes a name of the form a:b, determines the URI mapped
4052     // to by a in the current SchemaNamespaceSupport object, and returns this
4053     // information in the form (nsURI,b) suitable for lookups in the global
4054     // decl maps.
4055     // REVISIT: should have it return QName, instead of String. this would
4056     //          save lots of string concatenation time. we can use
4057     //          QName#equals() to compare two QNames, and use QName directly
4058     //          as a key to the SymbolHash.
4059     //          And when the DV's are ready to return compiled values from
4060     //          validate() method, we should just call QNameDV.validate()
4061     //          in this method.
4062     private String findQName(String name, XSDocumentInfo schemaDoc) {
4063         SchemaNamespaceSupport currNSMap = schemaDoc.fNamespaceSupport;
4064         int colonPtr = name.indexOf(':');
4065         String prefix = XMLSymbols.EMPTY_STRING;
4066         if (colonPtr > 0)
4067             prefix = name.substring(0, colonPtr);
4068         String uri = currNSMap.getURI(fSymbolTable.addSymbol(prefix));
4069         String localpart = (colonPtr == 0)?name:name.substring(colonPtr+1);
4070         if (prefix == XMLSymbols.EMPTY_STRING && uri == null && schemaDoc.fIsChameleonSchema)
4071             uri = schemaDoc.fTargetNamespace;
4072         if (uri == null)
4073             return ","+localpart;
4074         return uri+","+localpart;
4075     } // findQName(String, XSDocumentInfo):  String
4076 
4077     // This function looks among the children of curr for an element of type elementSought.
4078     // If it finds one, it evaluates whether its ref attribute contains a reference
4079     // to originalQName.  If it does, it returns 1 + the value returned by
4080     // calls to itself on all other children.  In all other cases it returns 0 plus
4081     // the sum of the values returned by calls to itself on curr's children.
4082     // It also resets the value of ref so that it will refer to the renamed type from the schema
4083     // being redefined.
4084     private int changeRedefineGroup(String originalQName, String elementSought,
4085             String newName, Element curr, XSDocumentInfo schemaDoc) {
4086         int result = 0;
4087         for (Element child = DOMUtil.getFirstChildElement(curr);
4088         child != null; child = DOMUtil.getNextSiblingElement(child)) {
4089             String name = DOMUtil.getLocalName(child);
4090             if (!name.equals(elementSought))
4091                 result += changeRedefineGroup(originalQName, elementSought, newName, child, schemaDoc);
4092             else {
4093                 String ref = child.getAttribute( SchemaSymbols.ATT_REF );
4094                 if (ref.length() != 0) {
4095                     String processedRef = findQName(ref, schemaDoc);
4096                     if (originalQName.equals(processedRef)) {
4097                         String prefix = XMLSymbols.EMPTY_STRING;
4098                         int colonptr = ref.indexOf(":");
4099                         if (colonptr > 0) {
4100                             prefix = ref.substring(0,colonptr);
4101                             child.setAttribute(SchemaSymbols.ATT_REF, prefix + ":" + newName);
4102                         }
4103                         else
4104                             child.setAttribute(SchemaSymbols.ATT_REF, newName);
4105                         result++;
4106                         if (elementSought.equals(SchemaSymbols.ELT_GROUP)) {
4107                             String minOccurs = child.getAttribute( SchemaSymbols.ATT_MINOCCURS );
4108                             String maxOccurs = child.getAttribute( SchemaSymbols.ATT_MAXOCCURS );
4109                             if (!((maxOccurs.length() == 0 || maxOccurs.equals("1"))
4110                                     && (minOccurs.length() == 0 || minOccurs.equals("1")))) {
4111                                 reportSchemaError("src-redefine.6.1.2", new Object [] {ref}, child);
4112                             }
4113                         }
4114                     }
4115                 } // if ref was null some other stage of processing will flag the error
4116             }
4117         }
4118         return result;
4119     } // changeRedefineGroup
4120 
4121     // this method returns the XSDocumentInfo object that contains the
4122     // component corresponding to decl.  If components from this
4123     // document cannot be referred to from those of currSchema, this
4124     // method returns null; it's up to the caller to throw an error.
4125     // @param:  currSchema:  the XSDocumentInfo object containing the
4126     // decl ref'ing us.
4127     // @param:  decl:  the declaration being ref'd.
4128     // this method is superficial now. ---Jack
4129     private XSDocumentInfo findXSDocumentForDecl(XSDocumentInfo currSchema,
4130             Element decl, XSDocumentInfo decl_Doc) {
4131 
4132         if (DEBUG_NODE_POOL) {
4133             System.out.println("DOCUMENT NS:" + currSchema.fTargetNamespace + " hashcode:" +
4134                     ((Object)currSchema.fSchemaElement).hashCode());
4135         }
4136         Object temp = decl_Doc;
4137         if (temp == null) {
4138             // something went badly wrong; we don't know this doc?
4139             return null;
4140         }
4141         XSDocumentInfo declDocInfo = (XSDocumentInfo)temp;
4142         return declDocInfo;
4143         /*********
4144          Logic here is unnecessary after schema WG's recent decision to allow
4145          schema components from one document to refer to components of any other,
4146          so long as there's some include/import/redefine path amongst them.
4147          If they rver reverse this decision the code's right here though...  - neilg
4148          // now look in fDependencyMap to see if this is reachable
4149           if((fDependencyMap.get(currSchema)).contains(declDocInfo)) {
4150           return declDocInfo;
4151           }
4152           // obviously the requesting doc didn't include, redefine or
4153            // import the one containing decl...
4154             return null;
4155             **********/
4156     } // findXSDocumentForDecl(XSDocumentInfo, Element):  XSDocumentInfo
4157 
4158     // returns whether more than <annotation>s occur in children of elem
4159     private boolean nonAnnotationContent(Element elem) {
4160         for(Element child = DOMUtil.getFirstChildElement(elem); child != null;
4161                 child = DOMUtil.getNextSiblingElement(child)) {
4162             if(!(DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION))) return true;
4163         }
4164         return false;
4165     } // nonAnnotationContent(Element):  boolean
4166 
4167     private void setSchemasVisible(XSDocumentInfo startSchema) {
4168         if (DOMUtil.isHidden(startSchema.fSchemaElement, fHiddenNodes)) {
4169             // make it visible
4170             DOMUtil.setVisible(startSchema.fSchemaElement, fHiddenNodes);
4171             List<XSDocumentInfo> dependingSchemas = fDependencyMap.get(startSchema);
4172             for (int i = 0; i < dependingSchemas.size(); i++) {
4173                 setSchemasVisible(dependingSchemas.get(i));
4174             }
4175         }
4176         // if it's visible already than so must be its children
4177     } // setSchemasVisible(XSDocumentInfo): void
4178 
4179     private SimpleLocator xl = new SimpleLocator();
4180 
4181     /**
4182      * Extract location information from an Element node, and create a
4183      * new SimpleLocator object from such information. Returning null means
4184      * no information can be retrieved from the element.
4185      */
4186     public SimpleLocator element2Locator(Element e) {
4187         if (!( e instanceof ElementImpl))
4188             return null;
4189 
4190         SimpleLocator l = new SimpleLocator();
4191         return element2Locator(e, l) ? l : null;
4192     }
4193 
4194     /**
4195      * Extract location information from an Element node, store such
4196      * information in the passed-in SimpleLocator object, then return
4197      * true. Returning false means can't extract or store such information.
4198      */
4199     public boolean element2Locator(Element e, SimpleLocator l) {
4200         if (l == null)
4201             return false;
4202         if (e instanceof ElementImpl) {
4203             ElementImpl ele = (ElementImpl)e;
4204             // get system id from document object
4205             Document doc = ele.getOwnerDocument();
4206             String sid = fDoc2SystemId.get(DOMUtil.getRoot(doc));
4207             // line/column numbers are stored in the element node
4208             int line = ele.getLineNumber();
4209             int column = ele.getColumnNumber();
4210             l.setValues(sid, sid, line, column, ele.getCharacterOffset());
4211             return true;
4212         }
4213         return false;
4214     }
4215 
4216     private Element getElementFromMap(Map<String, Element> registry, String declKey) {
4217         if (registry == null) return null;
4218         return registry.get(declKey);
4219     }
4220 
4221     private XSDocumentInfo getDocInfoFromMap(Map<String, XSDocumentInfo> registry, String declKey) {
4222         if (registry == null) return null;
4223         return registry.get(declKey);
4224     }
4225 
4226     private List<String> getFromMap(Map<String, List<String>> registry, String key) {
4227         if (registry == null) return null;
4228         return registry.get(key);
4229     }
4230 
4231     void reportSchemaFatalError(String key, Object[] args, Element ele) {
4232         reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_FATAL_ERROR, null);
4233     }
4234 
4235     void reportSchemaError(String key, Object[] args, Element ele) {
4236         reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_ERROR, null);
4237     }
4238 
4239     void reportSchemaError(String key, Object[] args, Element ele, Exception exception) {
4240         reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_ERROR, exception);
4241     }
4242 
4243     void reportSchemaWarning(String key, Object[] args, Element ele) {
4244         reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_WARNING, null);
4245     }
4246 
4247     void reportSchemaWarning(String key, Object[] args, Element ele, Exception exception) {
4248         reportSchemaErr(key, args, ele, XMLErrorReporter.SEVERITY_WARNING, exception);
4249     }
4250 
4251     void reportSchemaErr(String key, Object[] args, Element ele, short type, Exception exception) {
4252         if (element2Locator(ele, xl)) {
4253             fErrorReporter.reportError(xl, XSMessageFormatter.SCHEMA_DOMAIN,
4254                     key, args, type, exception);
4255         }
4256         else {
4257             fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN,
4258                     key, args, type, exception);
4259         }
4260     }
4261 
4262     /**
4263      * Grammar pool used for validating annotations. This will return all of the
4264      * grammars from the grammar bucket. It will also return an object for the
4265      * schema for schemas which will contain at least the relevant declarations
4266      * for annotations.
4267      */
4268     private static class XSAnnotationGrammarPool implements XMLGrammarPool {
4269 
4270         private XSGrammarBucket fGrammarBucket;
4271         private Grammar [] fInitialGrammarSet;
4272 
4273         public Grammar[] retrieveInitialGrammarSet(String grammarType) {
4274             if (grammarType == XMLGrammarDescription.XML_SCHEMA) {
4275                 if (fInitialGrammarSet == null) {
4276                     if (fGrammarBucket == null) {
4277                         fInitialGrammarSet = new Grammar [] {SchemaGrammar.Schema4Annotations.INSTANCE};
4278                     }
4279                     else {
4280                         SchemaGrammar [] schemaGrammars = fGrammarBucket.getGrammars();
4281                         /**
4282                          * If the grammar bucket already contains the schema for schemas
4283                          * then we already have the definitions for the parts relevant
4284                          * to annotations.
4285                          */
4286                         for (int i = 0; i < schemaGrammars.length; ++i) {
4287                             if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(schemaGrammars[i].getTargetNamespace())) {
4288                                 fInitialGrammarSet = schemaGrammars;
4289                                 return fInitialGrammarSet;
4290                             }
4291                         }
4292                         Grammar [] grammars = new Grammar[schemaGrammars.length + 1];
4293                         System.arraycopy(schemaGrammars, 0, grammars, 0, schemaGrammars.length);
4294                         grammars[grammars.length - 1] = SchemaGrammar.Schema4Annotations.INSTANCE;
4295                         fInitialGrammarSet = grammars;
4296                     }
4297                 }
4298                 return fInitialGrammarSet;
4299             }
4300             return new Grammar[0];
4301         }
4302 
4303         public void cacheGrammars(String grammarType, Grammar[] grammars) {
4304 
4305         }
4306 
4307         public Grammar retrieveGrammar(XMLGrammarDescription desc) {
4308             if (desc.getGrammarType() == XMLGrammarDescription.XML_SCHEMA) {
4309                 final String tns = ((XMLSchemaDescription) desc).getTargetNamespace();
4310                 if (fGrammarBucket != null) {
4311                     Grammar grammar = fGrammarBucket.getGrammar(tns);
4312                     if (grammar != null) {
4313                         return grammar;
4314                     }
4315                 }
4316                 if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(tns)) {
4317                     return SchemaGrammar.Schema4Annotations.INSTANCE;
4318                 }
4319             }
4320             return null;
4321         }
4322 
4323         public void refreshGrammars(XSGrammarBucket gBucket) {
4324             fGrammarBucket = gBucket;
4325             fInitialGrammarSet = null;
4326         }
4327 
4328         public void lockPool() {}
4329 
4330         public void unlockPool() {}
4331 
4332         public void clear() {}
4333     }
4334 
4335     /**
4336      * used to identify a reference to a schema document
4337      * if the same document is referenced twice with the same key, then
4338      * we only need to parse it once.
4339      *
4340      * When 2 XSDKey's are compared, the following table can be used to
4341      * determine whether they are equal:
4342      *      inc     red     imp     pre     ins
4343      * inc  N/L      ?      N/L     N/L     N/L
4344      * red   ?      N/L      ?       ?       ?
4345      * imp  N/L      ?      N/P     N/P     N/P
4346      * pre  N/L      ?      N/P     N/P     N/P
4347      * ins  N/L      ?      N/P     N/P     N/P
4348      *
4349      * Where: N/L: duplicate when they have the same namespace and location.
4350      *         ? : not clear from the spec.
4351      *             REVISIT: to simplify the process, also considering
4352      *             it's very rare, we treat them as not duplicate.
4353      *        N/P: not possible. imp/pre/ins are referenced by namespace.
4354      *             when the first time we encounter a schema document for a
4355      *             namespace, we create a grammar and store it in the grammar
4356      *             bucket. when we see another reference to the same namespace,
4357      *             we first check whether a grammar with the same namespace is
4358      *             already in the bucket, which is true in this case, so we
4359      *             won't create another XSDKey.
4360      *
4361      * Conclusion from the table: two XSDKey's are duplicate only when all of
4362      * the following are true:
4363      * 1. They are both "redefine", or neither is "redefine";
4364      * 2. They have the same namespace;
4365      * 3. They have the same non-null location.
4366      *
4367      * About 3: if neither has a non-null location, then it's the case where
4368      * 2 input streams are provided, but no system ID is provided. We can't tell
4369      * whether the 2 streams have the same content, so we treat them as not
4370      * duplicate.
4371      */
4372     private static class XSDKey {
4373         String systemId;
4374         short  referType;
4375         // for inclue/redefine, this is the enclosing namespace
4376         // for import/preparse/instance, this is the target namespace
4377         String referNS;
4378 
4379         XSDKey(String systemId, short referType, String referNS) {
4380             this.systemId = systemId;
4381             this.referType = referType;
4382             this.referNS = referNS;
4383         }
4384 
4385         public int hashCode() {
4386             // according to the description at the beginning of this class,
4387             // we use the hashcode of the namespace as the hashcoe of this key.
4388             return referNS == null ? 0 : referNS.hashCode();
4389         }
4390 
4391         public boolean equals(Object obj) {
4392             if (!(obj instanceof XSDKey)) {
4393                 return false;
4394             }
4395             XSDKey key = (XSDKey)obj;
4396 
4397             // condition 1: both are redefine
4398             /** if (referType == XSDDescription.CONTEXT_REDEFINE ||
4399                     key.referType == XSDDescription.CONTEXT_REDEFINE) {
4400                 if (referType != key.referType)
4401                     return false;
4402             }**/
4403 
4404             // condition 2: same namespace
4405             if (referNS != key.referNS)
4406                 return false;
4407 
4408             // condition 3: same non-null location
4409             if (systemId == null || !systemId.equals(key.systemId)) {
4410                 return false;
4411             }
4412 
4413             return true;
4414         }
4415     }
4416 
4417     private static final class SAX2XNIUtil extends ErrorHandlerWrapper {
4418         public static XMLParseException createXMLParseException0(SAXParseException exception) {
4419             return createXMLParseException(exception);
4420         }
4421         public static XNIException createXNIException0(SAXException exception) {
4422             return createXNIException(exception);
4423         }
4424     }
4425 
4426     /**
4427      * @param state
4428      */
4429     public void setGenerateSyntheticAnnotations(boolean state) {
4430         fSchemaParser.setFeature(GENERATE_SYNTHETIC_ANNOTATIONS, state);
4431     }
4432 
4433 } // XSDHandler