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