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