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