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