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