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