KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > impl > xs > traversers > XSDHandler


1 /*
2  * Copyright 1999-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.xerces.impl.xs.traversers;
18
19 import java.io.IOException JavaDoc;
20 import java.io.StringReader JavaDoc;
21 import java.util.ArrayList JavaDoc;
22 import java.util.Hashtable JavaDoc;
23 import java.util.Stack JavaDoc;
24 import java.util.Vector JavaDoc;
25
26 import org.apache.xerces.impl.Constants;
27 import org.apache.xerces.impl.XMLEntityManager;
28 import org.apache.xerces.impl.XMLErrorReporter;
29 import org.apache.xerces.impl.xs.SchemaGrammar;
30 import org.apache.xerces.impl.xs.SchemaNamespaceSupport;
31 import org.apache.xerces.impl.xs.SchemaSymbols;
32 import org.apache.xerces.impl.xs.XMLSchemaException;
33 import org.apache.xerces.impl.xs.XMLSchemaLoader;
34 import org.apache.xerces.impl.xs.XSComplexTypeDecl;
35 import org.apache.xerces.impl.xs.XSDDescription;
36 import org.apache.xerces.impl.xs.XSDeclarationPool;
37 import org.apache.xerces.impl.xs.XSElementDecl;
38 import org.apache.xerces.impl.xs.XSGrammarBucket;
39 import org.apache.xerces.impl.xs.XSGroupDecl;
40 import org.apache.xerces.impl.xs.XSMessageFormatter;
41 import org.apache.xerces.impl.xs.XSModelGroupImpl;
42 import org.apache.xerces.impl.xs.XSParticleDecl;
43 import org.apache.xerces.impl.xs.opti.ElementImpl;
44 import org.apache.xerces.impl.xs.opti.SchemaDOMParser;
45 import org.apache.xerces.impl.xs.opti.SchemaParsingConfig;
46 import org.apache.xerces.impl.xs.util.SimpleLocator;
47
48 import org.apache.xerces.util.DOMUtil;
49 import org.apache.xerces.parsers.SAXParser;
50 import org.apache.xerces.parsers.XML11Configuration;
51 import org.apache.xerces.util.DOMInputSource;
52 import org.apache.xerces.util.DefaultErrorHandler;
53 import org.apache.xerces.util.SAXInputSource;
54 import org.apache.xerces.util.SymbolTable;
55 import org.apache.xerces.util.XMLSymbols;
56 import org.apache.xerces.util.URI.MalformedURIException;
57 import org.apache.xerces.xni.QName;
58 import org.apache.xerces.xni.grammars.Grammar;
59 import org.apache.xerces.xni.grammars.XMLGrammarDescription;
60 import org.apache.xerces.xni.grammars.XMLGrammarPool;
61 import org.apache.xerces.xni.grammars.XMLSchemaDescription;
62 import org.apache.xerces.xni.parser.XMLComponentManager;
63 import org.apache.xerces.xni.parser.XMLConfigurationException;
64 import org.apache.xerces.xni.parser.XMLEntityResolver;
65 import org.apache.xerces.xni.parser.XMLErrorHandler;
66 import org.apache.xerces.xni.parser.XMLInputSource;
67 import org.apache.xerces.xs.XSObject;
68 import org.apache.xerces.xs.XSParticle;
69 import org.w3c.dom.Document JavaDoc;
70 import org.w3c.dom.Element JavaDoc;
71 import org.w3c.dom.Node JavaDoc;
72 import org.xml.sax.InputSource JavaDoc;
73 import org.xml.sax.SAXException JavaDoc;
74 import org.xml.sax.XMLReader JavaDoc;
75 import org.xml.sax.helpers.XMLReaderFactory JavaDoc;
76
77
78 /**
79  * The purpose of this class is to co-ordinate the construction of a
80  * grammar object corresponding to a schema. To do this, it must be
81  * prepared to parse several schema documents (for instance if the
82  * schema document originally referred to contains <include> or
83  * <redefined> information items). If any of the schemas imports a
84  * schema, other grammars may be constructed as a side-effect.
85  *
86  * @xerces.internal
87  *
88  * @author Neil Graham, IBM
89  * @author Pavani Mukthipudi, Sun Microsystems
90  *
91  * @version $Id: XSDHandler.java,v 1.92 2005/06/24 17:56:41 mrglavas Exp $
92  */

93 public class XSDHandler {
94     
95     /** Feature identifier: validation. */
96     protected static final String JavaDoc VALIDATION =
97         Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
98     
99     /** feature identifier: XML Schema validation */
100     protected static final String JavaDoc XMLSCHEMA_VALIDATION =
101         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
102     
103     /** Feature identifier: allow java encodings */
104     protected static final String JavaDoc ALLOW_JAVA_ENCODINGS =
105         Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
106     
107     /** Feature identifier: continue after fatal error */
108     protected static final String JavaDoc CONTINUE_AFTER_FATAL_ERROR =
109         Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
110     
111     /** Feature identifier: allow java encodings */
112     protected static final String JavaDoc STANDARD_URI_CONFORMANT_FEATURE =
113         Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE;
114     
115     /** Feature: disallow doctype*/
116     protected static final String JavaDoc DISALLOW_DOCTYPE =
117         Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE;
118     
119     /** Feature: generate synthetic annotations */
120     protected static final String JavaDoc GENERATE_SYNTHETIC_ANNOTATIONS =
121         Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE;
122     
123     /** Feature identifier: validate annotations. */
124     protected static final String JavaDoc VALIDATE_ANNOTATIONS =
125         Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATE_ANNOTATIONS_FEATURE;
126     
127     /** Feature identifier: honour all schemaLocations */
128     protected static final String JavaDoc HONOUR_ALL_SCHEMALOCATIONS =
129       Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE;
130     
131     /** Feature identifier: namespace prefixes. */
132     private static final String JavaDoc NAMESPACE_PREFIXES =
133         Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE;
134     
135     /** Feature identifier: string interning. */
136     protected static final String JavaDoc STRING_INTERNING =
137         Constants.SAX_FEATURE_PREFIX + Constants.STRING_INTERNING_FEATURE;
138    
139     /** Property identifier: error handler. */
140     protected static final String JavaDoc ERROR_HANDLER =
141         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
142     
143     /** Property identifier: JAXP schema source. */
144     protected static final String JavaDoc JAXP_SCHEMA_SOURCE =
145         Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
146     
147     /** Property identifier: entity resolver. */
148     public static final String JavaDoc ENTITY_RESOLVER =
149         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
150     /** Property identifier: entity manager. */
151     protected static final String JavaDoc ENTITY_MANAGER =
152         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
153     
154     /** Property identifier: error reporter. */
155     public static final String JavaDoc ERROR_REPORTER =
156         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
157     
158     /** Property identifier: grammar pool. */
159     public static final String JavaDoc XMLGRAMMAR_POOL =
160         Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
161     
162     /** Property identifier: symbol table. */
163     public static final String JavaDoc SYMBOL_TABLE =
164         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
165     
166     /** Property identifier: security manager. */
167     protected static final String JavaDoc SECURITY_MANAGER =
168         Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
169     
170     protected static final boolean DEBUG_NODE_POOL = false;
171     
172     // Data
173

174     // different sorts of declarations; should make lookup and
175
// traverser calling more efficient/less bulky.
176
final static int ATTRIBUTE_TYPE = 1;
177     final static int ATTRIBUTEGROUP_TYPE = 2;
178     final static int ELEMENT_TYPE = 3;
179     final static int GROUP_TYPE = 4;
180     final static int IDENTITYCONSTRAINT_TYPE = 5;
181     final static int NOTATION_TYPE = 6;
182     final static int TYPEDECL_TYPE = 7;
183     
184     // this string gets appended to redefined names; it's purpose is to be
185
// as unlikely as possible to cause collisions.
186
public final static String JavaDoc REDEF_IDENTIFIER = "_fn3dktizrknc9pi";
187     
188     //
189
//protected data that can be accessable by any traverser
190
// stores <notation> decl
191
protected Hashtable JavaDoc fNotationRegistry = new Hashtable JavaDoc();
192     
193     protected XSDeclarationPool fDeclPool = null;
194     
195     
196     // These tables correspond to the symbol spaces defined in the
197
// spec.
198
// They are keyed with a QName (that is, String("URI,localpart) and
199
// their values are nodes corresponding to the given name's decl.
200
// By asking the node for its ownerDocument and looking in
201
// XSDocumentInfoRegistry we can easily get the corresponding
202
// XSDocumentInfo object.
203
private Hashtable JavaDoc fUnparsedAttributeRegistry = new Hashtable JavaDoc();
204     private Hashtable JavaDoc fUnparsedAttributeGroupRegistry = new Hashtable JavaDoc();
205     private Hashtable JavaDoc fUnparsedElementRegistry = new Hashtable JavaDoc();
206     private Hashtable JavaDoc fUnparsedGroupRegistry = new Hashtable JavaDoc();
207     private Hashtable JavaDoc fUnparsedIdentityConstraintRegistry = new Hashtable JavaDoc();
208     private Hashtable JavaDoc fUnparsedNotationRegistry = new Hashtable JavaDoc();
209     private Hashtable JavaDoc fUnparsedTypeRegistry = new Hashtable JavaDoc();
210     // Compensation for the above hashtables to locate XSDocumentInfo,
211
// Since we may take Schema Element directly, so can not get the
212
// corresponding XSDocumentInfo object just using above hashtables.
213
private Hashtable JavaDoc fUnparsedAttributeRegistrySub = new Hashtable JavaDoc();
214     private Hashtable JavaDoc fUnparsedAttributeGroupRegistrySub = new Hashtable JavaDoc();
215     private Hashtable JavaDoc fUnparsedElementRegistrySub = new Hashtable JavaDoc();
216     private Hashtable JavaDoc fUnparsedGroupRegistrySub = new Hashtable JavaDoc();
217     private Hashtable JavaDoc fUnparsedIdentityConstraintRegistrySub = new Hashtable JavaDoc();
218     private Hashtable JavaDoc fUnparsedNotationRegistrySub = new Hashtable JavaDoc();
219     private Hashtable JavaDoc fUnparsedTypeRegistrySub = new Hashtable JavaDoc();
220     
221     // this is keyed with a documentNode (or the schemaRoot nodes
222
// contained in the XSDocumentInfo objects) and its value is the
223
// XSDocumentInfo object corresponding to that document.
224
// Basically, the function of this registry is to be a link
225
// between the nodes we fetch from calls to the fUnparsed*
226
// arrays and the XSDocumentInfos they live in.
227
private Hashtable JavaDoc fXSDocumentInfoRegistry = new Hashtable JavaDoc();
228     
229     // this hashtable is keyed on by XSDocumentInfo objects. Its values
230
// are Vectors containing the XSDocumentInfo objects <include>d,
231
// <import>ed or <redefine>d by the key XSDocumentInfo.
232
private Hashtable JavaDoc fDependencyMap = new Hashtable JavaDoc();
233     
234     // this hashtable is keyed on by a target namespace. Its values
235
// are Vectors containing namespaces imported by schema documents
236
// with the key target namespace.
237
// if an imprted schema has absent namespace, the value "null" is stored.
238
private Hashtable JavaDoc fImportMap = new Hashtable JavaDoc();
239     // all namespaces that imports other namespaces
240
// if the importing schema has absent namespace, empty string is stored.
241
// (because the key of a hashtable can't be null.)
242
private Vector JavaDoc fAllTNSs = new Vector JavaDoc();
243     // stores instance document mappings between namespaces and schema hints
244
private Hashtable JavaDoc fLocationPairs = null;
245     
246     //this hashtable is keyded on by DOM node objects.
247
//The table stores the hidden nodes
248
private Hashtable JavaDoc fHiddenNodes = null;
249     
250     // convenience methods
251
private String JavaDoc null2EmptyString(String JavaDoc ns) {
252         return ns == null ? XMLSymbols.EMPTY_STRING : ns;
253     }
254     private String JavaDoc emptyString2Null(String JavaDoc ns) {
255         return ns == XMLSymbols.EMPTY_STRING ? null : ns;
256     }
257     // use Schema Element to lookup the SystemId.
258
private String JavaDoc doc2SystemId(Element JavaDoc ele) {
259         String JavaDoc documentURI = null;
260         /**
261          * REVISIT: Casting until DOM Level 3 interfaces are available. -- mrglavas
262          */

263         if(ele.getOwnerDocument() instanceof org.apache.xerces.impl.xs.opti.SchemaDOM){
264             documentURI = ((org.apache.xerces.impl.xs.opti.SchemaDOM) ele.getOwnerDocument()).getDocumentURI();
265         }
266         return documentURI != null ? documentURI : (String JavaDoc) fDoc2SystemId.get(ele);
267     }
268     
269     // This vector stores strings which are combinations of the
270
// publicId and systemId of the inputSource corresponding to a
271
// schema document. This combination is used so that the user's
272
// EntityResolver can provide a consistent way of identifying a
273
// schema document that is included in multiple other schemas.
274
private Hashtable JavaDoc fTraversed = new Hashtable JavaDoc();
275     
276     // this hashtable contains a mapping from Schema Element to its systemId
277
// this is useful to resolve a uri relative to the referring document
278
private Hashtable JavaDoc fDoc2SystemId = new Hashtable JavaDoc();
279     
280     // the primary XSDocumentInfo we were called to parse
281
private XSDocumentInfo fRoot = null;
282     
283     // This hashtable's job is to act as a link between the Schema Element and its
284
// XSDocumentInfo object.
285
private Hashtable JavaDoc fDoc2XSDocumentMap = new Hashtable JavaDoc();
286     
287     // map between <redefine> elements and the XSDocumentInfo
288
// objects that correspond to the documents being redefined.
289
private Hashtable JavaDoc fRedefine2XSDMap = new Hashtable JavaDoc();
290     
291     // map between <redefine> elements and the namespace support
292
private Hashtable JavaDoc fRedefine2NSSupport = new Hashtable JavaDoc();
293     
294     // these objects store a mapping between the names of redefining
295
// groups/attributeGroups and the groups/AttributeGroups which
296
// they redefine by restriction (implicitly). It is up to the
297
// Group and AttributeGroup traversers to check these restrictions for
298
// validity.
299
private Hashtable JavaDoc fRedefinedRestrictedAttributeGroupRegistry = new Hashtable JavaDoc();
300     private Hashtable JavaDoc fRedefinedRestrictedGroupRegistry = new Hashtable JavaDoc();
301     
302     // a variable storing whether the last schema document
303
// processed (by getSchema) was a duplicate.
304
private boolean fLastSchemaWasDuplicate;
305     
306     // validate annotations feature
307
private boolean fValidateAnnotations = false;
308     
309     //handle multiple import feature
310
private boolean fHonourAllSchemaLocations = false;
311
312     // the XMLErrorReporter
313
private XMLErrorReporter fErrorReporter;
314     private XMLEntityResolver fEntityResolver;
315     
316     // the XSAttributeChecker
317
private XSAttributeChecker fAttributeChecker;
318     
319     // the symbol table
320
private SymbolTable fSymbolTable;
321     
322     // the GrammarResolver
323
private XSGrammarBucket fGrammarBucket;
324     
325     // the Grammar description
326
private XSDDescription fSchemaGrammarDescription;
327     
328     // the Grammar Pool
329
private XMLGrammarPool fGrammarPool;
330     
331     //************ Traversers **********
332
XSDAttributeGroupTraverser fAttributeGroupTraverser;
333     XSDAttributeTraverser fAttributeTraverser;
334     XSDComplexTypeTraverser fComplexTypeTraverser;
335     XSDElementTraverser fElementTraverser;
336     XSDGroupTraverser fGroupTraverser;
337     XSDKeyrefTraverser fKeyrefTraverser;
338     XSDNotationTraverser fNotationTraverser;
339     XSDSimpleTypeTraverser fSimpleTypeTraverser;
340     XSDUniqueOrKeyTraverser fUniqueOrKeyTraverser;
341     XSDWildcardTraverser fWildCardTraverser;
342     
343     SchemaDOMParser fSchemaParser;
344     SchemaContentHandler fXSContentHandler;
345     XML11Configuration fAnnotationValidator;
346     XSAnnotationGrammarPool fGrammarBucketAdapter;
347     
348     // these data members are needed for the deferred traversal
349
// of local elements.
350

351     // the initial size of the array to store deferred local elements
352
private static final int INIT_STACK_SIZE = 30;
353     // the incremental size of the array to store deferred local elements
354
private static final int INC_STACK_SIZE = 10;
355     // current position of the array (# of deferred local elements)
356
private int fLocalElemStackPos = 0;
357     
358     private XSParticleDecl[] fParticle = new XSParticleDecl[INIT_STACK_SIZE];
359     private Element JavaDoc[] fLocalElementDecl = new Element JavaDoc[INIT_STACK_SIZE];
360     private XSDocumentInfo[] fLocalElementDecl_schema = new XSDocumentInfo[INIT_STACK_SIZE]; //JACK
361
private int[] fAllContext = new int[INIT_STACK_SIZE];
362     private XSObject[] fParent = new XSObject[INIT_STACK_SIZE];
363     private String JavaDoc [][] fLocalElemNamespaceContext = new String JavaDoc [INIT_STACK_SIZE][1];
364     
365     // these data members are needed for the deferred traversal
366
// of keyrefs.
367

368     // the initial size of the array to store deferred keyrefs
369
private static final int INIT_KEYREF_STACK = 2;
370     // the incremental size of the array to store deferred keyrefs
371
private static final int INC_KEYREF_STACK_AMOUNT = 2;
372     // current position of the array (# of deferred keyrefs)
373
private int fKeyrefStackPos = 0;
374     
375     private Element JavaDoc [] fKeyrefs = new Element JavaDoc[INIT_KEYREF_STACK];
376     private XSDocumentInfo [] fKeyrefsMapXSDocumentInfo = new XSDocumentInfo[INIT_KEYREF_STACK];
377     private XSElementDecl [] fKeyrefElems = new XSElementDecl [INIT_KEYREF_STACK];
378     private String JavaDoc [][] fKeyrefNamespaceContext = new String JavaDoc[INIT_KEYREF_STACK][1];
379     
380     // Constructors
381
public XSDHandler(){
382         fHiddenNodes = new Hashtable JavaDoc();
383         fSchemaParser = new SchemaDOMParser(new SchemaParsingConfig());
384     }
385     
386     // it should be possible to use the same XSDHandler to parse
387
// multiple schema documents; this will allow one to be
388
// constructed.
389
public XSDHandler (XSGrammarBucket gBucket) {
390         this();
391         fGrammarBucket = gBucket;
392         
393         // Note: don't use SchemaConfiguration internally
394
// we will get stack overflaw because
395
// XMLSchemaValidator will be instantiating XSDHandler...
396
fSchemaGrammarDescription = new XSDDescription();
397     } // end constructor
398

399     /**
400      * This method initiates the parse of a schema. It will likely be
401      * called from the Validator and it will make the
402      * resulting grammar available; it returns a reference to this object just
403      * in case. A reset(XMLComponentManager) must be called before this methods is called.
404      * @param is
405      * @param desc
406      * @param locationPairs
407      * @return
408      * @throws IOException
409      */

410     public SchemaGrammar parseSchema(XMLInputSource is, XSDDescription desc,
411             Hashtable JavaDoc locationPairs)
412     throws IOException JavaDoc {
413         fLocationPairs = locationPairs;
414         fSchemaParser.resetNodePool();
415         SchemaGrammar grammar = null;
416         String JavaDoc schemaNamespace = null;
417         short referType = desc.getContextType();
418         // if loading using JAXP schemaSource property, or using grammar caching loadGrammar
419
// the desc.targetNamespace is always null.
420
// Therefore we should not attempt to find out if
421
// the schema is already in the bucket, since in the case we have
422
// no namespace schema in the bucket, findGrammar will always return the
423
// no namespace schema.
424
if (referType != XSDDescription.CONTEXT_PREPARSE){
425             // first try to find it in the bucket/pool, return if one is found
426
if(fHonourAllSchemaLocations && referType == XSDDescription.CONTEXT_IMPORT && isExistingGrammar(desc)) {
427                 grammar = fGrammarBucket.getGrammar(desc.getTargetNamespace());
428             }
429             else {
430                 grammar = findGrammar(desc);
431             }
432             if (grammar != null)
433                 return grammar;
434             schemaNamespace = desc.getTargetNamespace();
435             // handle empty string URI as null
436
if (schemaNamespace != null) {
437                 schemaNamespace = fSymbolTable.addSymbol(schemaNamespace);
438             }
439         }
440         
441         // before parsing a schema, need to clear registries associated with
442
// parsing schemas
443
prepareForParse();
444         
445         Document JavaDoc schemaRootDoc = null;
446         Element JavaDoc schemaRoot = null;
447         // first phase: construct trees.
448
if (is instanceof DOMInputSource) {
449             //clean up the field fHiddenNodes, used for DOMInputSource
450
fHiddenNodes.clear();
451             Node JavaDoc domNode = ((DOMInputSource)is).getNode();
452             
453             if (domNode instanceof Document JavaDoc) {
454                 schemaRootDoc = (Document JavaDoc)domNode;
455                 schemaRoot = DOMUtil.getRoot(schemaRootDoc);
456             }
457             else if (domNode instanceof Element JavaDoc) {
458                 schemaRoot = (Element JavaDoc)domNode;
459             }
460             else {
461                 return null;
462             }
463         } // DOMInputSource
464
else if (is instanceof SAXInputSource) {
465             XMLReader JavaDoc parser = ((SAXInputSource)is).getXMLReader();
466             InputSource inputSource = ((SAXInputSource)is).getInputSource();
467             boolean namespacePrefixes = false;
468             if (parser != null) {
469                 try {
470                     namespacePrefixes = parser.getFeature(NAMESPACE_PREFIXES);
471                 }
472                 catch (SAXException JavaDoc se) {}
473             }
474             else {
475                 try {
476                     parser = XMLReaderFactory.createXMLReader();
477                 }
478                 // If something went wrong with the factory
479
// just use our own SAX parser.
480
catch (SAXException JavaDoc se) {
481                     parser = new SAXParser();
482                 }
483                 try {
484                     parser.setFeature(NAMESPACE_PREFIXES, true);
485                     namespacePrefixes = true;
486                 }
487                 catch (SAXException JavaDoc se) {}
488             }
489             // If XML names and Namespace URIs are already internalized we
490
// can avoid running them through the SymbolTable.
491
boolean stringsInternalized = false;
492             try {
493                 stringsInternalized = parser.getFeature(STRING_INTERNING);
494             }
495             catch (SAXException JavaDoc exc) {
496                 // The feature isn't recognized or getting it is not supported.
497
// In either case, assume that strings are not internalized.
498
}
499             if (fXSContentHandler == null) {
500                 fXSContentHandler = new SchemaContentHandler();
501             }
502             fXSContentHandler.reset(fSchemaParser, fSymbolTable,
503                     namespacePrefixes, stringsInternalized);
504             parser.setContentHandler(fXSContentHandler);
505             parser.setErrorHandler(fErrorReporter.getSAXErrorHandler());
506             try {
507                 parser.parse(inputSource);
508             }
509             catch (SAXException JavaDoc se) {
510                 return null;
511             }
512             schemaRootDoc = fXSContentHandler.getDocument();
513             if (schemaRootDoc == null) {
514                 // something went wrong right off the hop
515
return null;
516             }
517             schemaRoot = DOMUtil.getRoot(schemaRootDoc);
518         }
519         else {
520             schemaRoot = getSchemaDocument(schemaNamespace, is,
521                   referType == XSDDescription.CONTEXT_PREPARSE,
522                   referType, null);
523              
524         }//is instanceof XMLInputSource
525

526         if(schemaRoot == null){
527             // something went wrong right off the hop
528
return null;
529         }
530         
531         if ( referType == XSDDescription.CONTEXT_PREPARSE) {
532             Element JavaDoc schemaElem = schemaRoot;
533             schemaNamespace = DOMUtil.getAttrValue(schemaElem, SchemaSymbols.ATT_TARGETNAMESPACE);
534             if(schemaNamespace != null && schemaNamespace.length() > 0) {
535                 // Since now we've discovered a namespace, we need to update xsd key
536
// and store this schema in traversed schemas bucket
537
schemaNamespace = fSymbolTable.addSymbol(schemaNamespace);
538                 desc.setTargetNamespace(schemaNamespace);
539             }
540             else {
541                 schemaNamespace = null;
542             }
543             grammar = findGrammar(desc);
544             if (grammar != null)
545                 return grammar;
546             String JavaDoc schemaId = XMLEntityManager.expandSystemId(is.getSystemId(), is.getBaseSystemId(), false);
547             XSDKey key = new XSDKey(schemaId, referType, schemaNamespace);
548             fTraversed.put(key, schemaRoot);
549             if (schemaId != null) {
550                 fDoc2SystemId.put(schemaRoot, schemaId);
551             }
552         }
553         
554         // before constructing trees and traversing a schema, need to reset
555
// all traversers and clear all registries
556
prepareForTraverse();
557         
558         fRoot = constructTrees(schemaRoot, is.getSystemId(), desc);
559         if (fRoot == null) {
560             return null;
561         }
562         
563         // second phase: fill global registries.
564
buildGlobalNameRegistries();
565         
566         // third phase: call traversers
567
ArrayList JavaDoc annotationInfo = fValidateAnnotations ? new ArrayList JavaDoc() : null;
568         traverseSchemas(annotationInfo);
569         
570         // fourth phase: handle local element decls
571
traverseLocalElements();
572         
573         // fifth phase: handle Keyrefs
574
resolveKeyRefs();
575         
576         // sixth phase: validate attribute of non-schema namespaces
577
// REVISIT: skip this for now. we really don't want to do it.
578
//fAttributeChecker.checkNonSchemaAttributes(fGrammarBucket);
579

580         // seventh phase: store imported grammars
581
// for all grammars with <import>s
582
for (int i = fAllTNSs.size() - 1; i >= 0; i--) {
583             // get its target namespace
584
String JavaDoc tns = (String JavaDoc)fAllTNSs.elementAt(i);
585             // get all namespaces it imports
586
Vector JavaDoc ins = (Vector JavaDoc)fImportMap.get(tns);
587             // get the grammar
588
SchemaGrammar sg = fGrammarBucket.getGrammar(emptyString2Null(tns));
589             if (sg == null)
590                 continue;
591             SchemaGrammar isg;
592             // for imported namespace
593
int count = 0;
594             for (int j = 0; j < ins.size(); j++) {
595                 // get imported grammar
596
isg = fGrammarBucket.getGrammar((String JavaDoc)ins.elementAt(j));
597                 // reuse the same vector
598
if (isg != null)
599                     ins.setElementAt(isg, count++);
600             }
601             ins.setSize(count);
602             // set the imported grammars
603
sg.setImportedGrammars(ins);
604         }
605         
606         /** validate annotations **/
607         if (fValidateAnnotations && annotationInfo.size() > 0) {
608             validateAnnotations(annotationInfo);
609         }
610
611         // and return.
612
return fGrammarBucket.getGrammar(fRoot.fTargetNamespace);
613     } // end parseSchema
614

615     private void validateAnnotations(ArrayList JavaDoc annotationInfo) {
616         if (fAnnotationValidator == null) {
617             createAnnotationValidator();
618         }
619         final int size = annotationInfo.size();
620         final XMLInputSource src = new XMLInputSource(null, null, null);
621         fGrammarBucketAdapter.refreshGrammars(fGrammarBucket);
622         for (int i = 0; i < size; i += 2) {
623             src.setSystemId((String JavaDoc) annotationInfo.get(i));
624             XSAnnotationInfo annotation = (XSAnnotationInfo) annotationInfo.get(i+1);
625             while (annotation != null) {
626                 src.setCharacterStream(new StringReader JavaDoc(annotation.fAnnotation));
627                 try {
628                     fAnnotationValidator.parse(src);
629                 }
630                 catch (IOException JavaDoc exc) {}
631                 annotation = annotation.next;
632             }
633         }
634     }
635     
636     private void createAnnotationValidator() {
637         fAnnotationValidator = new XML11Configuration();
638         fGrammarBucketAdapter = new XSAnnotationGrammarPool();
639         fAnnotationValidator.setFeature(VALIDATION, true);
640         fAnnotationValidator.setFeature(XMLSCHEMA_VALIDATION, true);
641         fAnnotationValidator.setProperty(XMLGRAMMAR_POOL, fGrammarBucketAdapter);
642         /** Set error handler. **/
643         XMLErrorHandler errorHandler = fErrorReporter.getErrorHandler();
644         fAnnotationValidator.setProperty(ERROR_HANDLER, (errorHandler != null) ? errorHandler : new DefaultErrorHandler());
645     }
646
647     /**
648      * Pull the grammar out of the bucket simply using
649      * its TNS as a key
650      */

651     SchemaGrammar getGrammar(String JavaDoc tns) {
652         return fGrammarBucket.getGrammar(tns);
653     }
654     
655     /**
656      * First try to find a grammar in the bucket, if failed, consult the
657      * grammar pool. If a grammar is found in the pool, then add it (and all
658      * imported ones) into the bucket.
659      */

660     protected SchemaGrammar findGrammar(XSDDescription desc) {
661         SchemaGrammar sg = fGrammarBucket.getGrammar(desc.getTargetNamespace());
662         if (sg == null) {
663             if (fGrammarPool != null) {
664                 sg = (SchemaGrammar)fGrammarPool.retrieveGrammar(desc);
665                 if (sg != null) {
666                     // put this grammar into the bucket, along with grammars
667
// imported by it (directly or indirectly)
668
if (!fGrammarBucket.putGrammar(sg, true)) {
669                         // REVISIT: a conflict between new grammar(s) and grammars
670
// in the bucket. What to do? A warning? An exception?
671
reportSchemaWarning("GrammarConflict", null, null);
672                         sg = null;
673                     }
674                 }
675             }
676         }
677         return sg;
678     }
679     
680     // may wish to have setter methods for ErrorHandler,
681
// EntityResolver...
682

683     private static final String JavaDoc[][] NS_ERROR_CODES = {
684             {"src-include.2.1", "src-include.2.1"},
685             {"src-redefine.3.1", "src-redefine.3.1"},
686             {"src-import.3.1", "src-import.3.2"},
687             null,
688             {"TargetNamespace.1", "TargetNamespace.2"},
689             {"TargetNamespace.1", "TargetNamespace.2"},
690             {"TargetNamespace.1", "TargetNamespace.2"},
691             {"TargetNamespace.1", "TargetNamespace.2"}
692     };
693     
694     private static final String JavaDoc[] ELE_ERROR_CODES = {
695             "src-include.1", "src-redefine.2", "src-import.2", "schema_reference.4",
696             "schema_reference.4", "schema_reference.4", "schema_reference.4", "schema_reference.4"
697     };
698     
699     // This method does several things:
700
// It constructs an instance of an XSDocumentInfo object using the
701
// schemaRoot node. Then, for each <include>,
702
// <redefine>, and <import> children, it attempts to resolve the
703
// requested schema document, initiates a DOM parse, and calls
704
// itself recursively on that document's root. It also records in
705
// the DependencyMap object what XSDocumentInfo objects its XSDocumentInfo
706
// depends on.
707
// It also makes sure the targetNamespace of the schema it was
708
// called to parse is correct.
709
protected XSDocumentInfo constructTrees(Element JavaDoc schemaRoot, String JavaDoc locationHint, XSDDescription desc) {
710         if (schemaRoot == null) return null;
711         String JavaDoc callerTNS = desc.getTargetNamespace();
712         short referType = desc.getContextType();
713         
714         XSDocumentInfo currSchemaInfo = null;
715         try {
716             // note that attributes are freed at end of traverseSchemas()
717
currSchemaInfo = new XSDocumentInfo(schemaRoot, fAttributeChecker, fSymbolTable);
718         } catch (XMLSchemaException se) {
719             reportSchemaError(ELE_ERROR_CODES[referType],
720                     new Object JavaDoc[]{locationHint},
721                       schemaRoot);
722             return null;
723         }
724         // targetNamespace="" is not valid, issue a warning, and ignore it
725
if (currSchemaInfo.fTargetNamespace != null &&
726                 currSchemaInfo.fTargetNamespace.length() == 0) {
727             reportSchemaWarning("EmptyTargetNamespace",
728                     new Object JavaDoc[]{locationHint},
729                     schemaRoot);
730             currSchemaInfo.fTargetNamespace = null;
731         }
732         
733         if (callerTNS != null) {
734             // the second index to the NS_ERROR_CODES array
735
// if the caller/expected NS is not absent, we use the first column
736
int secondIdx = 0;
737             // for include and redefine
738
if (referType == XSDDescription.CONTEXT_INCLUDE ||
739                     referType == XSDDescription.CONTEXT_REDEFINE) {
740                 // if the referred document has no targetNamespace,
741
// it's a chameleon schema
742
if (currSchemaInfo.fTargetNamespace == null) {
743                     currSchemaInfo.fTargetNamespace = callerTNS;
744                     currSchemaInfo.fIsChameleonSchema = true;
745                 }
746                 // if the referred document has a target namespace differing
747
// from the caller, it's an error
748
else if (callerTNS != currSchemaInfo.fTargetNamespace) {
749                     reportSchemaError(NS_ERROR_CODES[referType][secondIdx],
750                             new Object JavaDoc [] {callerTNS, currSchemaInfo.fTargetNamespace},
751                             schemaRoot);
752                     return null;
753                 }
754             }
755             // for instance and import, the two NS's must be the same
756
else if (referType != XSDDescription.CONTEXT_PREPARSE && callerTNS != currSchemaInfo.fTargetNamespace) {
757                 reportSchemaError(NS_ERROR_CODES[referType][secondIdx],
758                         new Object JavaDoc [] {callerTNS, currSchemaInfo.fTargetNamespace},
759                         schemaRoot);
760                 return null;
761             }
762         }
763         // now there is no caller/expected NS, it's an error for the referred
764
// document to have a target namespace, unless we are preparsing a schema
765
else if (currSchemaInfo.fTargetNamespace != null) {
766             // set the target namespace of the description
767
if (referType == XSDDescription.CONTEXT_PREPARSE) {
768                 desc.setTargetNamespace(currSchemaInfo.fTargetNamespace);
769                 callerTNS = currSchemaInfo.fTargetNamespace;
770             }
771             else {
772                 // the second index to the NS_ERROR_CODES array
773
// if the caller/expected NS is absent, we use the second column
774
int secondIdx = 1;
775                 reportSchemaError(NS_ERROR_CODES[referType][secondIdx],
776                         new Object JavaDoc [] {callerTNS, currSchemaInfo.fTargetNamespace},
777                         schemaRoot);
778                 return null;
779             }
780         }
781         // the other cases (callerTNS == currSchemaInfo.fTargetNamespce == null)
782
// are valid
783

784         // a schema document can always access it's own target namespace
785
currSchemaInfo.addAllowedNS(currSchemaInfo.fTargetNamespace);
786         
787         SchemaGrammar sg = null;
788         
789         if (referType == XSDDescription.CONTEXT_INCLUDE ||
790                 referType == XSDDescription.CONTEXT_REDEFINE) {
791             sg = fGrammarBucket.getGrammar(currSchemaInfo.fTargetNamespace);
792         }
793         else if(fHonourAllSchemaLocations && referType == XSDDescription.CONTEXT_IMPORT) {
794             sg = findGrammar(desc);
795             if(sg == null) {
796                 sg = new SchemaGrammar(currSchemaInfo.fTargetNamespace, desc.makeClone(), fSymbolTable);
797                 fGrammarBucket.putGrammar(sg);
798             }
799         }
800         else {
801             sg = new SchemaGrammar(currSchemaInfo.fTargetNamespace, desc.makeClone(), fSymbolTable);
802             fGrammarBucket.putGrammar(sg);
803         }
804         
805         // store the document and its location
806
// REVISIT: don't expose the DOM tree
807
sg.addDocument(null, (String JavaDoc)fDoc2SystemId.get(currSchemaInfo.fSchemaElement));
808         
809         fDoc2XSDocumentMap.put(schemaRoot, currSchemaInfo);
810         Vector JavaDoc dependencies = new Vector JavaDoc();
811         Element JavaDoc rootNode = schemaRoot;
812         
813         Element JavaDoc newSchemaRoot = null;
814         for (Element JavaDoc child = DOMUtil.getFirstChildElement(rootNode);
815         child != null;
816         child = DOMUtil.getNextSiblingElement(child)) {
817             String JavaDoc schemaNamespace=null;
818             String JavaDoc schemaHint=null;
819             String JavaDoc localName = DOMUtil.getLocalName(child);
820             
821             short refType = -1;
822             
823             if (localName.equals(SchemaSymbols.ELT_ANNOTATION))
824                 continue;
825             else if (localName.equals(SchemaSymbols.ELT_IMPORT)) {
826                 refType = XSDDescription.CONTEXT_IMPORT;
827                 // have to handle some validation here too!
828
// call XSAttributeChecker to fill in attrs
829
Object JavaDoc[] importAttrs = fAttributeChecker.checkAttributes(child, true, currSchemaInfo);
830                 schemaHint = (String JavaDoc)importAttrs[XSAttributeChecker.ATTIDX_SCHEMALOCATION];
831                 schemaNamespace = (String JavaDoc)importAttrs[XSAttributeChecker.ATTIDX_NAMESPACE];
832                 if (schemaNamespace != null)
833                     schemaNamespace = fSymbolTable.addSymbol(schemaNamespace);
834                 // a document can't import another document with the same namespace
835
if (schemaNamespace == currSchemaInfo.fTargetNamespace) {
836                     reportSchemaError("src-import.1.1", new Object JavaDoc [] {schemaNamespace}, child);
837                 }
838                 
839                 // check contents and process optional annotations
840
Element JavaDoc importChild = DOMUtil.getFirstChildElement(child);
841                 if(importChild != null ) {
842                     String JavaDoc importComponentType = DOMUtil.getLocalName(importChild);
843                     if (importComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) {
844                         // promoting annotations to parent component
845
sg.addAnnotation(
846                                 fElementTraverser.traverseAnnotationDecl(importChild, importAttrs, true, currSchemaInfo));
847                     } else {
848                         reportSchemaError("s4s-elt-must-match.1", new Object JavaDoc [] {localName, "annotation?", importComponentType}, child);
849                     }
850                     if(DOMUtil.getNextSiblingElement(importChild) != null) {
851                         reportSchemaError("s4s-elt-must-match.1", new Object JavaDoc [] {localName, "annotation?", DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(importChild))}, child);
852                     }
853                 }
854                 else {
855                     String JavaDoc text = DOMUtil.getSyntheticAnnotation(child);
856                     if (text != null) {
857                         sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, importAttrs, true, currSchemaInfo));
858                     }
859                 }
860                 fAttributeChecker.returnAttrArray(importAttrs, currSchemaInfo);
861                 
862                 // if this namespace has not been imported by this document,
863
// then import if multiple imports support is enabled.
864
if(currSchemaInfo.isAllowedNS(schemaNamespace)) {
865                     if(!fHonourAllSchemaLocations)
866                         continue;
867                 }
868                 else {
869                     currSchemaInfo.addAllowedNS(schemaNamespace);
870                 }
871                 // also record the fact that one namespace imports another one
872
// convert null to ""
873
String JavaDoc tns = null2EmptyString(currSchemaInfo.fTargetNamespace);
874                 // get all namespaces imported by this one
875
Vector JavaDoc ins = (Vector JavaDoc)fImportMap.get(tns);
876                 // if no namespace was imported, create new Vector
877
if (ins == null) {
878                     // record that this one imports other(s)
879
fAllTNSs.addElement(tns);
880                     ins = new Vector JavaDoc();
881                     fImportMap.put(tns, ins);
882                     ins.addElement(schemaNamespace);
883                 }
884                 else if (!ins.contains(schemaNamespace)){
885                     ins.addElement(schemaNamespace);
886                 }
887                 
888                 fSchemaGrammarDescription.reset();
889                 fSchemaGrammarDescription.setContextType(XSDDescription.CONTEXT_IMPORT);
890                 fSchemaGrammarDescription.setBaseSystemId(doc2SystemId(schemaRoot));
891                 fSchemaGrammarDescription.setLocationHints(new String JavaDoc[]{schemaHint});
892                 fSchemaGrammarDescription.setTargetNamespace(schemaNamespace);
893                 
894                 // if a grammar with the same namespace and location exists (or being
895
// built), ignore this one (don't traverse it).
896
if ((!fHonourAllSchemaLocations && findGrammar(fSchemaGrammarDescription) != null) || isExistingGrammar(fSchemaGrammarDescription))
897                     continue;
898                 newSchemaRoot = resolveSchema(fSchemaGrammarDescription, false, child);
899             }
900             else if ((localName.equals(SchemaSymbols.ELT_INCLUDE)) ||
901                     (localName.equals(SchemaSymbols.ELT_REDEFINE))) {
902                 // validation for redefine/include will be the same here; just
903
// make sure TNS is right (don't care about redef contents
904
// yet).
905
Object JavaDoc[] includeAttrs = fAttributeChecker.checkAttributes(child, true, currSchemaInfo);
906                 schemaHint = (String JavaDoc)includeAttrs[XSAttributeChecker.ATTIDX_SCHEMALOCATION];
907                 // store the namespace decls of the redefine element
908
if (localName.equals(SchemaSymbols.ELT_REDEFINE)) {
909                     fRedefine2NSSupport.put(child, new SchemaNamespaceSupport(currSchemaInfo.fNamespaceSupport));
910                 }
911                 
912                 // check annotations. Must do this here to avoid having to
913
// re-parse attributes later
914
if(localName.equals(SchemaSymbols.ELT_INCLUDE)) {
915                     Element JavaDoc includeChild = DOMUtil.getFirstChildElement(child);
916                     if(includeChild != null ) {
917                         String JavaDoc includeComponentType = DOMUtil.getLocalName(includeChild);
918                         if (includeComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) {
919                             // promoting annotations to parent component
920
sg.addAnnotation(
921                                     fElementTraverser.traverseAnnotationDecl(includeChild, includeAttrs, true, currSchemaInfo));
922                         } else {
923                             reportSchemaError("s4s-elt-must-match.1", new Object JavaDoc [] {localName, "annotation?", includeComponentType}, child);
924                         }
925                         if(DOMUtil.getNextSiblingElement(includeChild) != null) {
926                             reportSchemaError("s4s-elt-must-match.1", new Object JavaDoc [] {localName, "annotation?", DOMUtil.getLocalName(DOMUtil.getNextSiblingElement(includeChild))}, child);
927                         }
928                     }
929                     else {
930                         String JavaDoc text = DOMUtil.getSyntheticAnnotation(child);
931                         if (text != null) {
932                             sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, includeAttrs, true, currSchemaInfo));
933                         }
934                     }
935                 }
936                 else {
937                     for (Element JavaDoc redefinedChild = DOMUtil.getFirstChildElement(child);
938                     redefinedChild != null;
939                     redefinedChild = DOMUtil.getNextSiblingElement(redefinedChild)) {
940                         String JavaDoc redefinedComponentType = DOMUtil.getLocalName(redefinedChild);
941                         if (redefinedComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) {
942                             // promoting annotations to parent component
943
sg.addAnnotation(
944                                     fElementTraverser.traverseAnnotationDecl(redefinedChild, includeAttrs, true, currSchemaInfo));
945                             DOMUtil.setHidden(redefinedChild, fHiddenNodes);
946                         }
947                         else {
948                             String JavaDoc text = DOMUtil.getSyntheticAnnotation(child);
949                             if (text != null) {
950                                 sg.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(child, text, includeAttrs, true, currSchemaInfo));
951                             }
952                         }
953                         // catch all other content errors later
954
}
955                 }
956                 fAttributeChecker.returnAttrArray(includeAttrs, currSchemaInfo);
957                 // schemaLocation is required on <include> and <redefine>
958
if (schemaHint == null) {
959                     reportSchemaError("s4s-att-must-appear", new Object JavaDoc [] {
960                             "<include> or <redefine>", "schemaLocation"},
961                             child);
962                 }
963                 // pass the systemId of the current document as the base systemId
964
boolean mustResolve = false;
965                 refType = XSDDescription.CONTEXT_INCLUDE;
966                 if(localName.equals(SchemaSymbols.ELT_REDEFINE)) {
967                     mustResolve = nonAnnotationContent(child);
968                     refType = XSDDescription.CONTEXT_REDEFINE;
969                 }
970                 fSchemaGrammarDescription.reset();
971                 fSchemaGrammarDescription.setContextType(refType);
972                 fSchemaGrammarDescription.setBaseSystemId(doc2SystemId(schemaRoot));
973                 fSchemaGrammarDescription.setLocationHints(new String JavaDoc[]{schemaHint});
974                 fSchemaGrammarDescription.setTargetNamespace(callerTNS);
975                 newSchemaRoot = resolveSchema(fSchemaGrammarDescription, mustResolve, child);
976                 schemaNamespace = currSchemaInfo.fTargetNamespace;
977             }
978             else {
979                 // no more possibility of schema references in well-formed
980
// schema...
981
break;
982             }
983             
984             // If the schema is duplicate, we needn't call constructTrees() again.
985
// To handle mutual <include>s
986
XSDocumentInfo newSchemaInfo = null;
987             if (fLastSchemaWasDuplicate) {
988                 newSchemaInfo = newSchemaRoot == null ? null : (XSDocumentInfo)fDoc2XSDocumentMap.get(newSchemaRoot);
989             }
990             else {
991                 newSchemaInfo = constructTrees(newSchemaRoot, schemaHint, fSchemaGrammarDescription);
992             }
993             
994             if (localName.equals(SchemaSymbols.ELT_REDEFINE) &&
995                     newSchemaInfo != null) {
996                 // must record which schema we're redefining so that we can
997
// rename the right things later!
998
fRedefine2XSDMap.put(child, newSchemaInfo);
999             }
1000            if (newSchemaRoot != null) {
1001                if (newSchemaInfo != null)
1002                    dependencies.addElement(newSchemaInfo);
1003                newSchemaRoot = null;
1004            }
1005        }
1006        
1007        fDependencyMap.put(currSchemaInfo, dependencies);
1008        return currSchemaInfo;
1009    } // end constructTrees
1010

1011    private boolean isExistingGrammar(XSDDescription desc) {
1012        SchemaGrammar sg = fGrammarBucket.getGrammar(desc.getTargetNamespace());
1013        if(sg == null) {
1014            return findGrammar(desc) != null;
1015        }
1016        else {
1017            try {
1018                return sg.getDocumentLocations().contains(XMLEntityManager.expandSystemId(desc.getLiteralSystemId(), desc.getBaseSystemId(), false));
1019            } catch (MalformedURIException e) {
1020                return false;
1021            }
1022        }
1023    }
1024    
1025    // This method builds registries for all globally-referenceable
1026
// names. A registry will be built for each symbol space defined
1027
// by the spec. It is also this method's job to rename redefined
1028
// components, and to record which components redefine others (so
1029
// that implicit redefinitions of groups and attributeGroups can be handled).
1030
protected void buildGlobalNameRegistries() {
1031        
1032
1033        // Starting with fRoot, we examine each child of the schema
1034
// element. Skipping all imports and includes, we record the names
1035
// of all other global components (and children of <redefine>). We
1036
// also put <redefine> names in a registry that we look through in
1037
// case something needs renaming. Once we're done with a schema we
1038
// set its Document node to hidden so that we don't try to traverse
1039
// it again; then we look to its Dependency map entry. We keep a
1040
// stack of schemas that we haven't yet finished processing; this
1041
// is a depth-first traversal.
1042

1043        Stack JavaDoc schemasToProcess = new Stack JavaDoc();
1044        schemasToProcess.push(fRoot);
1045       
1046        while (!schemasToProcess.empty()) {
1047            XSDocumentInfo currSchemaDoc =
1048                (XSDocumentInfo)schemasToProcess.pop();
1049            Element JavaDoc currDoc = currSchemaDoc.fSchemaElement;
1050            if(DOMUtil.isHidden(currDoc, fHiddenNodes)){
1051                // must have processed this already!
1052
continue;
1053            }
1054
1055            Element JavaDoc currRoot = currDoc;
1056            // process this schema's global decls
1057
boolean dependenciesCanOccur = true;
1058            for (Element JavaDoc globalComp =
1059                DOMUtil.getFirstChildElement(currRoot);
1060            globalComp != null;
1061            globalComp = DOMUtil.getNextSiblingElement(globalComp)) {
1062                // this loop makes sure the <schema> element ordering is
1063
// also valid.
1064
if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_ANNOTATION)) {
1065                    //skip it; traverse it later
1066
continue;
1067                }
1068                else if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_INCLUDE) ||
1069                        DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_IMPORT)) {
1070                    if (!dependenciesCanOccur) {
1071                        reportSchemaError("s4s-elt-invalid-content.3", new Object JavaDoc [] {DOMUtil.getLocalName(globalComp)}, globalComp);
1072                    }
1073                    DOMUtil.setHidden(globalComp, fHiddenNodes);
1074                }
1075                else if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_REDEFINE)) {
1076                    if (!dependenciesCanOccur) {
1077                        reportSchemaError("s4s-elt-invalid-content.3", new Object JavaDoc [] {DOMUtil.getLocalName(globalComp)}, globalComp);
1078                    }
1079                    for (Element JavaDoc redefineComp = DOMUtil.getFirstChildElement(globalComp);
1080                    redefineComp != null;
1081                    redefineComp = DOMUtil.getNextSiblingElement(redefineComp)) {
1082                        String JavaDoc lName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME);
1083                        if (lName.length() == 0) // an error we'll catch later
1084
continue;
1085                        String JavaDoc qName = currSchemaDoc.fTargetNamespace == null ?
1086                                ","+lName:
1087                                    currSchemaDoc.fTargetNamespace +","+lName;
1088                        String JavaDoc componentType = DOMUtil.getLocalName(redefineComp);
1089                        if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
1090                            checkForDuplicateNames(qName, fUnparsedAttributeGroupRegistry, fUnparsedAttributeGroupRegistrySub, redefineComp, currSchemaDoc);
1091                            // the check will have changed our name;
1092
String JavaDoc targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME)+REDEF_IDENTIFIER;
1093                            // and all we need to do is error-check+rename our kkids:
1094
renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_ATTRIBUTEGROUP,
1095                                    lName, targetLName);
1096                        }
1097                        else if ((componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) ||
1098                                (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE))) {
1099                            checkForDuplicateNames(qName, fUnparsedTypeRegistry, fUnparsedTypeRegistrySub, redefineComp, currSchemaDoc);
1100                            // the check will have changed our name;
1101
String JavaDoc targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME) + REDEF_IDENTIFIER;
1102                            // and all we need to do is error-check+rename our kkids:
1103
if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
1104                                renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_COMPLEXTYPE,
1105                                        lName, targetLName);
1106                            }
1107                            else { // must be simpleType
1108
renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_SIMPLETYPE,
1109                                        lName, targetLName);
1110                            }
1111                        }
1112                        else if (componentType.equals(SchemaSymbols.ELT_GROUP)) {
1113                            checkForDuplicateNames(qName, fUnparsedGroupRegistry, fUnparsedGroupRegistrySub, redefineComp, currSchemaDoc);
1114                            // the check will have changed our name;
1115
String JavaDoc targetLName = DOMUtil.getAttrValue(redefineComp, SchemaSymbols.ATT_NAME)+REDEF_IDENTIFIER;
1116                            // and all we need to do is error-check+rename our kids:
1117
renameRedefiningComponents(currSchemaDoc, redefineComp, SchemaSymbols.ELT_GROUP,
1118                                    lName, targetLName);
1119                        }
1120                    } // end march through <redefine> children
1121
// and now set as traversed
1122
//DOMUtil.setHidden(globalComp);
1123
}
1124                else {
1125                    dependenciesCanOccur = false;
1126                    String JavaDoc lName = DOMUtil.getAttrValue(globalComp, SchemaSymbols.ATT_NAME);
1127                    if (lName.length() == 0) // an error we'll catch later
1128
continue;
1129                    String JavaDoc qName = currSchemaDoc.fTargetNamespace == null?
1130                            ","+lName:
1131                                currSchemaDoc.fTargetNamespace +","+lName;
1132                    String JavaDoc componentType = DOMUtil.getLocalName(globalComp);
1133                    if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTE)) {
1134                        checkForDuplicateNames(qName, fUnparsedAttributeRegistry, fUnparsedAttributeRegistrySub, globalComp, currSchemaDoc);
1135                    }
1136                    else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
1137                        checkForDuplicateNames(qName, fUnparsedAttributeGroupRegistry, fUnparsedAttributeGroupRegistrySub, globalComp, currSchemaDoc);
1138                    }
1139                    else if ((componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) ||
1140                            (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE))) {
1141                        checkForDuplicateNames(qName, fUnparsedTypeRegistry, fUnparsedTypeRegistrySub, globalComp, currSchemaDoc);
1142                    }
1143                    else if (componentType.equals(SchemaSymbols.ELT_ELEMENT)) {
1144                        checkForDuplicateNames(qName, fUnparsedElementRegistry, fUnparsedElementRegistrySub, globalComp, currSchemaDoc);
1145                    }
1146                    else if (componentType.equals(SchemaSymbols.ELT_GROUP)) {
1147                        checkForDuplicateNames(qName, fUnparsedGroupRegistry, fUnparsedGroupRegistrySub, globalComp, currSchemaDoc);
1148                    }
1149                    else if (componentType.equals(SchemaSymbols.ELT_NOTATION)) {
1150                        checkForDuplicateNames(qName, fUnparsedNotationRegistry, fUnparsedNotationRegistrySub, globalComp, currSchemaDoc);
1151                    }
1152                }
1153            } // end for
1154

1155            // now we're done with this one!
1156
DOMUtil.setHidden(currDoc, fHiddenNodes);
1157            // now add the schemas this guy depends on
1158
Vector JavaDoc currSchemaDepends = (Vector JavaDoc)fDependencyMap.get(currSchemaDoc);
1159            for (int i = 0; i < currSchemaDepends.size(); i++) {
1160                schemasToProcess.push(currSchemaDepends.elementAt(i));
1161            }
1162        } // while
1163

1164    } // end buildGlobalNameRegistries
1165

1166    // Beginning at the first schema processing was requested for
1167
// (fRoot), this method
1168
// examines each child (global schema information item) of each
1169
// schema document (and of each <redefine> element)
1170
// corresponding to an XSDocumentInfo object. If the
1171
// readOnly field on that node has not been set, it calls an
1172
// appropriate traverser to traverse it. Once all global decls in
1173
// an XSDocumentInfo object have been traversed, it marks that object
1174
// as traversed (or hidden) in order to avoid infinite loops. It completes
1175
// when it has visited all XSDocumentInfo objects in the
1176
// DependencyMap and marked them as traversed.
1177
protected void traverseSchemas(ArrayList JavaDoc annotationInfo) {
1178        // the process here is very similar to that in
1179
// buildGlobalRegistries, except we can't set our schemas as
1180
// hidden for a second time; so make them all visible again
1181
// first!
1182
setSchemasVisible(fRoot);
1183        Stack JavaDoc schemasToProcess = new Stack JavaDoc();
1184        schemasToProcess.push(fRoot);
1185        while (!schemasToProcess.empty()) {
1186            XSDocumentInfo currSchemaDoc =
1187                (XSDocumentInfo)schemasToProcess.pop();
1188            Element JavaDoc currDoc = currSchemaDoc.fSchemaElement;
1189       
1190            SchemaGrammar currSG = fGrammarBucket.getGrammar(currSchemaDoc.fTargetNamespace);
1191
1192            if(DOMUtil.isHidden(currDoc, fHiddenNodes)) {
1193                // must have processed this already!
1194
continue;
1195            }
1196            Element JavaDoc currRoot = currDoc;
1197            boolean sawAnnotation = false;
1198            // traverse this schema's global decls
1199
for (Element JavaDoc globalComp =
1200                DOMUtil.getFirstVisibleChildElement(currRoot, fHiddenNodes);
1201            globalComp != null;
1202            globalComp = DOMUtil.getNextVisibleSiblingElement(globalComp, fHiddenNodes)) {
1203                DOMUtil.setHidden(globalComp, fHiddenNodes);
1204                String JavaDoc componentType = DOMUtil.getLocalName(globalComp);
1205                // includes and imports will not show up here!
1206
if (DOMUtil.getLocalName(globalComp).equals(SchemaSymbols.ELT_REDEFINE)) {
1207                    // use the namespace decls for the redefine, instead of for the parent <schema>
1208
currSchemaDoc.backupNSSupport((SchemaNamespaceSupport)fRedefine2NSSupport.get(globalComp));
1209                    for (Element JavaDoc redefinedComp = DOMUtil.getFirstVisibleChildElement(globalComp, fHiddenNodes);
1210                    redefinedComp != null;
1211                    redefinedComp = DOMUtil.getNextVisibleSiblingElement(redefinedComp, fHiddenNodes)) {
1212                        String JavaDoc redefinedComponentType = DOMUtil.getLocalName(redefinedComp);
1213                        DOMUtil.setHidden(redefinedComp, fHiddenNodes);
1214                        if (redefinedComponentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
1215                            fAttributeGroupTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG);
1216                        }
1217                        else if (redefinedComponentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
1218                            fComplexTypeTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG);
1219                        }
1220                        else if (redefinedComponentType.equals(SchemaSymbols.ELT_GROUP)) {
1221                            fGroupTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG);
1222                        }
1223                        else if (redefinedComponentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
1224                            fSimpleTypeTraverser.traverseGlobal(redefinedComp, currSchemaDoc, currSG);
1225                        }
1226                        // annotations will have been processed already; this is now
1227
// unnecessary
1228
//else if (redefinedComponentType.equals(SchemaSymbols.ELT_ANNOTATION)) {
1229
// fElementTraverser.traverseAnnotationDecl(redefinedComp, null, true, currSchemaDoc);
1230
//}
1231
else {
1232                            reportSchemaError("s4s-elt-must-match.1", new Object JavaDoc [] {DOMUtil.getLocalName(globalComp), "(annotation | (simpleType | complexType | group | attributeGroup))*", redefinedComponentType}, redefinedComp);
1233                        }
1234                    } // end march through <redefine> children
1235
currSchemaDoc.restoreNSSupport();
1236                }
1237                else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTE)) {
1238                    fAttributeTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG);
1239                }
1240                else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
1241                    fAttributeGroupTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG);
1242                }
1243                else if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
1244                    fComplexTypeTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG);
1245                }
1246                else if (componentType.equals(SchemaSymbols.ELT_ELEMENT)) {
1247                    fElementTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG);
1248                }
1249                else if (componentType.equals(SchemaSymbols.ELT_GROUP)) {
1250                    fGroupTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG);
1251                }
1252                else if (componentType.equals(SchemaSymbols.ELT_NOTATION)) {
1253                    fNotationTraverser.traverse(globalComp, currSchemaDoc, currSG);
1254                }
1255                else if (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
1256                    fSimpleTypeTraverser.traverseGlobal(globalComp, currSchemaDoc, currSG);
1257                }
1258                else if (componentType.equals(SchemaSymbols.ELT_ANNOTATION)) {
1259                    currSG.addAnnotation(fElementTraverser.traverseAnnotationDecl(globalComp, currSchemaDoc.getSchemaAttrs(), true, currSchemaDoc));
1260                    sawAnnotation = true;
1261                }
1262                else {
1263                    reportSchemaError("s4s-elt-invalid-content.1", new Object JavaDoc [] {SchemaSymbols.ELT_SCHEMA, DOMUtil.getLocalName(globalComp)}, globalComp);
1264                }
1265            } // end for
1266

1267            if (!sawAnnotation) {
1268                String JavaDoc text = DOMUtil.getSyntheticAnnotation(currRoot);
1269                if (text != null) {
1270                    currSG.addAnnotation(fElementTraverser.traverseSyntheticAnnotation(currRoot, text, currSchemaDoc.getSchemaAttrs(), true, currSchemaDoc));
1271                }
1272            }
1273            
1274            /** Collect annotation information for validation. **/
1275            if (annotationInfo != null) {
1276                XSAnnotationInfo info = currSchemaDoc.getAnnotations();
1277                /** Only add annotations to the list if there were any in this document. **/
1278                if (info != null) {
1279                    annotationInfo.add(doc2SystemId(currDoc));
1280                    annotationInfo.add(info);
1281                }
1282            }
1283            // now we're done with this one!
1284
currSchemaDoc.returnSchemaAttrs();
1285            DOMUtil.setHidden(currDoc, fHiddenNodes);
1286
1287            // now add the schemas this guy depends on
1288
Vector JavaDoc currSchemaDepends = (Vector JavaDoc)fDependencyMap.get(currSchemaDoc);
1289            for (int i = 0; i < currSchemaDepends.size(); i++) {
1290                schemasToProcess.push(currSchemaDepends.elementAt(i));
1291            }
1292        } // while
1293
} // end traverseSchemas
1294

1295    // store whether we have reported an error about that no grammar
1296
// is found for the given namespace uri
1297
private Vector JavaDoc fReportedTNS = null;
1298    // check whether we need to report an error against the given uri.
1299
// if we have reported an error, then we don't need to report again;
1300
// otherwise we reported the error, and remember this fact.
1301
private final boolean needReportTNSError(String JavaDoc uri) {
1302        if (fReportedTNS == null)
1303            fReportedTNS = new Vector JavaDoc();
1304        else if (fReportedTNS.contains(uri))
1305            return false;
1306        fReportedTNS.addElement(uri);
1307        return true;
1308    }
1309    
1310    private static final String JavaDoc[] COMP_TYPE = {
1311            null, // index 0
1312
"attribute declaration",
1313            "attribute group",
1314            "element declaration",
1315            "group",
1316            "identity constraint",
1317            "notation",
1318            "type definition",
1319    };
1320    
1321    private static final String JavaDoc[] CIRCULAR_CODES = {
1322            "Internal-Error",
1323            "Internal-Error",
1324            "src-attribute_group.3",
1325            "e-props-correct.6",
1326            "mg-props-correct.2",
1327            "Internal-Error",
1328            "Internal-Error",
1329            "st-props-correct.2", //or ct-props-correct.3
1330
};
1331    
1332    // since it is forbidden for traversers to talk to each other
1333
// directly (except wen a traverser encounters a local declaration),
1334
// this provides a generic means for a traverser to call
1335
// for the traversal of some declaration. An XSDocumentInfo is
1336
// required because the XSDocumentInfo that the traverser is traversing
1337
// may bear no relation to the one the handler is operating on.
1338
// This method will:
1339
// 1. See if a global definition matching declToTraverse exists;
1340
// 2. if so, determine if there is a path from currSchema to the
1341
// schema document where declToTraverse lives (i.e., do a lookup
1342
// in DependencyMap);
1343
// 3. depending on declType (which will be relevant to step 1 as
1344
// well), call the appropriate traverser with the appropriate
1345
// XSDocumentInfo object.
1346
// This method returns whatever the traverser it called returned;
1347
// this will be an Object of some kind
1348
// that lives in the Grammar.
1349
protected Object JavaDoc getGlobalDecl(XSDocumentInfo currSchema,
1350            int declType,
1351            QName declToTraverse,
1352            Element JavaDoc elmNode) {
1353        
1354        if (DEBUG_NODE_POOL) {
1355            System.out.println("TRAVERSE_GL: "+declToTraverse.toString());
1356        }
1357        // from the schema spec, all built-in types are present in all schemas,
1358
// so if the requested component is a type, and could be found in the
1359
// default schema grammar, we should return that type.
1360
// otherwise (since we would support user-defined schema grammar) we'll
1361
// use the normal way to get the decl
1362
if (declToTraverse.uri != null &&
1363                declToTraverse.uri == SchemaSymbols.URI_SCHEMAFORSCHEMA) {
1364            if (declType == TYPEDECL_TYPE) {
1365                Object JavaDoc retObj = SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(declToTraverse.localpart);
1366                if (retObj != null)
1367                    return retObj;
1368            }
1369        }
1370        
1371        // now check whether this document can access the requsted namespace
1372
if (!currSchema.isAllowedNS(declToTraverse.uri)) {
1373            // cannot get to this schema from the one containing the requesting decl
1374
if (currSchema.needReportTNSError(declToTraverse.uri)) {
1375                String JavaDoc code = declToTraverse.uri == null ? "src-resolve.4.1" : "src-resolve.4.2";
1376                reportSchemaError(code, new Object JavaDoc[]{fDoc2SystemId.get(currSchema.fSchemaElement), declToTraverse.uri, declToTraverse.rawname}, elmNode);
1377            }
1378            return null;
1379        }
1380        
1381        // check whether there is grammar for the requested namespace
1382
SchemaGrammar sGrammar = fGrammarBucket.getGrammar(declToTraverse.uri);
1383        if (sGrammar == null) {
1384            if (needReportTNSError(declToTraverse.uri))
1385                reportSchemaError("src-resolve", new Object JavaDoc[]{declToTraverse.rawname, COMP_TYPE[declType]}, elmNode);
1386            return null;
1387        }
1388        
1389        // if there is such grammar, check whether the requested component is in the grammar
1390
Object JavaDoc retObj = null;
1391        switch (declType) {
1392        case ATTRIBUTE_TYPE :
1393            retObj = sGrammar.getGlobalAttributeDecl(declToTraverse.localpart);
1394            break;
1395        case ATTRIBUTEGROUP_TYPE :
1396            retObj = sGrammar.getGlobalAttributeGroupDecl(declToTraverse.localpart);
1397            break;
1398        case ELEMENT_TYPE :
1399            retObj = sGrammar.getGlobalElementDecl(declToTraverse.localpart);
1400            break;
1401        case GROUP_TYPE :
1402            retObj = sGrammar.getGlobalGroupDecl(declToTraverse.localpart);
1403            break;
1404        case IDENTITYCONSTRAINT_TYPE :
1405            retObj = sGrammar.getIDConstraintDecl(declToTraverse.localpart);
1406            break;
1407        case NOTATION_TYPE :
1408            retObj = sGrammar.getGlobalNotationDecl(declToTraverse.localpart);
1409            break;
1410        case TYPEDECL_TYPE :
1411            retObj = sGrammar.getGlobalTypeDecl(declToTraverse.localpart);
1412            break;
1413        }
1414        
1415        // if the component is parsed, return it
1416
if (retObj != null)
1417            return retObj;
1418        
1419        XSDocumentInfo schemaWithDecl = null;
1420        Element JavaDoc decl = null;
1421        XSDocumentInfo declDoc = null;
1422        
1423        // the component is not parsed, try to find a DOM element for it
1424
String JavaDoc declKey = declToTraverse.uri == null? ","+declToTraverse.localpart:
1425            declToTraverse.uri+","+declToTraverse.localpart;
1426        switch (declType) {
1427        case ATTRIBUTE_TYPE :
1428            decl = (Element JavaDoc)fUnparsedAttributeRegistry.get(declKey);
1429            declDoc = (XSDocumentInfo)fUnparsedAttributeRegistrySub.get(declKey);
1430            break;
1431        case ATTRIBUTEGROUP_TYPE :
1432            decl = (Element JavaDoc)fUnparsedAttributeGroupRegistry.get(declKey);
1433            declDoc = (XSDocumentInfo)fUnparsedAttributeGroupRegistrySub.get(declKey);
1434            break;
1435        case ELEMENT_TYPE :
1436            decl = (Element JavaDoc)fUnparsedElementRegistry.get(declKey);
1437            declDoc = (XSDocumentInfo)fUnparsedElementRegistrySub.get(declKey);
1438            break;
1439        case GROUP_TYPE :
1440            decl = (Element JavaDoc)fUnparsedGroupRegistry.get(declKey);
1441            declDoc = (XSDocumentInfo)fUnparsedGroupRegistrySub.get(declKey);
1442            break;
1443        case IDENTITYCONSTRAINT_TYPE :
1444            decl = (Element JavaDoc)fUnparsedIdentityConstraintRegistry.get(declKey);
1445            declDoc = (XSDocumentInfo)fUnparsedIdentityConstraintRegistrySub.get(declKey);
1446            break;
1447        case NOTATION_TYPE :
1448            decl = (Element JavaDoc)fUnparsedNotationRegistry.get(declKey);
1449            declDoc = (XSDocumentInfo)fUnparsedNotationRegistrySub.get(declKey);
1450            break;
1451        case TYPEDECL_TYPE :
1452            decl = (Element JavaDoc)fUnparsedTypeRegistry.get(declKey);
1453            declDoc = (XSDocumentInfo)fUnparsedTypeRegistrySub.get(declKey);
1454            break;
1455        default:
1456            reportSchemaError("Internal-Error", new Object JavaDoc [] {"XSDHandler asked to locate component of type " + declType + "; it does not recognize this type!"}, elmNode);
1457        }
1458        
1459        // no DOM element found, so the component can't be located
1460
if (decl == null) {
1461            reportSchemaError("src-resolve", new Object JavaDoc[]{declToTraverse.rawname, COMP_TYPE[declType]}, elmNode);
1462            return null;
1463        }
1464        
1465        // get the schema doc containing the component to be parsed
1466
// it should always return non-null value, but since null-checking
1467
// comes for free, let's be safe and check again
1468
schemaWithDecl = findXSDocumentForDecl(currSchema, decl, declDoc);
1469        if (schemaWithDecl == null) {
1470            // cannot get to this schema from the one containing the requesting decl
1471
String JavaDoc code = declToTraverse.uri == null ? "src-resolve.4.1" : "src-resolve.4.2";
1472            reportSchemaError(code, new Object JavaDoc[]{fDoc2SystemId.get(currSchema.fSchemaElement), declToTraverse.uri, declToTraverse.rawname}, elmNode);
1473            return null;
1474        }
1475        // a component is hidden, meaning either it's traversed, or being traversed.
1476
// but we didn't find it in the grammar, so it's the latter case, and
1477
// a circular reference. error!
1478
if (DOMUtil.isHidden(decl, fHiddenNodes)) {
1479            String JavaDoc code = CIRCULAR_CODES[declType];
1480            if (declType == TYPEDECL_TYPE) {
1481                if (SchemaSymbols.ELT_COMPLEXTYPE.equals(DOMUtil.getLocalName(decl)))
1482                    code = "ct-props-correct.3";
1483            }
1484            // decl must not be null if we're here...
1485
reportSchemaError(code, new Object JavaDoc [] {declToTraverse.prefix+":"+declToTraverse.localpart}, elmNode);
1486            return null;
1487        }
1488        
1489        DOMUtil.setHidden(decl, fHiddenNodes);
1490        SchemaNamespaceSupport nsSupport = null;
1491        // if the parent is <redefine> use the namespace delcs for it.
1492
Element JavaDoc parent = DOMUtil.getParent(decl);
1493        if (DOMUtil.getLocalName(parent).equals(SchemaSymbols.ELT_REDEFINE))
1494            nsSupport = (SchemaNamespaceSupport)fRedefine2NSSupport.get(parent);
1495        // back up the current SchemaNamespaceSupport, because we need to provide
1496
// a fresh one to the traverseGlobal methods.
1497
schemaWithDecl.backupNSSupport(nsSupport);
1498        
1499        // traverse the referenced global component
1500
switch (declType) {
1501        case ATTRIBUTE_TYPE :
1502            retObj = fAttributeTraverser.traverseGlobal(decl, schemaWithDecl, sGrammar);
1503            break;
1504        case ATTRIBUTEGROUP_TYPE :
1505            retObj = fAttributeGroupTraverser.traverseGlobal(decl, schemaWithDecl, sGrammar);
1506            break;
1507        case ELEMENT_TYPE :
1508            retObj = fElementTraverser.traverseGlobal(decl, schemaWithDecl, sGrammar);
1509            break;
1510        case GROUP_TYPE :
1511            retObj = fGroupTraverser.traverseGlobal(decl, schemaWithDecl, sGrammar);
1512            break;
1513        case IDENTITYCONSTRAINT_TYPE :
1514            // identity constraints should have been parsed already...
1515
// we should never get here
1516
retObj = null;
1517            break;
1518        case NOTATION_TYPE :
1519            retObj = fNotationTraverser.traverse(decl, schemaWithDecl, sGrammar);
1520            break;
1521        case TYPEDECL_TYPE :
1522            if (DOMUtil.getLocalName(decl).equals(SchemaSymbols.ELT_COMPLEXTYPE))
1523                retObj = fComplexTypeTraverser.traverseGlobal(decl, schemaWithDecl, sGrammar);
1524            else
1525                retObj = fSimpleTypeTraverser.traverseGlobal(decl, schemaWithDecl, sGrammar);
1526        }
1527        
1528        // restore the previous SchemaNamespaceSupport, so that the caller can get
1529
// proper namespace binding.
1530
schemaWithDecl.restoreNSSupport();
1531        
1532        return retObj;
1533    } // getGlobalDecl(XSDocumentInfo, int, QName): Object
1534

1535    // This method determines whether there is a group
1536
// (attributeGroup) which the given one has redefined by
1537
// restriction. If so, it returns it; else it returns null.
1538
// @param type: whether what's been redefined is an
1539
// attributeGroup or a group;
1540
// @param name: the QName of the component doing the redefining.
1541
// @param currSchema: schema doc in which the redefining component lives.
1542
// @return: Object representing decl redefined if present, null
1543
// otherwise.
1544
Object JavaDoc getGrpOrAttrGrpRedefinedByRestriction(int type, QName name, XSDocumentInfo currSchema, Element JavaDoc elmNode) {
1545        String JavaDoc realName = name.uri != null?name.uri+","+name.localpart:
1546            ","+name.localpart;
1547        String JavaDoc nameToFind = null;
1548        switch (type) {
1549        case ATTRIBUTEGROUP_TYPE:
1550            nameToFind = (String JavaDoc)fRedefinedRestrictedAttributeGroupRegistry.get(realName);
1551            break;
1552        case GROUP_TYPE:
1553            nameToFind = (String JavaDoc)fRedefinedRestrictedGroupRegistry.get(realName);
1554            break;
1555        default:
1556            return null;
1557        }
1558        if (nameToFind == null) return null;
1559        int commaPos = nameToFind.indexOf(",");
1560        QName qNameToFind = new QName(XMLSymbols.EMPTY_STRING, nameToFind.substring(commaPos+1),
1561                nameToFind.substring(commaPos), (commaPos == 0)? null : nameToFind.substring(0, commaPos));
1562        Object JavaDoc retObj = getGlobalDecl(currSchema, type, qNameToFind, elmNode);
1563        if(retObj == null) {
1564            switch (type) {
1565            case ATTRIBUTEGROUP_TYPE:
1566                reportSchemaError("src-redefine.7.2.1", new Object JavaDoc []{name.localpart}, elmNode);
1567                break;
1568            case GROUP_TYPE:
1569                reportSchemaError("src-redefine.6.2.1", new Object JavaDoc []{name.localpart}, elmNode);
1570                break;
1571            }
1572            return null;
1573        }
1574        return retObj;
1575    } // getGrpOrAttrGrpRedefinedByRestriction(int, QName, XSDocumentInfo): Object
1576

1577    // Since ID constraints can occur in local elements, unless we
1578
// wish to completely traverse all our DOM trees looking for ID
1579
// constraints while we're building our global name registries,
1580
// which seems terribly inefficient, we need to resolve keyrefs
1581
// after all parsing is complete. This we can simply do by running through
1582
// fIdentityConstraintRegistry and calling traverseKeyRef on all
1583
// of the KeyRef nodes. This unfortunately removes this knowledge
1584
// from the elementTraverser class (which must ignore keyrefs),
1585
// but there seems to be no efficient way around this...
1586
protected void resolveKeyRefs() {
1587        for (int i=0; i<fKeyrefStackPos; i++) {
1588            XSDocumentInfo keyrefSchemaDoc = fKeyrefsMapXSDocumentInfo[i];
1589            keyrefSchemaDoc.fNamespaceSupport.makeGlobal();
1590            keyrefSchemaDoc.fNamespaceSupport.setEffectiveContext( fKeyrefNamespaceContext[i] );
1591            SchemaGrammar keyrefGrammar = fGrammarBucket.getGrammar(keyrefSchemaDoc.fTargetNamespace);
1592            // need to set <keyref> to hidden before traversing it,
1593
// because it has global scope
1594
DOMUtil.setHidden(fKeyrefs[i], fHiddenNodes);
1595            fKeyrefTraverser.traverse(fKeyrefs[i], fKeyrefElems[i], keyrefSchemaDoc, keyrefGrammar);
1596        }
1597    } // end resolveKeyRefs
1598

1599    // an accessor method. Just makes sure callers
1600
// who want the Identity constraint registry vaguely know what they're about.
1601
protected Hashtable JavaDoc getIDRegistry() {
1602        return fUnparsedIdentityConstraintRegistry;
1603    }
1604    // an accessor method.
1605
protected Hashtable JavaDoc getIDRegistry_sub() {
1606        return fUnparsedIdentityConstraintRegistrySub;
1607    }
1608    
1609   
1610    
1611    // This method squirrels away <keyref> declarations--along with the element
1612
// decls and namespace bindings they might find handy.
1613
protected void storeKeyRef (Element JavaDoc keyrefToStore, XSDocumentInfo schemaDoc,
1614            XSElementDecl currElemDecl) {
1615        String JavaDoc keyrefName = DOMUtil.getAttrValue(keyrefToStore, SchemaSymbols.ATT_NAME);
1616        if (keyrefName.length() != 0) {
1617            String JavaDoc keyrefQName = schemaDoc.fTargetNamespace == null?
1618                    "," + keyrefName: schemaDoc.fTargetNamespace+","+keyrefName;
1619            checkForDuplicateNames(keyrefQName, fUnparsedIdentityConstraintRegistry, fUnparsedIdentityConstraintRegistrySub, keyrefToStore, schemaDoc);
1620        }
1621        // now set up all the registries we'll need...
1622

1623        // check array sizes
1624
if (fKeyrefStackPos == fKeyrefs.length) {
1625            Element JavaDoc [] elemArray = new Element JavaDoc [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT];
1626            System.arraycopy(fKeyrefs, 0, elemArray, 0, fKeyrefStackPos);
1627            fKeyrefs = elemArray;
1628            XSElementDecl [] declArray = new XSElementDecl [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT];
1629            System.arraycopy(fKeyrefElems, 0, declArray, 0, fKeyrefStackPos);
1630            fKeyrefElems = declArray;
1631            String JavaDoc[][] stringArray = new String JavaDoc [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT][];
1632            System.arraycopy(fKeyrefNamespaceContext, 0, stringArray, 0, fKeyrefStackPos);
1633            fKeyrefNamespaceContext = stringArray;
1634            
1635            XSDocumentInfo [] xsDocumentInfo = new XSDocumentInfo [fKeyrefStackPos + INC_KEYREF_STACK_AMOUNT];
1636            System.arraycopy(fKeyrefsMapXSDocumentInfo, 0, xsDocumentInfo, 0, fKeyrefStackPos);
1637            fKeyrefsMapXSDocumentInfo = xsDocumentInfo;
1638            
1639        }
1640        fKeyrefs[fKeyrefStackPos] = keyrefToStore;
1641        fKeyrefElems[fKeyrefStackPos] = currElemDecl;
1642        fKeyrefNamespaceContext[fKeyrefStackPos] = schemaDoc.fNamespaceSupport.getEffectiveLocalContext();
1643        
1644        fKeyrefsMapXSDocumentInfo[fKeyrefStackPos++] = schemaDoc;
1645    } // storeKeyref (Element, XSDocumentInfo, XSElementDecl): void
1646

1647    
1648    /**
1649     * resolveSchema method is responsible for resolving location of the schema (using XMLEntityResolver),
1650     * and if it was succefully resolved getting the schema Document.
1651     * @param desc
1652     * @param mustResolve
1653     * @param referElement
1654     * @return A schema Element or null.
1655     */

1656    private Element JavaDoc resolveSchema(XSDDescription desc,
1657              boolean mustResolve, Element JavaDoc referElement) {
1658        XMLInputSource schemaSource = null;
1659        try {
1660            schemaSource = XMLSchemaLoader.resolveDocument(desc, fLocationPairs, fEntityResolver);
1661        }
1662        catch (IOException JavaDoc ex) {
1663            if (mustResolve) {
1664                reportSchemaError("schema_reference.4",
1665                        new Object JavaDoc[]{desc.getLocationHints()[0]},
1666                        referElement);
1667            }
1668            else {
1669                reportSchemaWarning("schema_reference.4",
1670                        new Object JavaDoc[]{desc.getLocationHints()[0]},
1671                        referElement);
1672            }
1673        }
1674        if (schemaSource instanceof DOMInputSource) {
1675            fHiddenNodes.clear();
1676            Node JavaDoc node = ((DOMInputSource)schemaSource).getNode();
1677 
1678            if (node instanceof Document JavaDoc) {
1679                return DOMUtil.getRoot((Document JavaDoc) node);
1680            }
1681            else if (node instanceof Element JavaDoc) {
1682                return (Element JavaDoc) node;
1683            }
1684            else {
1685                return null;
1686            }
1687        } // DOMInputSource
1688
else if (schemaSource instanceof SAXInputSource) {
1689            XMLReader JavaDoc parser = ((SAXInputSource)schemaSource).getXMLReader();
1690            InputSource inputSource = ((SAXInputSource)schemaSource).getInputSource();
1691            boolean namespacePrefixes = false;
1692            if (parser != null) {
1693                try {
1694                    namespacePrefixes = parser.getFeature(NAMESPACE_PREFIXES);
1695                }
1696                catch (SAXException JavaDoc se) {}
1697            }
1698            else {
1699                try {
1700                    parser = XMLReaderFactory.createXMLReader();
1701                }
1702                // If something went wrong with the factory
1703
// just use our own SAX parser.
1704
catch (SAXException JavaDoc se) {
1705                    parser = new SAXParser();
1706                }
1707                try {
1708                    parser.setFeature(NAMESPACE_PREFIXES, true);
1709                    namespacePrefixes = true;
1710                }
1711                catch (SAXException JavaDoc se) {}
1712            }
1713            // If XML names and Namespace URIs are already internalized we
1714
// can avoid running them through the SymbolTable.
1715
boolean stringsInternalized = false;
1716            try {
1717                stringsInternalized = parser.getFeature(STRING_INTERNING);
1718            }
1719            catch (SAXException JavaDoc exc) {
1720                // The feature isn't recognized or getting it is not supported.
1721
// In either case, assume that strings are not internalized.
1722
}
1723            if (fXSContentHandler == null) {
1724                fXSContentHandler = new SchemaContentHandler();
1725            }
1726            fXSContentHandler.reset(fSchemaParser, fSymbolTable,
1727                    namespacePrefixes, stringsInternalized);
1728            parser.setContentHandler(fXSContentHandler);
1729            parser.setErrorHandler(fErrorReporter.getSAXErrorHandler());
1730            try {
1731                parser.parse(inputSource);
1732            }
1733            catch (SAXException JavaDoc se) {
1734                return null;
1735            }
1736            catch (IOException JavaDoc ioe) {
1737                return null;
1738            }
1739            Document JavaDoc root = fXSContentHandler.getDocument();
1740            if (root == null) {
1741                // something went wrong right off the hop
1742
return null;
1743            }
1744            return DOMUtil.getRoot(root);
1745        }
1746        return getSchemaDocument(desc.getTargetNamespace(), schemaSource, mustResolve, desc.getContextType(), referElement);
1747    } // getSchema(String, String, String, boolean, short): Document
1748

1749    /**
1750     * getSchemaDocument method uses XMLInputSource to parse a schema document.
1751     * @param schemaNamespace
1752     * @param schemaSource
1753     * @param mustResolve
1754     * @param referType
1755     * @param referElement
1756     * @return A schema Element.
1757     */

1758    private Element JavaDoc getSchemaDocument(String JavaDoc schemaNamespace, XMLInputSource schemaSource,
1759            boolean mustResolve, short referType, Element JavaDoc referElement) {
1760        
1761        boolean hasInput = true;
1762        // contents of this method will depend on the system we adopt for entity resolution--i.e., XMLEntityHandler, EntityHandler, etc.
1763
Element JavaDoc schemaElement = null;
1764        try {
1765            // when the system id and byte stream and character stream
1766
// of the input source are all null, it's
1767
// impossible to find the schema document. so we skip in
1768
// this case. otherwise we'll receive some NPE or
1769
// file not found errors. but schemaHint=="" is perfectly
1770
// legal for import.
1771
if (schemaSource != null &&
1772                    (schemaSource.getSystemId() != null ||
1773                            schemaSource.getByteStream() != null ||
1774                            schemaSource.getCharacterStream() != null)) {
1775                
1776                // When the system id of the input source is used, first try to
1777
// expand it, and check whether the same document has been
1778
// parsed before. If so, return the document corresponding to
1779
// that system id.
1780
XSDKey key = null;
1781                String JavaDoc schemaId = null;
1782                if (referType != XSDDescription.CONTEXT_PREPARSE){
1783                    schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false);
1784                    key = new XSDKey(schemaId, referType, schemaNamespace);
1785                    if((schemaElement = (Element JavaDoc)fTraversed.get(key)) != null) {
1786                        fLastSchemaWasDuplicate = true;
1787                        return schemaElement;
1788                    }
1789                }
1790                
1791                fSchemaParser.parse(schemaSource);
1792                schemaElement = fSchemaParser.getDocument2() == null ? null: DOMUtil.getRoot(fSchemaParser.getDocument2());
1793                
1794                // now we need to store the mapping information from system id
1795
// to the document. also from the document to the system id.
1796
if (key != null)
1797                    fTraversed.put(key, schemaElement );
1798                if (schemaId != null)
1799                    fDoc2SystemId.put(schemaElement, schemaId );
1800                fLastSchemaWasDuplicate = false;
1801                return schemaElement;
1802            }
1803            else {
1804                hasInput = false;
1805            }
1806        }
1807        catch (IOException JavaDoc ex) {
1808        }
1809        
1810        // either an error occured (exception), or empty input source was
1811
// returned, we need to report an error or a warning
1812
if (mustResolve) {
1813            if (hasInput) {
1814                reportSchemaError("schema_reference.4",
1815                        new Object JavaDoc[]{schemaSource.getSystemId()},
1816                        referElement);
1817            }
1818            else {
1819                reportSchemaError("schema_reference.4",
1820                        new Object JavaDoc[]{schemaSource == null ? "" : schemaSource.getSystemId()},
1821                        referElement);
1822            }
1823        }
1824        else if (hasInput) {
1825            reportSchemaWarning("schema_reference.4",
1826                    new Object JavaDoc[]{schemaSource.getSystemId()},
1827                    referElement);
1828        }
1829        
1830        fLastSchemaWasDuplicate = false;
1831        return null;
1832    } // getSchema(String, XMLInputSource, boolean, boolean): Document
1833

1834    // initialize all the traversers.
1835
// this should only need to be called once during the construction
1836
// of this object; it creates the traversers that will be used to
1837

1838    // construct schemaGrammars.
1839
private void createTraversers() {
1840        fAttributeChecker = new XSAttributeChecker(this);
1841        fAttributeGroupTraverser = new XSDAttributeGroupTraverser(this, fAttributeChecker);
1842        fAttributeTraverser = new XSDAttributeTraverser(this, fAttributeChecker);
1843        fComplexTypeTraverser = new XSDComplexTypeTraverser(this, fAttributeChecker);
1844        fElementTraverser = new XSDElementTraverser(this, fAttributeChecker);
1845        fGroupTraverser = new XSDGroupTraverser(this, fAttributeChecker);
1846        fKeyrefTraverser = new XSDKeyrefTraverser(this, fAttributeChecker);
1847        fNotationTraverser = new XSDNotationTraverser(this, fAttributeChecker);
1848        fSimpleTypeTraverser = new XSDSimpleTypeTraverser(this, fAttributeChecker);
1849        fUniqueOrKeyTraverser = new XSDUniqueOrKeyTraverser(this, fAttributeChecker);
1850        fWildCardTraverser = new XSDWildcardTraverser(this, fAttributeChecker);
1851    } // createTraversers()
1852

1853    // before parsing a schema, need to clear registries associated with
1854
// parsing schemas
1855
void prepareForParse() {
1856        fTraversed.clear();
1857        fDoc2SystemId.clear();
1858        fHiddenNodes.clear();
1859        fLastSchemaWasDuplicate = false;
1860    }
1861    
1862    // before traversing a schema's parse tree, need to reset all traversers and
1863
// clear all registries
1864
void prepareForTraverse() {
1865        fUnparsedAttributeRegistry.clear();
1866        fUnparsedAttributeGroupRegistry.clear();
1867        fUnparsedElementRegistry.clear();
1868        fUnparsedGroupRegistry.clear();
1869        fUnparsedIdentityConstraintRegistry.clear();
1870        fUnparsedNotationRegistry.clear();
1871        fUnparsedTypeRegistry.clear();
1872        
1873        fUnparsedAttributeRegistrySub.clear();
1874        fUnparsedAttributeGroupRegistrySub.clear();
1875        fUnparsedElementRegistrySub.clear();
1876        fUnparsedGroupRegistrySub.clear();
1877        fUnparsedIdentityConstraintRegistrySub.clear();
1878        fUnparsedNotationRegistrySub.clear();
1879        fUnparsedTypeRegistrySub.clear();
1880        
1881        fXSDocumentInfoRegistry.clear();
1882        fDependencyMap.clear();
1883        fDoc2XSDocumentMap.clear();
1884        fRedefine2XSDMap.clear();
1885        fRedefine2NSSupport.clear();
1886        fAllTNSs.removeAllElements();
1887        fImportMap.clear();
1888        fRoot = null;
1889        
1890        // clear local element stack
1891
for (int i = 0; i < fLocalElemStackPos; i++) {
1892            fParticle[i] = null;
1893            fLocalElementDecl[i] = null;
1894            fLocalElementDecl_schema[i] = null;
1895            fLocalElemNamespaceContext[i] = null;
1896        }
1897        fLocalElemStackPos = 0;
1898        
1899        // and do same for keyrefs.
1900
for (int i = 0; i < fKeyrefStackPos; i++) {
1901            fKeyrefs[i] = null;
1902            fKeyrefElems[i] = null;
1903            fKeyrefNamespaceContext[i] = null;
1904            fKeyrefsMapXSDocumentInfo[i] = null;
1905        }
1906        fKeyrefStackPos = 0;
1907        
1908        // create traversers if necessary
1909
if (fAttributeChecker == null) {
1910            createTraversers();
1911        }
1912        
1913        // reset traversers
1914
fAttributeChecker.reset(fSymbolTable);
1915        fAttributeGroupTraverser.reset(fSymbolTable, fValidateAnnotations);
1916        fAttributeTraverser.reset(fSymbolTable, fValidateAnnotations);
1917        fComplexTypeTraverser.reset(fSymbolTable, fValidateAnnotations);
1918        fElementTraverser.reset(fSymbolTable, fValidateAnnotations);
1919        fGroupTraverser.reset(fSymbolTable, fValidateAnnotations);
1920        fKeyrefTraverser.reset(fSymbolTable, fValidateAnnotations);
1921        fNotationTraverser.reset(fSymbolTable, fValidateAnnotations);
1922        fSimpleTypeTraverser.reset(fSymbolTable, fValidateAnnotations);
1923        fUniqueOrKeyTraverser.reset(fSymbolTable, fValidateAnnotations);
1924        fWildCardTraverser.reset(fSymbolTable, fValidateAnnotations);
1925        
1926        fRedefinedRestrictedAttributeGroupRegistry.clear();
1927        fRedefinedRestrictedGroupRegistry.clear();
1928    }
1929    public void setDeclPool (XSDeclarationPool declPool){
1930        fDeclPool = declPool;
1931    }
1932    
1933    public void reset(XMLComponentManager componentManager) {
1934        
1935        // set symbol table
1936
fSymbolTable = (SymbolTable) componentManager.getProperty(SYMBOL_TABLE);
1937        
1938        //set entity resolver
1939
fEntityResolver = (XMLEntityResolver) componentManager.getProperty(ENTITY_MANAGER);
1940        XMLEntityResolver er = (XMLEntityResolver)componentManager.getProperty(ENTITY_RESOLVER);
1941        if (er != null)
1942            fSchemaParser.setEntityResolver(er);
1943        
1944        // set error reporter
1945
fErrorReporter =
1946            (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER);
1947        try {
1948            XMLErrorHandler currErrorHandler = fErrorReporter.getErrorHandler();
1949            // Setting a parser property can be much more expensive
1950
// than checking its value. Don't set the ERROR_HANDLER
1951
// property unless it's actually changed.
1952
if (currErrorHandler != fSchemaParser.getProperty(ERROR_HANDLER)) {
1953                fSchemaParser.setProperty(ERROR_HANDLER, (currErrorHandler != null) ? currErrorHandler : new DefaultErrorHandler());
1954                if (fAnnotationValidator != null) {
1955                    fAnnotationValidator.setProperty(ERROR_HANDLER, (currErrorHandler != null) ? currErrorHandler : new DefaultErrorHandler());
1956                }
1957            }
1958        } catch (XMLConfigurationException e) {
1959        }
1960        
1961        try {
1962            fValidateAnnotations = componentManager.getFeature(VALIDATE_ANNOTATIONS);
1963        } catch (XMLConfigurationException e) {
1964            fValidateAnnotations = false;
1965        }
1966        
1967        try {
1968            fHonourAllSchemaLocations = componentManager.getFeature(HONOUR_ALL_SCHEMALOCATIONS);
1969        } catch (XMLConfigurationException e) {
1970            fHonourAllSchemaLocations = false;
1971        }
1972
1973        try {
1974            fSchemaParser.setFeature(
1975                    CONTINUE_AFTER_FATAL_ERROR,
1976                    fErrorReporter.getFeature(CONTINUE_AFTER_FATAL_ERROR));
1977        } catch (XMLConfigurationException e) {
1978        }
1979        
1980        try {
1981            fSchemaParser.setFeature(
1982                    ALLOW_JAVA_ENCODINGS,
1983                    componentManager.getFeature(ALLOW_JAVA_ENCODINGS));
1984        } catch (XMLConfigurationException e) {
1985        }
1986        try {
1987            fSchemaParser.setFeature(
1988                    STANDARD_URI_CONFORMANT_FEATURE,
1989                    componentManager.getFeature(STANDARD_URI_CONFORMANT_FEATURE));
1990        } catch (XMLConfigurationException e) {
1991        }
1992        
1993        try {
1994            fGrammarPool =
1995                (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL);
1996        } catch (XMLConfigurationException e) {
1997            fGrammarPool = null;
1998        }
1999        // security features
2000
try {
2001            fSchemaParser.setFeature( DISALLOW_DOCTYPE,
2002                    componentManager.getFeature(DISALLOW_DOCTYPE));
2003        } catch (XMLConfigurationException e) {
2004        }
2005        try {
2006            Object JavaDoc security = componentManager.getProperty(SECURITY_MANAGER);
2007            if (security != null){
2008                fSchemaParser.setProperty(SECURITY_MANAGER, security);
2009            }
2010        } catch (XMLConfigurationException e) {
2011        }
2012        
2013    } // reset(XMLComponentManager)
2014

2015    
2016    /**
2017     * Traverse all the deferred local elements. This method should be called
2018     * by traverseSchemas after we've done with all the global declarations.
2019     */

2020    void traverseLocalElements() {
2021        fElementTraverser.fDeferTraversingLocalElements = false;
2022        
2023        for (int i = 0; i < fLocalElemStackPos; i++) {
2024            Element JavaDoc currElem = fLocalElementDecl[i];
2025            //XSDocumentInfo currSchema = (XSDocumentInfo)fDoc2XSDocumentMap.get(DOMUtil.getDocument(currElem));
2026
//XSDocumentInfo currSchema = (XSDocumentInfo)fDoc2XSDocumentMap.get(DOMUtil.getRoot(DOMUtil.getDocument(currElem)));
2027
XSDocumentInfo currSchema = fLocalElementDecl_schema[i];
2028            SchemaGrammar currGrammar = fGrammarBucket.getGrammar(currSchema.fTargetNamespace);
2029            fElementTraverser.traverseLocal (fParticle[i], currElem, currSchema, currGrammar, fAllContext[i], fParent[i], fLocalElemNamespaceContext[i]);
2030            // If it's an empty particle, remove it from the containing component.
2031
if (fParticle[i].fType == XSParticleDecl.PARTICLE_EMPTY) {
2032                XSModelGroupImpl group = null;
2033                if (fParent[i] instanceof XSComplexTypeDecl) {
2034                    XSParticle p = ((XSComplexTypeDecl)fParent[i]).getParticle();
2035                    if (p != null)
2036                        group = (XSModelGroupImpl)p.getTerm();
2037                }
2038                else {
2039                    group = ((XSGroupDecl)fParent[i]).fModelGroup;
2040                }
2041                if (group != null)
2042                    removeParticle(group, fParticle[i]);
2043            }
2044        }
2045    }
2046    
2047    private boolean removeParticle(XSModelGroupImpl group, XSParticleDecl particle) {
2048        XSParticleDecl member;
2049        for (int i = 0; i < group.fParticleCount; i++) {
2050            member = group.fParticles[i];
2051            if (member == particle) {
2052                for (int j = i; j < group.fParticleCount-1; j++)
2053                    group.fParticles[j] = group.fParticles[j+1];
2054                group.fParticleCount--;
2055                return true;
2056            }
2057            if (member.fType == XSParticleDecl.PARTICLE_MODELGROUP) {
2058                if (removeParticle((XSModelGroupImpl)member.fValue, particle))
2059                    return true;
2060            }
2061        }
2062        return false;
2063    }
2064    
2065    // the purpose of this method is to keep up-to-date structures
2066
// we'll need for the feferred traversal of local elements.
2067
void fillInLocalElemInfo(Element JavaDoc elmDecl,
2068            XSDocumentInfo schemaDoc,
2069            int allContextFlags,
2070            XSObject parent,
2071            XSParticleDecl particle) {
2072        
2073        // if the stack is full, increase the size
2074
if (fParticle.length == fLocalElemStackPos) {
2075            // increase size
2076
XSParticleDecl[] newStackP = new XSParticleDecl[fLocalElemStackPos+INC_STACK_SIZE];
2077            System.arraycopy(fParticle, 0, newStackP, 0, fLocalElemStackPos);
2078            fParticle = newStackP;
2079            Element JavaDoc[] newStackE = new Element JavaDoc[fLocalElemStackPos+INC_STACK_SIZE];
2080            System.arraycopy(fLocalElementDecl, 0, newStackE, 0, fLocalElemStackPos);
2081            fLocalElementDecl = newStackE;
2082            XSDocumentInfo [] newStackE_schema = new XSDocumentInfo[fLocalElemStackPos+INC_STACK_SIZE];
2083            System.arraycopy(fLocalElementDecl_schema, 0, newStackE_schema, 0, fLocalElemStackPos);
2084            fLocalElementDecl_schema = newStackE_schema;
2085            int[] newStackI = new int[fLocalElemStackPos+INC_STACK_SIZE];
2086            System.arraycopy(fAllContext, 0, newStackI, 0, fLocalElemStackPos);
2087            fAllContext = newStackI;
2088            XSObject[] newStackC = new XSObject[fLocalElemStackPos+INC_STACK_SIZE];
2089            System.arraycopy(fParent, 0, newStackC, 0, fLocalElemStackPos);
2090            fParent = newStackC;
2091            String JavaDoc [][] newStackN = new String JavaDoc [fLocalElemStackPos+INC_STACK_SIZE][];
2092            System.arraycopy(fLocalElemNamespaceContext, 0, newStackN, 0, fLocalElemStackPos);
2093            fLocalElemNamespaceContext = newStackN;
2094        }
2095        
2096        fParticle[fLocalElemStackPos] = particle;
2097        fLocalElementDecl[fLocalElemStackPos] = elmDecl;
2098        fLocalElementDecl_schema[fLocalElemStackPos] = schemaDoc;
2099        fAllContext[fLocalElemStackPos] = allContextFlags;
2100        fParent[fLocalElemStackPos] = parent;
2101        fLocalElemNamespaceContext[fLocalElemStackPos++] = schemaDoc.fNamespaceSupport.getEffectiveLocalContext();
2102    } // end fillInLocalElemInfo(...)
2103

2104    /** This method makes sure that
2105     * if this component is being redefined that it lives in the
2106     * right schema. It then renames the component correctly. If it
2107     * detects a collision--a duplicate definition--then it complains.
2108     * Note that redefines must be handled carefully: if there
2109     * is a collision, it may be because we're redefining something we know about
2110     * or because we've found the thing we're redefining.
2111     */

2112    void checkForDuplicateNames(String JavaDoc qName,
2113            Hashtable JavaDoc registry, Hashtable JavaDoc registry_sub, Element JavaDoc currComp,
2114            XSDocumentInfo currSchema) {
2115        Object JavaDoc objElem = null;
2116        // REVISIT: when we add derivation checking, we'll have to make
2117
// sure that ID constraint collisions don't necessarily result in error messages.
2118
if ((objElem = registry.get(qName)) == null) {
2119            // just add it in!
2120
registry.put(qName, currComp);
2121            registry_sub.put(qName, currSchema);
2122            
2123        }
2124        else {
2125            Element JavaDoc collidingElem = (Element JavaDoc)objElem;
2126            XSDocumentInfo collidingElemSchema = (XSDocumentInfo)registry_sub.get(qName);
2127            if (collidingElem == currComp) return;
2128            Element JavaDoc elemParent = null;
2129            XSDocumentInfo redefinedSchema = null;
2130            // case where we've collided with a redefining element
2131
// (the parent of the colliding element is a redefine)
2132
boolean collidedWithRedefine = true;
2133            if ((DOMUtil.getLocalName((elemParent = DOMUtil.getParent(collidingElem))).equals(SchemaSymbols.ELT_REDEFINE))) {
2134                redefinedSchema = (XSDocumentInfo)(fRedefine2XSDMap.get(elemParent));
2135                // case where we're a redefining element.
2136
}
2137            else if ((DOMUtil.getLocalName(DOMUtil.getParent(currComp)).equals(SchemaSymbols.ELT_REDEFINE))) {
2138                redefinedSchema = collidingElemSchema;
2139                collidedWithRedefine = false;
2140            }
2141            if (redefinedSchema != null) { //redefinition involved somehow
2142
// If both components belong to the same document then
2143
// report an error and return.
2144
if(collidingElemSchema == currSchema){
2145                    reportSchemaError("sch-props-correct.2", new Object JavaDoc[]{qName}, currComp);
2146                    return;
2147                }
2148                
2149                String JavaDoc newName = qName.substring(qName.lastIndexOf(',')+1)+REDEF_IDENTIFIER;
2150                if (redefinedSchema == currSchema) { // object comp. okay here
2151
// now have to do some renaming...
2152
currComp.setAttribute(SchemaSymbols.ATT_NAME, newName);
2153                    if (currSchema.fTargetNamespace == null){
2154                        registry.put(","+newName, currComp);
2155                        registry_sub.put(","+newName, currSchema);
2156                    }
2157                    else{
2158                        registry.put(currSchema.fTargetNamespace+","+newName, currComp);
2159                        registry_sub.put(currSchema.fTargetNamespace+","+newName, currSchema);
2160                    }
2161                    // and take care of nested redefines by calling recursively:
2162
if (currSchema.fTargetNamespace == null)
2163                        checkForDuplicateNames(","+newName, registry, registry_sub, currComp, currSchema);
2164                    else
2165                        checkForDuplicateNames(currSchema.fTargetNamespace+","+newName, registry, registry_sub, currComp, currSchema);
2166                }
2167                else { // we may be redefining the wrong schema
2168
if (collidedWithRedefine) {
2169                        if (currSchema.fTargetNamespace == null)
2170                            checkForDuplicateNames(","+newName, registry, registry_sub, currComp, currSchema);
2171                        else
2172                            checkForDuplicateNames(currSchema.fTargetNamespace+","+newName, registry, registry_sub, currComp, currSchema);
2173                    }
2174                    else {
2175                        // error that redefined element in wrong schema
2176
reportSchemaError("sch-props-correct.2", new Object JavaDoc [] {qName}, currComp);
2177                    }
2178                }
2179            }
2180            else {
2181                // we've just got a flat-out collision
2182
reportSchemaError("sch-props-correct.2", new Object JavaDoc []{qName}, currComp);
2183            }
2184        }
2185    } // checkForDuplicateNames(String, Hashtable, Element, XSDocumentInfo):void
2186

2187    // the purpose of this method is to take the component of the
2188
// specified type and rename references to itself so that they
2189
// refer to the object being redefined. It takes special care of
2190
// <group>s and <attributeGroup>s to ensure that information
2191
// relating to implicit restrictions is preserved for those
2192
// traversers.
2193
private void renameRedefiningComponents(XSDocumentInfo currSchema,
2194            Element JavaDoc child, String JavaDoc componentType,
2195            String JavaDoc oldName, String JavaDoc newName) {
2196        if (componentType.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
2197            Element JavaDoc grandKid = DOMUtil.getFirstChildElement(child);
2198            if (grandKid == null) {
2199                reportSchemaError("src-redefine.5.a.a", null, child);
2200            }
2201            else {
2202                String JavaDoc grandKidName = DOMUtil.getLocalName(grandKid);
2203                if (grandKidName.equals(SchemaSymbols.ELT_ANNOTATION)) {
2204                    grandKid = DOMUtil.getNextSiblingElement(grandKid);
2205                }
2206                if (grandKid == null) {
2207                    reportSchemaError("src-redefine.5.a.a", null, child);
2208                }
2209                else {
2210                    grandKidName = DOMUtil.getLocalName(grandKid);
2211                    if (!grandKidName.equals(SchemaSymbols.ELT_RESTRICTION)) {
2212                        reportSchemaError("src-redefine.5.a.b", new Object JavaDoc[]{grandKidName}, child);
2213                    }
2214                    else {
2215                        Object JavaDoc[] attrs = fAttributeChecker.checkAttributes(grandKid, false, currSchema);
2216                        QName derivedBase = (QName)attrs[XSAttributeChecker.ATTIDX_BASE];
2217                        if (derivedBase == null ||
2218                                derivedBase.uri != currSchema.fTargetNamespace ||
2219                                !derivedBase.localpart.equals(oldName)) {
2220                            reportSchemaError("src-redefine.5.a.c",
2221                                    new Object JavaDoc[]{grandKidName,
2222                                    (currSchema.fTargetNamespace==null?"":currSchema.fTargetNamespace)
2223                                    + "," + oldName},
2224                                    child);
2225                        }
2226                        else {
2227                            // now we have to do the renaming...
2228
if (derivedBase.prefix != null && derivedBase.prefix.length() > 0)
2229                                grandKid.setAttribute( SchemaSymbols.ATT_BASE,
2230                                        derivedBase.prefix + ":" + newName );
2231                            else
2232                                grandKid.setAttribute( SchemaSymbols.ATT_BASE, newName );
2233                            // return true;
2234
}
2235                        fAttributeChecker.returnAttrArray(attrs, currSchema);
2236                    }
2237                }
2238            }
2239        }
2240        else if (componentType.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
2241            Element JavaDoc grandKid = DOMUtil.getFirstChildElement(child);
2242            if (grandKid == null) {
2243                reportSchemaError("src-redefine.5.b.a", null, child);
2244            }
2245            else {
2246                if (DOMUtil.getLocalName(grandKid).equals(SchemaSymbols.ELT_ANNOTATION)) {
2247                    grandKid = DOMUtil.getNextSiblingElement(grandKid);
2248                }
2249                if (grandKid == null) {
2250                    reportSchemaError("src-redefine.5.b.a", null, child);
2251                }
2252                else {
2253                    // have to go one more level down; let another pass worry whether complexType is valid.
2254
Element JavaDoc greatGrandKid = DOMUtil.getFirstChildElement(grandKid);
2255                    if (greatGrandKid == null) {
2256                        reportSchemaError("src-redefine.5.b.b", null, grandKid);
2257                    }
2258                    else {
2259                        String JavaDoc greatGrandKidName = DOMUtil.getLocalName(greatGrandKid);
2260                        if (greatGrandKidName.equals(SchemaSymbols.ELT_ANNOTATION)) {
2261                            greatGrandKid = DOMUtil.getNextSiblingElement(greatGrandKid);
2262                        }
2263                        if (greatGrandKid == null) {
2264                            reportSchemaError("src-redefine.5.b.b", null, grandKid);
2265                        }
2266                        else {
2267                            greatGrandKidName = DOMUtil.getLocalName(greatGrandKid);
2268                            if (!greatGrandKidName.equals(SchemaSymbols.ELT_RESTRICTION) &&
2269                                    !greatGrandKidName.equals(SchemaSymbols.ELT_EXTENSION)) {
2270                                reportSchemaError("src-redefine.5.b.c", new Object JavaDoc[]{greatGrandKidName}, greatGrandKid);
2271                            }
2272                            else {
2273                                Object JavaDoc[] attrs = fAttributeChecker.checkAttributes(greatGrandKid, false, currSchema);
2274                                QName derivedBase = (QName)attrs[XSAttributeChecker.ATTIDX_BASE];
2275                                if (derivedBase == null ||
2276                                        derivedBase.uri != currSchema.fTargetNamespace ||
2277                                        !derivedBase.localpart.equals(oldName)) {
2278                                    reportSchemaError("src-redefine.5.b.d",
2279                                            new Object JavaDoc[]{greatGrandKidName,
2280                                            (currSchema.fTargetNamespace==null?"":currSchema.fTargetNamespace)
2281                                            + "," + oldName},
2282                                            greatGrandKid);
2283                                }
2284                                else {
2285                                    // now we have to do the renaming...
2286
if (derivedBase.prefix != null && derivedBase.prefix.length() > 0)
2287                                        greatGrandKid.setAttribute( SchemaSymbols.ATT_BASE,
2288                                                derivedBase.prefix + ":" + newName );
2289                                    else
2290                                        greatGrandKid.setAttribute( SchemaSymbols.ATT_BASE,
2291                                                newName );
2292                                    // return true;
2293
}
2294                            }
2295                        }
2296                    }
2297                }
2298            }
2299        }
2300        else if (componentType.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
2301            String JavaDoc processedBaseName = (currSchema.fTargetNamespace == null)?
2302                    ","+oldName:currSchema.fTargetNamespace+","+oldName;
2303            int attGroupRefsCount = changeRedefineGroup(processedBaseName, componentType, newName, child, currSchema);
2304            if (attGroupRefsCount > 1) {
2305                reportSchemaError("src-redefine.7.1", new Object JavaDoc []{new Integer JavaDoc(attGroupRefsCount)}, child);
2306            }
2307            else if (attGroupRefsCount == 1) {
2308                // return true;
2309
}
2310            else
2311                if (currSchema.fTargetNamespace == null)
2312                    fRedefinedRestrictedAttributeGroupRegistry.put(processedBaseName, ","+newName);
2313                else
2314                    fRedefinedRestrictedAttributeGroupRegistry.put(processedBaseName, currSchema.fTargetNamespace+","+newName);
2315        }
2316        else if (componentType.equals(SchemaSymbols.ELT_GROUP)) {
2317            String JavaDoc processedBaseName = (currSchema.fTargetNamespace == null)?
2318                    ","+oldName:currSchema.fTargetNamespace+","+oldName;
2319            int groupRefsCount = changeRedefineGroup(processedBaseName, componentType, newName, child, currSchema);
2320            if (groupRefsCount > 1) {
2321                reportSchemaError("src-redefine.6.1.1", new Object JavaDoc []{new Integer JavaDoc(groupRefsCount)}, child);
2322            }
2323            else if (groupRefsCount == 1) {
2324                // return true;
2325
}
2326            else {
2327                if (currSchema.fTargetNamespace == null)
2328                    fRedefinedRestrictedGroupRegistry.put(processedBaseName, ","+newName);
2329                else
2330                    fRedefinedRestrictedGroupRegistry.put(processedBaseName, currSchema.fTargetNamespace+","+newName);
2331            }
2332        }
2333        else {
2334            reportSchemaError("Internal-Error", new Object JavaDoc [] {"could not handle this particular <redefine>; please submit your schemas and instance document in a bug report!"}, child);
2335        }
2336        // if we get here then we must have reported an error and failed somewhere...
2337
// return false;
2338
} // renameRedefiningComponents(XSDocumentInfo, Element, String, String, String):void
2339

2340    // this method takes a name of the form a:b, determines the URI mapped
2341
// to by a in the current SchemaNamespaceSupport object, and returns this
2342
// information in the form (nsURI,b) suitable for lookups in the global
2343
// decl Hashtables.
2344
// REVISIT: should have it return QName, instead of String. this would
2345
// save lots of string concatenation time. we can use
2346
// QName#equals() to compare two QNames, and use QName directly
2347
// as a key to the SymbolHash.
2348
// And when the DV's are ready to return compiled values from
2349
// validate() method, we should just call QNameDV.validate()
2350
// in this method.
2351
private String JavaDoc findQName(String JavaDoc name, XSDocumentInfo schemaDoc) {
2352        SchemaNamespaceSupport currNSMap = schemaDoc.fNamespaceSupport;
2353        int colonPtr = name.indexOf(':');
2354        String JavaDoc prefix = XMLSymbols.EMPTY_STRING;
2355        if (colonPtr > 0)
2356            prefix = name.substring(0, colonPtr);
2357        String JavaDoc uri = currNSMap.getURI(fSymbolTable.addSymbol(prefix));
2358        String JavaDoc localpart = (colonPtr == 0)?name:name.substring(colonPtr+1);
2359        if (prefix == XMLSymbols.EMPTY_STRING && uri == null && schemaDoc.fIsChameleonSchema)
2360            uri = schemaDoc.fTargetNamespace;
2361        if (uri == null)
2362            return ","+localpart;
2363        return uri+","+localpart;
2364    } // findQName(String, XSDocumentInfo): String
2365

2366    // This function looks among the children of curr for an element of type elementSought.
2367
// If it finds one, it evaluates whether its ref attribute contains a reference
2368
// to originalQName. If it does, it returns 1 + the value returned by
2369
// calls to itself on all other children. In all other cases it returns 0 plus
2370
// the sum of the values returned by calls to itself on curr's children.
2371
// It also resets the value of ref so that it will refer to the renamed type from the schema
2372
// being redefined.
2373
private int changeRedefineGroup(String JavaDoc originalQName, String JavaDoc elementSought,
2374            String JavaDoc newName, Element JavaDoc curr, XSDocumentInfo schemaDoc) {
2375        int result = 0;
2376        for (Element JavaDoc child = DOMUtil.getFirstChildElement(curr);
2377        child != null; child = DOMUtil.getNextSiblingElement(child)) {
2378            String JavaDoc name = DOMUtil.getLocalName(child);
2379            if (!name.equals(elementSought))
2380                result += changeRedefineGroup(originalQName, elementSought, newName, child, schemaDoc);
2381            else {
2382                String JavaDoc ref = child.getAttribute( SchemaSymbols.ATT_REF );
2383                if (ref.length() != 0) {
2384                    String JavaDoc processedRef = findQName(ref, schemaDoc);
2385                    if (originalQName.equals(processedRef)) {
2386                        String JavaDoc prefix = XMLSymbols.EMPTY_STRING;
2387                        int colonptr = ref.indexOf(":");
2388                        if (colonptr > 0) {
2389                            prefix = ref.substring(0,colonptr);
2390                            child.setAttribute(SchemaSymbols.ATT_REF, prefix + ":" + newName);
2391                        }
2392                        else
2393                            child.setAttribute(SchemaSymbols.ATT_REF, newName);
2394                        result++;
2395                        if (elementSought.equals(SchemaSymbols.ELT_GROUP)) {
2396                            String JavaDoc minOccurs = child.getAttribute( SchemaSymbols.ATT_MINOCCURS );
2397                            String JavaDoc maxOccurs = child.getAttribute( SchemaSymbols.ATT_MAXOCCURS );
2398                            if (!((maxOccurs.length() == 0 || maxOccurs.equals("1"))
2399                                    && (minOccurs.length() == 0 || minOccurs.equals("1")))) {
2400                                reportSchemaError("src-redefine.6.1.2", new Object JavaDoc [] {ref}, child);
2401                            }
2402                        }
2403                    }
2404                } // if ref was null some other stage of processing will flag the error
2405
}
2406        }
2407        return result;
2408    } // changeRedefineGroup
2409

2410    // this method returns the XSDocumentInfo object that contains the
2411
// component corresponding to decl. If components from this
2412
// document cannot be referred to from those of currSchema, this
2413
// method returns null; it's up to the caller to throw an error.
2414
// @param: currSchema: the XSDocumentInfo object containing the
2415
// decl ref'ing us.
2416
// @param: decl: the declaration being ref'd.
2417
// this method is superficial now. ---Jack
2418
private XSDocumentInfo findXSDocumentForDecl(XSDocumentInfo currSchema,
2419            Element JavaDoc decl, XSDocumentInfo decl_Doc) {
2420        
2421        if (DEBUG_NODE_POOL) {
2422            System.out.println("DOCUMENT NS:"+ currSchema.fTargetNamespace+" hashcode:"+ ((Object JavaDoc)currSchema.fSchemaElement).hashCode());
2423        }
2424        Object JavaDoc temp = decl_Doc;
2425        if (temp == null) {
2426            // something went badly wrong; we don't know this doc?
2427
return null;
2428        }
2429        XSDocumentInfo declDocInfo = (XSDocumentInfo)temp;
2430        return declDocInfo;
2431        /*********
2432         Logic here is unnecessary after schema WG's recent decision to allow
2433         schema components from one document to refer to components of any other,
2434         so long as there's some include/import/redefine path amongst them.
2435         If they rver reverse this decision the code's right here though... - neilg
2436         // now look in fDependencyMap to see if this is reachable
2437          if(((Vector)fDependencyMap.get(currSchema)).contains(declDocInfo)) {
2438          return declDocInfo;
2439          }
2440          // obviously the requesting doc didn't include, redefine or
2441           // import the one containing decl...
2442            return null;
2443            **********/

2444    } // findXSDocumentForDecl(XSDocumentInfo, Element): XSDocumentInfo
2445

2446    // returns whether more than <annotation>s occur in children of elem
2447
private boolean nonAnnotationContent(Element JavaDoc elem) {
2448        for(Element JavaDoc child = DOMUtil.getFirstChildElement(elem); child != null; child = DOMUtil.getNextSiblingElement(child)) {
2449            if(!(DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION))) return true;
2450        }
2451        return false;
2452    } // nonAnnotationContent(Element): boolean
2453

2454    private void setSchemasVisible(XSDocumentInfo startSchema) {
2455        if (DOMUtil.isHidden(startSchema.fSchemaElement, fHiddenNodes)) {
2456            // make it visible
2457
DOMUtil.setVisible(startSchema.fSchemaElement, fHiddenNodes);
2458            Vector JavaDoc dependingSchemas = (Vector JavaDoc)fDependencyMap.get(startSchema);
2459            for (int i = 0; i < dependingSchemas.size(); i++) {
2460                setSchemasVisible((XSDocumentInfo)dependingSchemas.elementAt(i));
2461            }
2462        }
2463        // if it's visible already than so must be its children
2464
} // setSchemasVisible(XSDocumentInfo): void
2465

2466    private SimpleLocator xl = new SimpleLocator();
2467    
2468    /**
2469     * Extract location information from an Element node, and create a
2470     * new SimpleLocator object from such information. Returning null means
2471     * no information can be retrieved from the element.
2472     */

2473    public SimpleLocator element2Locator(Element JavaDoc e) {
2474        if (!( e instanceof ElementImpl))
2475            return null;
2476        
2477        SimpleLocator l = new SimpleLocator();
2478        return element2Locator(e, l) ? l : null;
2479    }
2480    
2481    /**
2482     * Extract location information from an Element node, store such
2483     * information in the passed-in SimpleLocator object, then return
2484     * true. Returning false means can't extract or store such information.
2485     */

2486    public boolean element2Locator(Element JavaDoc e, SimpleLocator l) {
2487        if (l == null)
2488            return false;
2489        if (e instanceof ElementImpl) {
2490            ElementImpl ele = (ElementImpl)e;
2491            // get system id from document object
2492
Document JavaDoc doc = ele.getOwnerDocument();
2493            String JavaDoc sid = (String JavaDoc)fDoc2SystemId.get(DOMUtil.getRoot(doc));
2494            // line/column numbers are stored in the element node
2495
int line = ele.getLineNumber();
2496            int column = ele.getColumnNumber();
2497            l.setValues(sid, sid, line, column, ele.getCharacterOffset());
2498            return true;
2499        }
2500        return false;
2501    }
2502    
2503    void reportSchemaError(String JavaDoc key, Object JavaDoc[] args, Element JavaDoc ele) {
2504        if (element2Locator(ele, xl)) {
2505            fErrorReporter.reportError(xl, XSMessageFormatter.SCHEMA_DOMAIN,
2506                    key, args, XMLErrorReporter.SEVERITY_ERROR);
2507        }
2508        else {
2509            fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN,
2510                    key, args, XMLErrorReporter.SEVERITY_ERROR);
2511        }
2512    }
2513    
2514    void reportSchemaWarning(String JavaDoc key, Object JavaDoc[] args, Element JavaDoc ele) {
2515        if (element2Locator(ele, xl)) {
2516            fErrorReporter.reportError(xl, XSMessageFormatter.SCHEMA_DOMAIN,
2517                    key, args, XMLErrorReporter.SEVERITY_WARNING);
2518        }
2519        else {
2520            fErrorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN,
2521                    key, args, XMLErrorReporter.SEVERITY_WARNING);
2522        }
2523    }
2524    
2525    /**
2526     * Grammar pool used for validating annotations. This will return all of the
2527     * grammars from the grammar bucket. It will also return an object for the
2528     * schema for schemas which will contain at least the relevant declarations
2529     * for annotations.
2530     */

2531    private static class XSAnnotationGrammarPool implements XMLGrammarPool {
2532        
2533        private XSGrammarBucket fGrammarBucket;
2534        private Grammar [] fInitialGrammarSet;
2535        
2536        public Grammar[] retrieveInitialGrammarSet(String JavaDoc grammarType) {
2537            if (grammarType == XMLGrammarDescription.XML_SCHEMA) {
2538                if (fInitialGrammarSet == null) {
2539                    if (fGrammarBucket == null) {
2540                        fInitialGrammarSet = new Grammar [] {SchemaGrammar.SG_Schema4Annotations};
2541                    }
2542                    else {
2543                        SchemaGrammar [] schemaGrammars = fGrammarBucket.getGrammars();
2544                        /**
2545                         * If the grammar bucket already contains the schema for schemas
2546                         * then we already have the definitions for the parts relevant
2547                         * to annotations.
2548                         */

2549                        for (int i = 0; i < schemaGrammars.length; ++i) {
2550                            if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(schemaGrammars[i].getTargetNamespace())) {
2551                                fInitialGrammarSet = schemaGrammars;
2552                                return fInitialGrammarSet;
2553                            }
2554                        }
2555                        Grammar [] grammars = new Grammar[schemaGrammars.length + 1];
2556                        System.arraycopy(schemaGrammars, 0, grammars, 0, schemaGrammars.length);
2557                        grammars[grammars.length - 1] = SchemaGrammar.SG_Schema4Annotations;
2558                        fInitialGrammarSet = grammars;
2559                    }
2560                }
2561                return fInitialGrammarSet;
2562            }
2563            return new Grammar[0];
2564        }
2565
2566        public void cacheGrammars(String JavaDoc grammarType, Grammar[] grammars) {
2567            
2568        }
2569
2570        public Grammar retrieveGrammar(XMLGrammarDescription desc) {
2571            if (desc.getGrammarType() == XMLGrammarDescription.XML_SCHEMA) {
2572                final String JavaDoc tns = ((XMLSchemaDescription) desc).getTargetNamespace();
2573                if (fGrammarBucket != null) {
2574                    Grammar grammar = fGrammarBucket.getGrammar(tns);
2575                    if (grammar != null) {
2576                        return grammar;
2577                    }
2578                }
2579                if (SchemaSymbols.URI_SCHEMAFORSCHEMA.equals(tns)) {
2580                    return SchemaGrammar.SG_Schema4Annotations;
2581                }
2582            }
2583            return null;
2584        }
2585        
2586        public void refreshGrammars(XSGrammarBucket gBucket) {
2587            fGrammarBucket = gBucket;
2588            fInitialGrammarSet = null;
2589        }
2590
2591        public void lockPool() {}
2592
2593        public void unlockPool() {}
2594
2595        public void clear() {}
2596    }
2597
2598    /**
2599     * used to identify a reference to a schema document
2600     * if the same document is referenced twice with the same key, then
2601     * we only need to parse it once.
2602     *
2603     * When 2 XSDKey's are compared, the following table can be used to
2604     * determine whether they are equal:
2605     * inc red imp pre ins
2606     * inc N/L ? N/L N/L N/L
2607     * red ? N/L ? ? ?
2608     * imp N/L ? N/P N/P N/P
2609     * pre N/L ? N/P N/P N/P
2610     * ins N/L ? N/P N/P N/P
2611     *
2612     * Where: N/L: duplicate when they have the same namespace and location.
2613     * ? : not clear from the spec.
2614     * REVISIT: to simplify the process, also considering
2615     * it's very rare, we treat them as not duplicate.
2616     * N/P: not possible. imp/pre/ins are referenced by namespace.
2617     * when the first time we encounter a schema document for a
2618     * namespace, we create a grammar and store it in the grammar
2619     * bucket. when we see another reference to the same namespace,
2620     * we first check whether a grammar with the same namespace is
2621     * already in the bucket, which is true in this case, so we
2622     * won't create another XSDKey.
2623     *
2624     * Conclusion from the table: two XSDKey's are duplicate only when all of
2625     * the following are true:
2626     * 1. They are both "redefine", or neither is "redefine";
2627     * 2. They have the same namespace;
2628     * 3. They have the same non-null location.
2629     *
2630     * About 3: if neither has a non-null location, then it's the case where
2631     * 2 input streams are provided, but no system ID is provided. We can't tell
2632     * whether the 2 streams have the same content, so we treat them as not
2633     * duplicate.
2634     */

2635    private static class XSDKey {
2636        String JavaDoc systemId;
2637        short referType;
2638        // for inclue/redefine, this is the enclosing namespace
2639
// for import/preparse/instance, this is the target namespace
2640
String JavaDoc referNS;
2641        
2642        XSDKey(String JavaDoc systemId, short referType, String JavaDoc referNS) {
2643            this.systemId = systemId;
2644            this.referType = referType;
2645            this.referNS = referNS;
2646        }
2647        
2648        public int hashCode() {
2649            // according to the description at the beginning of this class,
2650
// we use the hashcode of the namespace as the hashcoe of this key.
2651
return referNS == null ? 0 : referNS.hashCode();
2652        }
2653        
2654        public boolean equals(Object JavaDoc obj) {
2655            if (!(obj instanceof XSDKey)) {
2656                return false;
2657            }
2658            XSDKey key = (XSDKey)obj;
2659            
2660            // condition 1: both are redefine
2661
if (referType == XSDDescription.CONTEXT_REDEFINE ||
2662                    key.referType == XSDDescription.CONTEXT_REDEFINE) {
2663                if (referType != key.referType)
2664                    return false;
2665            }
2666            
2667            // condition 2: same namespace
2668
if (referNS != key.referNS)
2669                return false;
2670            
2671            // condition 3: same non-null locatoin
2672
if (systemId == null || !systemId.equals(key.systemId)) {
2673                return false;
2674            }
2675            
2676            return true;
2677        }
2678    }
2679    
2680    /**
2681     * @param state
2682     */

2683    public void setGenerateSyntheticAnnotations(boolean state) {
2684        fSchemaParser.setFeature(GENERATE_SYNTHETIC_ANNOTATIONS, state);
2685    }
2686    
2687} // XSDHandler
2688
Popular Tags