KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > enhydra > apache > xerces > validators > schema > TraverseSchema


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2000,2001 The Apache Software Foundation.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 1999, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57 package org.enhydra.apache.xerces.validators.schema;
58
59 import java.io.IOException JavaDoc;
60 import java.net.MalformedURLException JavaDoc;
61 import java.net.URL JavaDoc;
62 import java.util.Enumeration JavaDoc;
63 import java.util.Hashtable JavaDoc;
64 import java.util.Stack JavaDoc;
65 import java.util.StringTokenizer JavaDoc;
66 import java.util.Vector JavaDoc;
67
68 import org.enhydra.apache.xerces.framework.XMLContentSpec;
69 import org.enhydra.apache.xerces.framework.XMLErrorReporter;
70 import org.enhydra.apache.xerces.parsers.DOMParser;
71 import org.enhydra.apache.xerces.utils.NamespacesScope;
72 import org.enhydra.apache.xerces.utils.QName;
73 import org.enhydra.apache.xerces.utils.StringPool;
74 import org.enhydra.apache.xerces.validators.common.Grammar;
75 import org.enhydra.apache.xerces.validators.common.GrammarResolver;
76 import org.enhydra.apache.xerces.validators.common.XMLAttributeDecl;
77 import org.enhydra.apache.xerces.validators.common.XMLElementDecl;
78 import org.enhydra.apache.xerces.validators.datatype.AnySimpleType;
79 import org.enhydra.apache.xerces.validators.datatype.DatatypeValidator;
80 import org.enhydra.apache.xerces.validators.datatype.DatatypeValidatorFactoryImpl;
81 import org.enhydra.apache.xerces.validators.datatype.IDDatatypeValidator;
82 import org.enhydra.apache.xerces.validators.datatype.InvalidDatatypeValueException;
83 import org.enhydra.apache.xerces.validators.datatype.ListDatatypeValidator;
84 import org.enhydra.apache.xerces.validators.datatype.NOTATIONDatatypeValidator;
85 import org.enhydra.apache.xerces.validators.datatype.StringDatatypeValidator;
86 import org.enhydra.apache.xerces.validators.datatype.UnionDatatypeValidator;
87 import org.enhydra.apache.xerces.validators.schema.identity.Field;
88 import org.enhydra.apache.xerces.validators.schema.identity.IdentityConstraint;
89 import org.enhydra.apache.xerces.validators.schema.identity.Key;
90 import org.enhydra.apache.xerces.validators.schema.identity.KeyRef;
91 import org.enhydra.apache.xerces.validators.schema.identity.Selector;
92 import org.enhydra.apache.xerces.validators.schema.identity.Unique;
93 import org.enhydra.apache.xerces.validators.schema.identity.XPathException;
94 import org.w3c.dom.Attr JavaDoc;
95 import org.w3c.dom.Document JavaDoc;
96 import org.w3c.dom.Element JavaDoc;
97 import org.w3c.dom.NamedNodeMap JavaDoc;
98 import org.w3c.dom.Node JavaDoc;
99 import org.xml.sax.EntityResolver JavaDoc;
100 import org.xml.sax.InputSource JavaDoc;
101 import org.xml.sax.SAXException JavaDoc;
102 import org.xml.sax.SAXParseException JavaDoc;
103
104 /**
105  * Instances of this class get delegated to Traverse the Schema and
106  * to populate the Grammar internal representation by
107  * instances of Grammar objects.
108  * Traverse a Schema Grammar:
109  *
110  * @author Eric Ye, IBM
111  * @author Jeffrey Rodriguez, IBM
112  * @author Andy Clark, IBM
113  *
114  * @see org.enhydra.apache.xerces.validators.common.Grammar
115  *
116  * @version $Id: TraverseSchema.java,v 1.2 2005/01/26 08:28:44 jkjome Exp $
117  */

118 public class TraverseSchema implements
119                             NamespacesScope.NamespacesHandler{
120
121     //CONSTANTS
122
private static final int TOP_LEVEL_SCOPE = -1;
123
124     /** Identity constraint keywords. */
125     private static final String JavaDoc[][] IDENTITY_CONSTRAINTS = {
126         { SchemaSymbols.URI_SCHEMAFORSCHEMA, SchemaSymbols.ELT_UNIQUE },
127         { SchemaSymbols.URI_SCHEMAFORSCHEMA, SchemaSymbols.ELT_KEY },
128         { SchemaSymbols.URI_SCHEMAFORSCHEMA, SchemaSymbols.ELT_KEYREF },
129     };
130     // hopefully a string people will not use in their names very often...
131
private static final String JavaDoc redefIdentifier = "_fn3dktizrknc9pi";
132     // fields to hold application-specified schemaLocations
133
private String JavaDoc fUnparsedExternalSchemas = null;
134     private Hashtable JavaDoc fExternalSchemas = null;
135     private String JavaDoc fExternalNoNamespaceSchema = null;
136     // Flags for handleOccurrences to indicate any special
137
// restrictions on minOccurs and maxOccurs relating to "all".
138
// NOT_ALL_CONTEXT - not processing an <all>
139
// PROCESSING_ALL_EL - processing an <element> in an <all>
140
// GROUP_REF_WITH_ALL - processing <group> reference that contained <all>
141
// CHILD_OF_GROUP - processing a child of a model group definition
142
// PROCESSING_ALL_GP - processing an <all> group itself
143
private static final int NOT_ALL_CONTEXT = 0;
144     private static final int PROCESSING_ALL_EL = 1;
145     private static final int GROUP_REF_WITH_ALL = 2;
146     private static final int CHILD_OF_GROUP = 4;
147     private static final int PROCESSING_ALL_GP = 8;
148
149     //debugging
150
private static final boolean DEBUGGING = false;
151
152     /** Compile to true to debug identity constraints. */
153     private static final boolean DEBUG_IDENTITY_CONSTRAINTS = false;
154     private static final boolean DEBUG_NEW_GROUP = true;
155
156     /**
157      * Compile to true to debug datatype validator lookup for
158      * identity constraint support.
159      */

160     private static final boolean DEBUG_IC_DATATYPES = false;
161
162     //private data members
163

164     private boolean fFullConstraintChecking = false;
165
166     private XMLErrorReporter fErrorReporter = null;
167     private StringPool fStringPool = null;
168
169     private GrammarResolver fGrammarResolver = null;
170     private SchemaGrammar fSchemaGrammar = null;
171
172     private Element JavaDoc fSchemaRootElement;
173     // this is always set to refer to the root of the linked list containing the root info of schemas under redefinition.
174
private SchemaInfo fSchemaInfoListRoot = null;
175     private SchemaInfo fCurrentSchemaInfo = null;
176     private boolean fRedefineSucceeded;
177
178     private DatatypeValidatorFactoryImpl fDatatypeRegistry = null;
179
180     private Hashtable JavaDoc fComplexTypeRegistry = new Hashtable JavaDoc();
181     private Hashtable JavaDoc fAttributeDeclRegistry = new Hashtable JavaDoc();
182
183     // stores the names of groups that we've traversed so we can avoid multiple traversals
184
// qualified group names are keys and their contentSpecIndexes are values.
185
private Hashtable JavaDoc fGroupNameRegistry = new Hashtable JavaDoc();
186     // this Hashtable keeps track of whether a given redefined group does so by restriction.
187
private Hashtable JavaDoc fRestrictedRedefinedGroupRegistry = new Hashtable JavaDoc();
188
189     // stores "final" values of simpleTypes--no clean way to integrate this into the existing datatype validation structure...
190
private Hashtable JavaDoc fSimpleTypeFinalRegistry = new Hashtable JavaDoc();
191
192     // stores <notation> decl
193
private Hashtable JavaDoc fNotationRegistry = new Hashtable JavaDoc();
194
195     private Vector JavaDoc fIncludeLocations = new Vector JavaDoc();
196     private Vector JavaDoc fImportLocations = new Vector JavaDoc();
197     private Hashtable JavaDoc fRedefineLocations = new Hashtable JavaDoc();
198     private Vector JavaDoc fTraversedRedefineElements = new Vector JavaDoc();
199     // Hashtable associating attributeGroups within a <redefine> which
200
// restrict attributeGroups in the original schema with the
201
// new name for those groups in the modified redefined schema.
202
private Hashtable JavaDoc fRedefineAttributeGroupMap = null;
203
204     // simpleType data
205
private Hashtable JavaDoc fFacetData = new Hashtable JavaDoc(10);
206     private Stack JavaDoc fSimpleTypeNameStack = new Stack JavaDoc();
207     private String JavaDoc fListName = "";
208
209
210     private int fAnonTypeCount =0;
211     private int fScopeCount=0;
212     private int fCurrentScope=TOP_LEVEL_SCOPE;
213     private int fSimpleTypeAnonCount = 0;
214     private Stack JavaDoc fCurrentTypeNameStack = new Stack JavaDoc();
215     private Stack JavaDoc fBaseTypeNameStack = new Stack JavaDoc();
216     private Stack JavaDoc fCurrentGroupNameStack = new Stack JavaDoc();
217     private Vector JavaDoc fElementRecurseComplex = new Vector JavaDoc();
218     private Vector JavaDoc fTopLevelElementsRefdFromGroup = new Vector JavaDoc();
219     private Stack JavaDoc fCurrentAttrGroupNameStack = new Stack JavaDoc();
220
221     private Vector JavaDoc fSubstitutionGroupRecursionRegistry = new Vector JavaDoc();
222     private boolean fElementDefaultQualified = false;
223     private boolean fAttributeDefaultQualified = false;
224     private int fBlockDefault = 0;
225     private int fFinalDefault = 0;
226
227     private int fTargetNSURI;
228     private String JavaDoc fTargetNSURIString = "";
229     private NamespacesScope fNamespacesScope = null;
230     private String JavaDoc fCurrentSchemaURL = "";
231     private Stack JavaDoc fSchemaURLStack = new Stack JavaDoc();
232
233     private XMLAttributeDecl fTempAttributeDecl = new XMLAttributeDecl();
234     private XMLAttributeDecl fTemp2AttributeDecl = new XMLAttributeDecl();
235     private XMLElementDecl fTempElementDecl = new XMLElementDecl();
236     private XMLElementDecl fTempElementDecl2 = new XMLElementDecl();
237     private XMLContentSpec tempContentSpec1 = new XMLContentSpec();
238     private XMLContentSpec tempContentSpec2 = new XMLContentSpec();
239
240     private EntityResolver JavaDoc fEntityResolver = null;
241     private SubstitutionGroupComparator fSComp = null;
242
243     private Hashtable JavaDoc fIdentityConstraints = new Hashtable JavaDoc();
244     // Yet one more data structure; this one associates
245
// <unique> and <key> QNames with their corresponding objects,
246
// so that <keyRef>s can find them.
247
private Hashtable JavaDoc fIdentityConstraintNames = new Hashtable JavaDoc();
248
249     // General Attribute Checking
250
private GeneralAttrCheck fGeneralAttrCheck = null;
251     private int fXsiURI;
252
253    // REVISIT: maybe need to be moved into SchemaGrammar class
254
public class ComplexTypeInfo {
255         public String JavaDoc typeName;
256
257         public DatatypeValidator baseDataTypeValidator;
258         public ComplexTypeInfo baseComplexTypeInfo;
259
260         public int derivedBy = 0;
261         public int blockSet = 0;
262         public int finalSet = 0;
263
264         public int miscFlags=0;
265
266         public int scopeDefined = -1;
267
268         public int contentType;
269         public int contentSpecHandle = -1;
270         public int templateElementIndex = -1;
271         public int attlistHead = -1;
272         public DatatypeValidator datatypeValidator;
273
274         public boolean isAbstractType() {
275            return ((miscFlags & CT_IS_ABSTRACT)!=0);
276         }
277         public boolean containsAttrTypeID () {
278            return ((miscFlags & CT_CONTAINS_ATTR_TYPE_ID)!=0);
279         }
280         public boolean declSeen () {
281            return ((miscFlags & CT_DECL_SEEN)!=0);
282         }
283
284         public void setIsAbstractType() {
285            miscFlags |= CT_IS_ABSTRACT;
286         }
287         public void setContainsAttrTypeID() {
288            miscFlags |= CT_CONTAINS_ATTR_TYPE_ID;
289         }
290         public void setDeclSeen() {
291            miscFlags |= CT_DECL_SEEN;
292         }
293
294     }
295     private static final int CT_IS_ABSTRACT=1;
296     private static final int CT_CONTAINS_ATTR_TYPE_ID=2;
297     private static final int CT_DECL_SEEN=4; // indicates that the declaration was
298
// traversed as opposed to processed due
299
// to a forward reference
300

301     private class ComplexTypeRecoverableError extends Exception JavaDoc {
302         ComplexTypeRecoverableError() {super();}
303         ComplexTypeRecoverableError(String JavaDoc s) {super(s);}
304     }
305
306     private class ParticleRecoverableError extends Exception JavaDoc {
307         ParticleRecoverableError(String JavaDoc s) {super(s);}
308     }
309
310     private class GroupInfo {
311         int contentSpecIndex = -1;
312         int scope = -1;
313     }
314
315     private class ElementInfo {
316         int elementIndex;
317         String JavaDoc typeName;
318
319         private ElementInfo(int i, String JavaDoc name) {
320            elementIndex = i;
321            typeName = name;
322         }
323     }
324
325     //REVISIT: verify the URI.
326
public final static String JavaDoc SchemaForSchemaURI = "http://www.w3.org/TR-1/Schema";
327
328     private TraverseSchema( ) {
329         // new TraverseSchema() is forbidden;
330
}
331
332     public void setFullConstraintCheckingEnabled() {
333         fFullConstraintChecking = true;
334     }
335
336     public void setGrammarResolver(GrammarResolver grammarResolver){
337         fGrammarResolver = grammarResolver;
338     }
339     public void startNamespaceDeclScope(int prefix, int uri){
340         //TO DO
341
}
342     public void endNamespaceDeclScope(int prefix){
343         //TO DO, do we need to do anything here?
344
}
345
346     public boolean particleEmptiable(int contentSpecIndex) {
347
348        if (!fFullConstraintChecking) {
349            return true;
350        }
351        if (minEffectiveTotalRange(contentSpecIndex)==0)
352          return true;
353        else
354          return false;
355     }
356
357     public int minEffectiveTotalRange(int contentSpecIndex) {
358
359        fSchemaGrammar.getContentSpec(contentSpecIndex, tempContentSpec1);
360        int type = tempContentSpec1.type;
361        if (type == XMLContentSpec.CONTENTSPECNODE_SEQ ||
362            type == XMLContentSpec.CONTENTSPECNODE_ALL) {
363           return minEffectiveTotalRangeSeq(contentSpecIndex);
364        }
365        else if (type == XMLContentSpec.CONTENTSPECNODE_CHOICE) {
366           return minEffectiveTotalRangeChoice(contentSpecIndex);
367        }
368        else {
369           return(fSchemaGrammar.getContentSpecMinOccurs(contentSpecIndex));
370        }
371
372     }
373
374     private int minEffectiveTotalRangeSeq(int csIndex) {
375
376        fSchemaGrammar.getContentSpec(csIndex, tempContentSpec1);
377        int type = tempContentSpec1.type;
378        int left = tempContentSpec1.value;
379        int right = tempContentSpec1.otherValue;
380        int min = fSchemaGrammar.getContentSpecMinOccurs(csIndex);
381
382        int result;
383        if (right == -2)
384           result = min * minEffectiveTotalRange(left);
385        else
386           result = min * (minEffectiveTotalRange(left) + minEffectiveTotalRange(right));
387        return result;
388
389     }
390     private int minEffectiveTotalRangeChoice(int csIndex) {
391
392        fSchemaGrammar.getContentSpec(csIndex, tempContentSpec1);
393        int type = tempContentSpec1.type;
394        int left = tempContentSpec1.value;
395        int right = tempContentSpec1.otherValue;
396        int min = fSchemaGrammar.getContentSpecMinOccurs(csIndex);
397
398        int result;
399        if (right == -2)
400           result = min * minEffectiveTotalRange(left);
401        else {
402           int minLeft = minEffectiveTotalRange(left);
403           int minRight = minEffectiveTotalRange(right);
404           result = min * ((minLeft < minRight)?minLeft:minRight);
405        }
406        return result;
407     }
408
409     public int maxEffectiveTotalRange(int contentSpecIndex) {
410
411        fSchemaGrammar.getContentSpec(contentSpecIndex, tempContentSpec1);
412        int type = tempContentSpec1.type;
413        if (type == XMLContentSpec.CONTENTSPECNODE_SEQ ||
414            type == XMLContentSpec.CONTENTSPECNODE_ALL) {
415           return maxEffectiveTotalRangeSeq(contentSpecIndex);
416        }
417        else if (type == XMLContentSpec.CONTENTSPECNODE_CHOICE) {
418           return maxEffectiveTotalRangeChoice(contentSpecIndex);
419        }
420        else {
421           return(fSchemaGrammar.getContentSpecMaxOccurs(contentSpecIndex));
422        }
423
424     }
425
426     private int maxEffectiveTotalRangeSeq(int csIndex) {
427
428        fSchemaGrammar.getContentSpec(csIndex, tempContentSpec1);
429        int type = tempContentSpec1.type;
430        int left = tempContentSpec1.value;
431        int right = tempContentSpec1.otherValue;
432        int max = fSchemaGrammar.getContentSpecMaxOccurs(csIndex);
433
434        if (max == SchemaSymbols.OCCURRENCE_UNBOUNDED)
435          return SchemaSymbols.OCCURRENCE_UNBOUNDED;
436
437        int maxLeft = maxEffectiveTotalRange(left);
438        if (right == -2) {
439          if (maxLeft == SchemaSymbols.OCCURRENCE_UNBOUNDED)
440            return SchemaSymbols.OCCURRENCE_UNBOUNDED;
441          else
442            return max * maxLeft;
443        }
444        else {
445          int maxRight = maxEffectiveTotalRange(right);
446          if (maxLeft == SchemaSymbols.OCCURRENCE_UNBOUNDED ||
447             maxRight == SchemaSymbols.OCCURRENCE_UNBOUNDED)
448            return SchemaSymbols.OCCURRENCE_UNBOUNDED;
449          else
450            return max * (maxLeft + maxRight);
451        }
452     }
453
454     private int maxEffectiveTotalRangeChoice(int csIndex) {
455
456        fSchemaGrammar.getContentSpec(csIndex, tempContentSpec1);
457        int type = tempContentSpec1.type;
458        int left = tempContentSpec1.value;
459        int right = tempContentSpec1.otherValue;
460        int max = fSchemaGrammar.getContentSpecMaxOccurs(csIndex);
461
462        if (max == SchemaSymbols.OCCURRENCE_UNBOUNDED)
463          return SchemaSymbols.OCCURRENCE_UNBOUNDED;
464
465        int maxLeft = maxEffectiveTotalRange(left);
466        if (right == -2) {
467          if (maxLeft == SchemaSymbols.OCCURRENCE_UNBOUNDED)
468            return SchemaSymbols.OCCURRENCE_UNBOUNDED;
469          else
470            return max * maxLeft;
471        }
472        else {
473          int maxRight = maxEffectiveTotalRange(right);
474          if (maxLeft == SchemaSymbols.OCCURRENCE_UNBOUNDED ||
475             maxRight == SchemaSymbols.OCCURRENCE_UNBOUNDED)
476            return SchemaSymbols.OCCURRENCE_UNBOUNDED;
477          else
478            return max * ((maxLeft > maxRight)?maxLeft:maxRight);
479        }
480     }
481
482
483     private String JavaDoc resolvePrefixToURI (String JavaDoc prefix) throws Exception JavaDoc {
484         String JavaDoc uriStr = fStringPool.toString(fNamespacesScope.getNamespaceForPrefix(fStringPool.addSymbol(prefix)));
485         if (uriStr.length() == 0 && prefix.length() > 0) {
486             // REVISIT: Localize
487
reportGenericSchemaError("prefix : [" + prefix +"] cannot be resolved to a URI");
488             return "";
489         }
490
491         return uriStr;
492     }
493
494     public TraverseSchema(Element JavaDoc root, StringPool stringPool,
495                            SchemaGrammar schemaGrammar,
496                            GrammarResolver grammarResolver,
497                            XMLErrorReporter errorReporter,
498                            String JavaDoc schemaURL,
499                            EntityResolver JavaDoc entityResolver,
500                            boolean fullChecking,
501                            GeneralAttrCheck generalAttrCheck,
502                            String JavaDoc externalSchemaLocations, String JavaDoc noNamespaceSchemaLocation
503                            ) throws Exception JavaDoc {
504         fErrorReporter = errorReporter;
505         fCurrentSchemaURL = schemaURL;
506         fFullConstraintChecking = fullChecking;
507         fEntityResolver = entityResolver;
508         fGeneralAttrCheck = generalAttrCheck;
509         fUnparsedExternalSchemas = externalSchemaLocations;
510         if(externalSchemaLocations != null) {
511             StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(externalSchemaLocations, " \n\t\r", false);
512             int tokenTotal = tokenizer.countTokens();
513             if (tokenTotal % 2 == 0 ) {
514                 fExternalSchemas = new Hashtable JavaDoc();
515                 String JavaDoc uri = null;
516                 String JavaDoc location = null;
517                 while (tokenizer.hasMoreTokens()) {
518                     uri = tokenizer.nextToken();
519                     location = tokenizer.nextToken();
520                     fExternalSchemas.put(location, uri);
521                 }
522             }
523         }
524         fExternalNoNamespaceSchema = noNamespaceSchemaLocation;
525         doTraverseSchema(root, stringPool, schemaGrammar, grammarResolver);
526     }
527
528     public TraverseSchema(Element JavaDoc root, StringPool stringPool,
529                            SchemaGrammar schemaGrammar,
530                            GrammarResolver grammarResolver,
531                            XMLErrorReporter errorReporter,
532                            String JavaDoc schemaURL,
533                            boolean fullChecking,
534                            GeneralAttrCheck generalAttrCheck
535                            ) throws Exception JavaDoc {
536         fErrorReporter = errorReporter;
537         fCurrentSchemaURL = schemaURL;
538         fFullConstraintChecking = fullChecking;
539         fGeneralAttrCheck = generalAttrCheck;
540         doTraverseSchema(root, stringPool, schemaGrammar, grammarResolver);
541     }
542
543     public TraverseSchema(Element JavaDoc root, StringPool stringPool,
544                            SchemaGrammar schemaGrammar,
545                            GrammarResolver grammarResolver,
546                            boolean fullChecking,
547                            GeneralAttrCheck generalAttrCheck
548                            ) throws Exception JavaDoc {
549         fFullConstraintChecking = fullChecking;
550         fGeneralAttrCheck = generalAttrCheck;
551         doTraverseSchema(root, stringPool, schemaGrammar, grammarResolver);
552     }
553
554     public void doTraverseSchema(Element JavaDoc root, StringPool stringPool,
555                            SchemaGrammar schemaGrammar,
556                            GrammarResolver grammarResolver) throws Exception JavaDoc {
557
558
559         fSchemaRootElement = root;
560         fStringPool = stringPool;
561         fSchemaGrammar = schemaGrammar;
562         fNamespacesScope = new NamespacesScope(this);
563         fNamespacesScope.setNamespaceForPrefix(fStringPool.addSymbol("xml"), fStringPool.addSymbol("http://www.w3.org/XML/1998/namespace"));
564
565         if (fFullConstraintChecking) {
566           fSchemaGrammar.setDeferContentSpecExpansion();
567           fSchemaGrammar.setCheckUniqueParticleAttribution();
568         }
569
570         fGrammarResolver = grammarResolver;
571         fDatatypeRegistry = (DatatypeValidatorFactoryImpl) fGrammarResolver.getDatatypeRegistry();
572
573         //Expand to registry type to contain all primitive datatype
574
fDatatypeRegistry.expandRegistryToFullSchemaSet();
575
576         fXsiURI = fStringPool.addSymbol(SchemaSymbols.URI_XSI);
577
578         if (root == null) {
579             // REVISIT: Anything to do?
580
return;
581         }
582
583         // General Attribute Checking
584
int scope = GeneralAttrCheck.ELE_CONTEXT_GLOBAL;
585         Hashtable JavaDoc attrValues = generalCheck(root, scope);
586
587         //Retrieve the targetNamespace URI information
588
fTargetNSURIString = getTargetNamespaceString(root);
589         fTargetNSURI = fStringPool.addSymbol(fTargetNSURIString);
590
591         if (fGrammarResolver == null) {
592             // REVISIT: Localize
593
reportGenericSchemaError("Internal error: don't have a GrammarResolver for TraverseSchema");
594         }
595         else{
596             // for complex type registry, attribute decl registry and
597
// namespace mapping, needs to check whether the passed in
598
// Grammar was a newly instantiated one.
599
if (fSchemaGrammar.getComplexTypeRegistry() == null ) {
600                 fSchemaGrammar.setComplexTypeRegistry(fComplexTypeRegistry);
601             }
602             else {
603                 fComplexTypeRegistry = fSchemaGrammar.getComplexTypeRegistry();
604             }
605
606             if (fSchemaGrammar.getAttributeDeclRegistry() == null ) {
607                 fSchemaGrammar.setAttributeDeclRegistry(fAttributeDeclRegistry);
608             }
609             else {
610                 fAttributeDeclRegistry = fSchemaGrammar.getAttributeDeclRegistry();
611             }
612
613             if (fSchemaGrammar.getNamespacesScope() == null ) {
614                 fSchemaGrammar.setNamespacesScope(fNamespacesScope);
615             }
616             else {
617                 fNamespacesScope = fSchemaGrammar.getNamespacesScope();
618             }
619
620             fSchemaGrammar.setDatatypeRegistry(fDatatypeRegistry);
621             fSchemaGrammar.setTargetNamespaceURI(fTargetNSURIString);
622             fGrammarResolver.putGrammar(fTargetNSURIString, fSchemaGrammar);
623         }
624
625
626
627         // Retrived the Namespace mapping from the schema element.
628
NamedNodeMap JavaDoc schemaEltAttrs = root.getAttributes();
629         int i = 0;
630         Attr JavaDoc sattr = null;
631
632         boolean seenXMLNS = false;
633         while ((sattr = (Attr JavaDoc)schemaEltAttrs.item(i++)) != null) {
634             String JavaDoc attName = sattr.getName();
635             if (attName.startsWith("xmlns:")) {
636                 String JavaDoc attValue = sattr.getValue();
637                 String JavaDoc prefix = attName.substring(attName.indexOf(":")+1);
638                 fNamespacesScope.setNamespaceForPrefix( fStringPool.addSymbol(prefix),
639                                                         fStringPool.addSymbol(attValue) );
640             }
641             if (attName.equals("xmlns")) {
642
643                 String JavaDoc attValue = sattr.getValue();
644                 fNamespacesScope.setNamespaceForPrefix( StringPool.EMPTY_STRING,
645                                                         fStringPool.addSymbol(attValue) );
646                 seenXMLNS = true;
647             }
648
649         }
650         if (!seenXMLNS && fTargetNSURIString.length() == 0 ) {
651             fNamespacesScope.setNamespaceForPrefix( StringPool.EMPTY_STRING,
652                                                     StringPool.EMPTY_STRING);
653         }
654
655         fElementDefaultQualified =
656             root.getAttribute(SchemaSymbols.ATT_ELEMENTFORMDEFAULT).equals(SchemaSymbols.ATTVAL_QUALIFIED);
657         fAttributeDefaultQualified =
658             root.getAttribute(SchemaSymbols.ATT_ATTRIBUTEFORMDEFAULT).equals(SchemaSymbols.ATTVAL_QUALIFIED);
659         Attr JavaDoc blockAttr = root.getAttributeNode(SchemaSymbols.ATT_BLOCKDEFAULT);
660         if (blockAttr == null)
661             fBlockDefault = 0;
662         else
663             fBlockDefault =
664                 parseBlockSet(blockAttr.getValue());
665         Attr JavaDoc finalAttr = root.getAttributeNode(SchemaSymbols.ATT_FINALDEFAULT);
666         if (finalAttr == null)
667             fFinalDefault = 0;
668         else
669             fFinalDefault =
670                 parseFinalSet(finalAttr.getValue());
671
672         //REVISIT, really sticky when noTargetNamesapce, for now, we assume everyting is in the same name space);
673
if (fTargetNSURI == StringPool.EMPTY_STRING) {
674             //fElementDefaultQualified = true;
675
//fAttributeDefaultQualified = true;
676
}
677
678
679         //fScopeCount++;
680
// fCurrentScope = -1;
681

682
683         //extract all top-level attribute, attributeGroup, and group Decls and put them in the 3 hasn table in the SchemaGrammar.
684
extractTopLevel3Components(root);
685
686         // process <redefine>, <include> and <import> info items.
687
Element JavaDoc child = XUtil.getFirstChildElement(root);
688         for (; child != null;
689             child = XUtil.getNextSiblingElement(child)) {
690
691             String JavaDoc name = child.getLocalName();
692             if (name.equals(SchemaSymbols.ELT_ANNOTATION) ) {
693                 traverseAnnotationDecl(child);
694             } else if (name.equals(SchemaSymbols.ELT_INCLUDE)) {
695                 fNamespacesScope.increaseDepth();
696                 traverseInclude(child);
697                 fNamespacesScope.decreaseDepth();
698             } else if (name.equals(SchemaSymbols.ELT_IMPORT)) {
699                 traverseImport(child);
700             } else if (name.equals(SchemaSymbols.ELT_REDEFINE)) {
701                 fRedefineSucceeded = true; // presume worked until proven failed.
702
traverseRedefine(child);
703             } else
704                 break;
705         }
706
707         // child refers to the first info item which is not <annotation> or
708
// one of the schema inclusion/importation declarations.
709
for (; child != null;
710             child = XUtil.getNextSiblingElement(child)) {
711
712             String JavaDoc name = child.getLocalName();
713             if (name.equals(SchemaSymbols.ELT_ANNOTATION) ) {
714                 traverseAnnotationDecl(child);
715             } else if (name.equals(SchemaSymbols.ELT_SIMPLETYPE )) {
716                 traverseSimpleTypeDecl(child);
717             } else if (name.equals(SchemaSymbols.ELT_COMPLEXTYPE )) {
718                 traverseComplexTypeDecl(child);
719             } else if (name.equals(SchemaSymbols.ELT_ELEMENT )) {
720                 traverseElementDecl(child);
721             } else if (name.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
722                 traverseAttributeGroupDecl(child, null, null);
723             } else if (name.equals( SchemaSymbols.ELT_ATTRIBUTE ) ) {
724                 traverseAttributeDecl( child, null, false );
725             } else if (name.equals(SchemaSymbols.ELT_GROUP)) {
726                 traverseGroupDecl(child);
727             } else if (name.equals(SchemaSymbols.ELT_NOTATION)) {
728                 traverseNotationDecl(child); //TO DO
729
} else {
730                 // REVISIT: Localize
731
reportGenericSchemaError("error in content of <schema> element information item");
732             }
733         } // for each child node
734

735         // handle identity constraints
736
// we must traverse <key>s and <unique>s before we tackel<keyref>s,
737
// since all have global scope and may be declared anywhere in the schema.
738
Enumeration JavaDoc elementIndexes = fIdentityConstraints.keys();
739         while (elementIndexes.hasMoreElements()) {
740             Integer JavaDoc elementIndexObj = (Integer JavaDoc)elementIndexes.nextElement();
741             if (DEBUG_IC_DATATYPES) {
742                 System.out.println("<ICD>: traversing identity constraints for element: "+elementIndexObj);
743             }
744             Vector JavaDoc identityConstraints = (Vector JavaDoc)fIdentityConstraints.get(elementIndexObj);
745             if (identityConstraints != null) {
746                 int elementIndex = elementIndexObj.intValue();
747                 traverseIdentityNameConstraintsFor(elementIndex, identityConstraints);
748             }
749         }
750         elementIndexes = fIdentityConstraints.keys();
751         while (elementIndexes.hasMoreElements()) {
752             Integer JavaDoc elementIndexObj = (Integer JavaDoc)elementIndexes.nextElement();
753             if (DEBUG_IC_DATATYPES) {
754                 System.out.println("<ICD>: traversing identity constraints for element: "+elementIndexObj);
755             }
756             Vector JavaDoc identityConstraints = (Vector JavaDoc)fIdentityConstraints.get(elementIndexObj);
757             if (identityConstraints != null) {
758                 int elementIndex = elementIndexObj.intValue();
759                 traverseIdentityRefConstraintsFor(elementIndex, identityConstraints);
760             }
761         }
762
763         // At this point, we can do any remaining checking for cos-element-consistent
764
// that involves substitution group elements
765

766         if (fFullConstraintChecking) {
767             // Loop thru all of the top-level elements that were ref'd from groups or
768
// complexTypes, and ensure that:
769
// 1. they have consistent type as any local element potentially declared in
770
// the group/type
771
// 2. any substitutable elements are consistent wrt type given any
772
// similiarly named elements from the group scope
773
// Note: for a complexType, we don't check against base scope. Not clear if
774
// we need to.
775

776             for (int j = 0; j < fTopLevelElementsRefdFromGroup.size(); j+=2) {
777                QName eltName = (QName)fTopLevelElementsRefdFromGroup.elementAt(j);
778                int groupScope = ((Integer JavaDoc)fTopLevelElementsRefdFromGroup.elementAt(j+1)).intValue();
779                checkConsistentElements(eltName, groupScope);
780             }
781
782             // Loop thru all of the complexTypes, and for any derived by restriction,
783
// do particle derivation checking
784
int count = fComplexTypeRegistry.size();
785             Enumeration JavaDoc enumer = fComplexTypeRegistry.elements();
786
787             ComplexTypeInfo typeInfo,baseTypeInfo;
788             while (enumer.hasMoreElements ()) {
789                typeInfo = (TraverseSchema.ComplexTypeInfo)enumer.nextElement();
790                baseTypeInfo = typeInfo.baseComplexTypeInfo;
791
792                if (typeInfo.derivedBy == SchemaSymbols.RESTRICTION &&
793                    baseTypeInfo!=null &&
794                    typeInfo.contentSpecHandle>-1) {
795                  try {
796                     checkParticleDerivationOK(typeInfo.contentSpecHandle,
797                          typeInfo.scopeDefined, baseTypeInfo.contentSpecHandle,
798                          baseTypeInfo.scopeDefined,baseTypeInfo);
799                  }
800                  catch (ParticleRecoverableError e) {
801                     String JavaDoc message = e.getMessage();
802                     reportGenericSchemaError("ComplexType '" + typeInfo.typeName + "': " + message);
803                  }
804                }
805             }
806
807         }
808
809     } // traverseSchema(Element)
810

811
812     private void extractTopLevel3Components(Element JavaDoc root) throws Exception JavaDoc {
813
814         for (Element JavaDoc child = XUtil.getFirstChildElement(root); child != null;
815             child = XUtil.getNextSiblingElement(child)) {
816
817             String JavaDoc name = child.getLocalName();
818             String JavaDoc compName = child.getAttribute(SchemaSymbols.ATT_NAME);
819             if (name.equals(SchemaSymbols.ELT_ELEMENT)) {
820                 // Check if the element has already been declared
821
if (fSchemaGrammar.topLevelElemDecls.get(compName) != null) {
822                    reportGenericSchemaError("sch-props-correct: Duplicate declaration for an element " +
823                                              compName);
824                 }
825                 else {
826                     fSchemaGrammar.topLevelElemDecls.put(compName, child);
827                 }
828             }
829             else if (name.equals(SchemaSymbols.ELT_SIMPLETYPE) ||
830                      name.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
831                  // Check for dublicate declaration
832
if (fSchemaGrammar.topLevelTypeDecls.get(compName) != null) {
833                    reportGenericSchemaError("sch-props-correct: Duplicate declaration for a type " +
834                                              compName);
835                 }
836                 else {
837                     fSchemaGrammar.topLevelTypeDecls.put(compName, child);
838                 }
839             }
840             else if (name.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
841                  // Check for dublicate declaration
842
if (fSchemaGrammar.topLevelAttrGrpDecls.get(compName) != null) {
843                    reportGenericSchemaError("sch-props-correct: Duplicate declaration for an attribute group " +
844                                              compName);
845                 }
846                 else {
847                 fSchemaGrammar.topLevelAttrGrpDecls.put(compName, child);
848                 }
849             } else if (name.equals( SchemaSymbols.ELT_ATTRIBUTE ) ) {
850                 // Check for dublicate declaration
851
if (fSchemaGrammar.topLevelAttrGrpDecls.get(compName) != null) {
852                    reportGenericSchemaError("sch-props-correct: Duplicate declaration for an attribute " +
853                                              compName);
854                 }
855                 else {
856                     fSchemaGrammar.topLevelAttrGrpDecls.put(compName, child);
857                 }
858             } else if ( name.equals(SchemaSymbols.ELT_GROUP) ) {
859                 // Check if the group has already been declared
860
if (fSchemaGrammar.topLevelGroupDecls.get(compName) != null){
861                    reportGenericSchemaError("sch-props-correct: Duplicate declaration for a group " +
862                                              compName);
863                 }
864                 else {
865                 fSchemaGrammar.topLevelGroupDecls.put(compName, child);
866                 }
867             } else if ( name.equals(SchemaSymbols.ELT_NOTATION) ) {
868                 // Check for dublicate declaration
869
if (fSchemaGrammar.topLevelNotationDecls.get(compName) != null) {
870                    reportGenericSchemaError("sch-props-correct: Duplicate declaration for a notation " +
871                                              compName);
872                 }
873                 else {
874                 fSchemaGrammar.topLevelNotationDecls.put(compName, child);
875             }
876             }
877         } // for each child node
878
}
879
880     private void checkConsistentElements(QName eltName, int scope) throws Exception JavaDoc {
881
882       // See if there is a declaration of an element with the same name at the
883
// given scope.
884
// This is required because any model group cannot have more than 1
885
// element with the same name, but different types (even if some are
886
// local, and others top-level)
887

888        fTempElementDecl.clear();
889        int topLevelElementNdx = fSchemaGrammar.getElementDeclIndex(eltName, TOP_LEVEL_SCOPE);
890        if (topLevelElementNdx < 0)
891            return;
892
893        fSchemaGrammar.getElementDecl(topLevelElementNdx, fTempElementDecl);
894        DatatypeValidator edv = fTempElementDecl.datatypeValidator;
895        ComplexTypeInfo eTypeInfo = fSchemaGrammar.getElementComplexTypeInfo(topLevelElementNdx);
896        int existingEltNdx = fSchemaGrammar.getElementDeclIndex(eltName.uri,
897                                               eltName.localpart,scope);
898        if (existingEltNdx > -1) {
899           if (!checkDuplicateElementTypes(existingEltNdx,eTypeInfo,edv))
900
901               reportGenericSchemaError("duplicate element decl in the same scope with different types : " +
902                                         fStringPool.toString(eltName.localpart));
903        }
904
905        Vector JavaDoc substitutableNames = fSchemaGrammar.getElementDeclAllSubstitutionGroupQNames(topLevelElementNdx, fGrammarResolver, fStringPool);
906
907        for (int i = 0; i < substitutableNames.size(); i++) {
908           SchemaGrammar.OneSubGroup subGroup = (SchemaGrammar.OneSubGroup)substitutableNames.elementAt(i);
909           QName substName = subGroup.name;
910           int substEltNdx = subGroup.eleIndex;
911
912           int localEltNdx = fSchemaGrammar.getElementDeclIndex(substName, scope);
913           if (localEltNdx > -1) {
914              fSchemaGrammar.getElementDecl(localEltNdx, fTempElementDecl);
915              edv = fTempElementDecl.datatypeValidator;
916              eTypeInfo = fSchemaGrammar.getElementComplexTypeInfo(localEltNdx);
917              if (!checkDuplicateElementTypes(substEltNdx,eTypeInfo,edv))
918                  reportGenericSchemaError("duplicate element decl in the same scope with different types : " +
919                   fStringPool.toString(substName.localpart));
920           }
921        }
922
923     }
924
925
926     /**
927      * Expands a system id and returns the system id as a URL, if
928      * it can be expanded. A return value of null means that the
929      * identifier is already expanded. An exception thrown
930      * indicates a failure to expand the id.
931      *
932      * @param systemId The systemId to be expanded.
933      *
934      * @return Returns the URL object representing the expanded system
935      * identifier. A null value indicates that the given
936      * system identifier is already expanded.
937      *
938      */

939     private String JavaDoc expandSystemId(String JavaDoc systemId, String JavaDoc currentSystemId) throws Exception JavaDoc{
940      String JavaDoc id = systemId;
941
942      // check for bad parameters id
943
if (id == null || id.length() == 0) {
944          return systemId;
945      }
946
947      // if id already expanded, return
948
try {
949          URL JavaDoc url = new URL JavaDoc(id);
950          if (url != null) {
951              return systemId;
952          }
953      }
954      catch (MalformedURLException JavaDoc e) {
955          // continue on...
956
}
957
958      // normalize id
959
id = fixURI(id);
960
961      // normalize base
962
URL JavaDoc base = null;
963      URL JavaDoc url = null;
964      try {
965          if (currentSystemId == null) {
966              String JavaDoc dir;
967              try {
968                  dir = fixURI(System.getProperty("user.dir"));
969              }
970              catch (SecurityException JavaDoc se) {
971                  dir = "";
972              }
973              if (!dir.endsWith("/")) {
974                  dir = dir + "/";
975              }
976              base = new URL JavaDoc("file", "", dir);
977          }
978          else {
979              base = new URL JavaDoc(currentSystemId);
980          }
981
982          // expand id
983
url = new URL JavaDoc(base, id);
984      }
985      catch (Exception JavaDoc e) {
986          // let it go through
987
}
988      if (url == null) {
989          return systemId;
990      }
991      return url.toString();
992     }
993     /**
994      * Fixes a platform dependent filename to standard URI form.
995      *
996      * @param str The string to fix.
997      *
998      * @return Returns the fixed URI string.
999      */

1000    private static String JavaDoc fixURI(String JavaDoc str) {
1001
1002        // handle platform dependent strings
1003
str = str.replace(java.io.File.separatorChar, '/');
1004
1005        // Windows fix
1006
if (str.length() >= 2) {
1007            char ch1 = str.charAt(1);
1008            if (ch1 == ':') {
1009                char ch0 = Character.toUpperCase(str.charAt(0));
1010                if (ch0 >= 'A' && ch0 <= 'Z') {
1011                    str = "/" + str;
1012                }
1013            }
1014        }
1015
1016        // done
1017
return str;
1018    }
1019
1020
1021    private void traverseInclude(Element JavaDoc includeDecl) throws Exception JavaDoc {
1022        // General Attribute Checking
1023
int scope = GeneralAttrCheck.ELE_CONTEXT_GLOBAL;
1024        Hashtable JavaDoc attrValues = generalCheck(includeDecl, scope);
1025        checkContent(includeDecl, XUtil.getFirstChildElement(includeDecl), true);
1026
1027        Attr JavaDoc locationAttr = includeDecl.getAttributeNode(SchemaSymbols.ATT_SCHEMALOCATION);
1028        if (locationAttr == null) {
1029            // REVISIT: Localize
1030
reportGenericSchemaError("a schemaLocation attribute must be specified on an <include> element");
1031            return;
1032        }
1033        String JavaDoc location = locationAttr.getValue();
1034        // expand it before passing it to the parser
1035
InputSource JavaDoc source = null;
1036
1037        // If fEntityResolver is not null and is not the default, only then use it - Gopal Sharma, Sun Microsystems Inc.
1038
if ( (fEntityResolver != null) &&
1039             !(fEntityResolver.getClass().getName().equals("org.enhydra.apache.xerces.validators.common.XMLValidator$Resolver")) ) {
1040            source = fEntityResolver.resolveEntity("", location);
1041        }
1042
1043        if (source == null) {
1044            location = expandSystemId(location, fCurrentSchemaURL);
1045            source = new InputSource JavaDoc(location);
1046        }
1047        // create a string for uniqueness of this included schema in fIncludeLocations
1048
// algorithm: string is pubId+sysId or if both null then filename
1049
String JavaDoc pubId = "";
1050        String JavaDoc sysId = "";
1051        if (source.getPublicId () != null)
1052            pubId = source.getPublicId ();
1053        if (source.getSystemId () != null)
1054            sysId = source.getSystemId ();
1055
1056        if(pubId.length() != 0 || sysId.length() != 0)
1057            location = pubId+sysId;
1058
1059        if (fIncludeLocations.contains((Object JavaDoc)location)) {
1060            return;
1061        }
1062        fIncludeLocations.addElement((Object JavaDoc)location);
1063
1064        DOMParser parser = new IgnoreWhitespaceParser();
1065        parser.setEntityResolver( (fEntityResolver != null)? (fEntityResolver):(new Resolver()) );
1066        parser.setErrorHandler( new ErrorHandler()
1067            {
1068                public void error(SAXParseException JavaDoc ex) throws SAXException JavaDoc {
1069                    StringBuffer JavaDoc str = new StringBuffer JavaDoc();
1070                    String JavaDoc systemId_ = ex.getSystemId();
1071                    if (systemId_ != null) {
1072                        int index = systemId_.lastIndexOf('/');
1073                        if (index != -1)
1074                            systemId_ = systemId_.substring(index + 1);
1075                        str.append(systemId_);
1076                    }
1077                    str.append(':').append(ex.getLineNumber()).append(':').append(ex.getColumnNumber());
1078                    String JavaDoc message = ex.getMessage();
1079                    if(message.toLowerCase().trim().endsWith("not found.")) {
1080                        System.err.println("[Warning] "+
1081                               str.toString()+": "+ message);
1082                    } else { // do standard thing
1083
System.err.println("[Error] "+
1084                               str.toString()+":"+message);
1085                        throw ex;
1086                    }
1087                }
1088            });
1089
1090        try {
1091            parser.setFeature("http://xml.org/sax/features/validation", false);
1092            parser.setFeature("http://xml.org/sax/features/namespaces", true);
1093            parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
1094            parser.setFeature("http://apache.org/xml/features/continue-after-fatal-error", true);
1095        }catch( org.xml.sax.SAXNotRecognizedException JavaDoc e ) {
1096            e.printStackTrace();
1097        }catch( org.xml.sax.SAXNotSupportedException JavaDoc e ) {
1098            e.printStackTrace();
1099        }
1100
1101        try {
1102            parser.parse( source );
1103        }catch( IOException JavaDoc e ) {
1104            // we already produce warnings on IOExceptions!
1105
// e.printStackTrace();
1106
}catch( SAXException JavaDoc e ) {
1107            //e.printStackTrace();
1108
}
1109
1110        Document JavaDoc document = parser.getDocument(); //Our Grammar
1111
Element JavaDoc root = null;
1112        if (document != null) {
1113            root = document.getDocumentElement();
1114        }
1115
1116        if (root != null) {
1117            String JavaDoc targetNSURI = getTargetNamespaceString(root);
1118            if (targetNSURI.length() > 0 && !targetNSURI.equals(fTargetNSURIString) ) {
1119                // REVISIT: Localize
1120
reportGenericSchemaError("included schema '"+location+"' has a different targetNameSpace '"
1121                                         +targetNSURI+"'");
1122            }
1123            else {
1124                // We not creating another TraverseSchema object to compile
1125
// the included schema file, because the scope count, anon-type count
1126
// should not be reset for a included schema, this can be fixed by saving
1127
// the counters in the Schema Grammar,
1128
if (fSchemaInfoListRoot == null) {
1129                    fSchemaInfoListRoot = new SchemaInfo(fElementDefaultQualified, fAttributeDefaultQualified,
1130                        fBlockDefault, fFinalDefault,
1131                        fCurrentSchemaURL, fSchemaRootElement,
1132                        fNamespacesScope, null, null);
1133                    fCurrentSchemaInfo = fSchemaInfoListRoot;
1134                }
1135                fSchemaRootElement = root;
1136                fSchemaURLStack.push(fCurrentSchemaURL);
1137                fCurrentSchemaURL = location;
1138                traverseIncludedSchemaHeader(root);
1139                //
1140
// Bug fix: http://nagoya.apache.org/bugzilla/show_bug.cgi?id=3272
1141
// For included schemas with no namespace we need to bind the default namespace
1142
// (empty string) to the target namespace of the including XML Schema.
1143
if((fTargetNSURIString.length() != 0) && (root.getAttributeNode("xmlns") == null)) {
1144                    fNamespacesScope.setNamespaceForPrefix(StringPool.EMPTY_STRING, fTargetNSURI);
1145                }
1146                // and now we'd better save this stuff!
1147
fCurrentSchemaInfo = new SchemaInfo(fElementDefaultQualified, fAttributeDefaultQualified,
1148                        fBlockDefault, fFinalDefault,
1149                        fCurrentSchemaURL, fSchemaRootElement,
1150                        fNamespacesScope, fCurrentSchemaInfo.getNext(), fCurrentSchemaInfo);
1151                (fCurrentSchemaInfo.getPrev()).setNext(fCurrentSchemaInfo);
1152                traverseIncludedSchema(root);
1153                // there must always be a previous element!
1154
fCurrentSchemaInfo = fCurrentSchemaInfo.getPrev();
1155                fCurrentSchemaInfo.restore();
1156                fCurrentSchemaURL = (String JavaDoc)fSchemaURLStack.pop();
1157            }
1158
1159        }
1160
1161    }
1162
1163    private void traverseIncludedSchemaHeader(Element JavaDoc root) throws Exception JavaDoc {
1164        // General Attribute Checking
1165
int scope = GeneralAttrCheck.ELE_CONTEXT_GLOBAL;
1166        Hashtable JavaDoc attrValues = generalCheck(root, scope);
1167
1168        // Retrieved the Namespace mapping from the schema element.
1169
NamedNodeMap JavaDoc schemaEltAttrs = root.getAttributes();
1170        int i = 0;
1171        Attr JavaDoc sattr = null;
1172
1173        boolean seenXMLNS = false;
1174        while ((sattr = (Attr JavaDoc)schemaEltAttrs.item(i++)) != null) {
1175            String JavaDoc attName = sattr.getName();
1176            if (attName.startsWith("xmlns:")) {
1177                String JavaDoc attValue = sattr.getValue();
1178                String JavaDoc prefix = attName.substring(attName.indexOf(":")+1);
1179                fNamespacesScope.setNamespaceForPrefix( fStringPool.addSymbol(prefix),
1180                                                        fStringPool.addSymbol(attValue) );
1181            }
1182            if (attName.equals("xmlns")) {
1183
1184                String JavaDoc attValue = sattr.getValue();
1185                fNamespacesScope.setNamespaceForPrefix( StringPool.EMPTY_STRING,
1186                                                        fStringPool.addSymbol(attValue) );
1187                seenXMLNS = true;
1188            }
1189
1190        }
1191        if (!seenXMLNS && fTargetNSURIString.length() == 0 ) {
1192            fNamespacesScope.setNamespaceForPrefix( StringPool.EMPTY_STRING,
1193                                                    StringPool.EMPTY_STRING);
1194        }
1195
1196        fElementDefaultQualified =
1197            root.getAttribute(SchemaSymbols.ATT_ELEMENTFORMDEFAULT).equals(SchemaSymbols.ATTVAL_QUALIFIED);
1198        fAttributeDefaultQualified =
1199            root.getAttribute(SchemaSymbols.ATT_ATTRIBUTEFORMDEFAULT).equals(SchemaSymbols.ATTVAL_QUALIFIED);
1200        Attr JavaDoc blockAttr = root.getAttributeNode(SchemaSymbols.ATT_BLOCKDEFAULT);
1201        if (blockAttr == null)
1202            fBlockDefault = 0;
1203        else
1204            fBlockDefault =
1205                parseBlockSet(blockAttr.getValue());
1206        Attr JavaDoc finalAttr = root.getAttributeNode(SchemaSymbols.ATT_FINALDEFAULT);
1207        if (finalAttr == null)
1208            fFinalDefault = 0;
1209        else
1210            fFinalDefault =
1211                parseFinalSet(finalAttr.getValue());
1212
1213        //REVISIT, really sticky when noTargetNamesapce, for now, we assume everyting is in the same name space);
1214
if (fTargetNSURI == StringPool.EMPTY_STRING) {
1215            fElementDefaultQualified = true;
1216            //fAttributeDefaultQualified = true;
1217
}
1218
1219        //fScopeCount++;
1220
//fCurrentScope = -1;
1221
} // traverseIncludedSchemaHeader
1222

1223    private void traverseIncludedSchema(Element JavaDoc root) throws Exception JavaDoc {
1224        // General Attribute Checking
1225
int scope = GeneralAttrCheck.ELE_CONTEXT_GLOBAL;
1226        Hashtable JavaDoc attrValues = generalCheck(root, scope);
1227
1228        //extract all top-level attribute, attributeGroup, and group Decls and put them in the 3 hasn table in the SchemaGrammar.
1229
extractTopLevel3Components(root);
1230
1231        // handle <redefine>, <include> and <import> elements.
1232
Element JavaDoc child = XUtil.getFirstChildElement(root);
1233        for (; child != null;
1234            child = XUtil.getNextSiblingElement(child)) {
1235
1236            String JavaDoc name = child.getLocalName();
1237
1238            if (name.equals(SchemaSymbols.ELT_ANNOTATION) ) {
1239                traverseAnnotationDecl(child);
1240            } else if (name.equals(SchemaSymbols.ELT_INCLUDE)) {
1241                fNamespacesScope.increaseDepth();
1242                traverseInclude(child);
1243                fNamespacesScope.decreaseDepth();
1244            } else if (name.equals(SchemaSymbols.ELT_IMPORT)) {
1245                traverseImport(child);
1246            } else if (name.equals(SchemaSymbols.ELT_REDEFINE)) {
1247                fRedefineSucceeded = true; // presume worked until proven failed.
1248
traverseRedefine(child);
1249            } else
1250                break;
1251        }
1252
1253        // handle the rest of the schema elements.
1254
// BEWARE! this method gets called both from traverseRedefine and
1255
// traverseInclude; the preconditions (especially with respect to
1256
// groups and attributeGroups) are different!
1257
for (; child != null;
1258            child = XUtil.getNextSiblingElement(child)) {
1259
1260            String JavaDoc name = child.getLocalName();
1261
1262            if (name.equals(SchemaSymbols.ELT_ANNOTATION) ) {
1263                traverseAnnotationDecl(child);
1264            } else if (name.equals(SchemaSymbols.ELT_SIMPLETYPE )) {
1265                traverseSimpleTypeDecl(child);
1266            } else if (name.equals(SchemaSymbols.ELT_COMPLEXTYPE )) {
1267                traverseComplexTypeDecl(child);
1268            } else if (name.equals(SchemaSymbols.ELT_ELEMENT )) {
1269                traverseElementDecl(child);
1270            } else if (name.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
1271                if(fRedefineAttributeGroupMap != null) {
1272                    String JavaDoc dName = child.getAttribute(SchemaSymbols.ATT_NAME);
1273                    String JavaDoc bName = (String JavaDoc)fRedefineAttributeGroupMap.get(dName);
1274                    if(bName != null) {
1275                        child.setAttribute(SchemaSymbols.ATT_NAME, bName);
1276                        // and make sure we wipe this out of the grammar!
1277
fSchemaGrammar.topLevelAttrGrpDecls.remove(dName);
1278                        // Now we reuse this location in the array to store info we'll need for validation...
1279
ComplexTypeInfo typeInfo = new ComplexTypeInfo();
1280                        int templateElementNameIndex = fStringPool.addSymbol("$"+bName);
1281                        int typeNameIndex = fStringPool.addSymbol("%"+bName);
1282                        typeInfo.scopeDefined = -2;
1283                        typeInfo.contentSpecHandle = -1;
1284                        typeInfo.contentType = XMLElementDecl.TYPE_SIMPLE;
1285                        typeInfo.datatypeValidator = null;
1286                        typeInfo.templateElementIndex = fSchemaGrammar.addElementDecl(
1287                            new QName(-1, templateElementNameIndex,typeNameIndex,fTargetNSURI),
1288                            (fTargetNSURI==StringPool.EMPTY_STRING) ? StringPool.EMPTY_STRING : -2, typeInfo.scopeDefined,
1289                            typeInfo.contentType,
1290                            typeInfo.contentSpecHandle, -1, typeInfo.datatypeValidator);
1291
1292                        Vector JavaDoc anyAttDecls = new Vector JavaDoc();
1293                        // need to determine how to initialize these babies; then
1294
// on the <redefine> traversing end, try
1295
// and cast the hash value into the right form;
1296
// failure indicates nothing to redefine; success
1297
// means we can feed checkAttribute... what it needs...
1298
traverseAttributeGroupDecl(child, typeInfo, anyAttDecls);
1299                        typeInfo.attlistHead = fSchemaGrammar.getFirstAttributeDeclIndex(
1300                                typeInfo.templateElementIndex);
1301                        fRedefineAttributeGroupMap.put(dName, new Object JavaDoc []{typeInfo, fSchemaGrammar, anyAttDecls});
1302                        continue;
1303                    }
1304                }
1305                traverseAttributeGroupDecl(child, null, null);
1306            } else if (name.equals( SchemaSymbols.ELT_ATTRIBUTE ) ) {
1307                traverseAttributeDecl( child, null , false);
1308            } else if (name.equals(SchemaSymbols.ELT_GROUP)) {
1309                String JavaDoc dName = child.getAttribute(SchemaSymbols.ATT_NAME);
1310                if(fGroupNameRegistry.get(fTargetNSURIString + ","+dName) == null) {
1311                    // we've been renamed already
1312
traverseGroupDecl(child);
1313                    continue;
1314                }
1315                // if we're here: must have been a restriction.
1316
// we have yet to be renamed.
1317
try {
1318                    GroupInfo gi = (GroupInfo)fGroupNameRegistry.get(fTargetNSURIString + ","+dName);
1319                    // if that succeeded then we're done; were ref'd here in
1320
// an include most likely.
1321
continue;
1322                } catch (ClassCastException JavaDoc c) {
1323                    String JavaDoc s = (String JavaDoc)fGroupNameRegistry.get(fTargetNSURIString + ","+dName);
1324                    if (s == null) continue; // must have seen this already--somehow...
1325
};
1326                String JavaDoc bName = (String JavaDoc)fGroupNameRegistry.get(fTargetNSURIString +"," + dName);
1327                if(bName != null) {
1328                    child.setAttribute(SchemaSymbols.ATT_NAME, bName);
1329                    // Now we reuse this location in the array to store info we'll need for validation...
1330
// note that traverseGroupDecl will happily do that for us!
1331
}
1332                traverseGroupDecl(child);
1333            } else if (name.equals(SchemaSymbols.ELT_NOTATION)) {
1334                traverseNotationDecl(child);
1335            } else {
1336                // REVISIT: Localize
1337
reportGenericSchemaError("error in content of included <schema> element information item");
1338            }
1339        } // for each child node
1340

1341    }
1342
1343    // This method's job is to open a redefined schema and store away its root element, defaultElementQualified and other
1344
// such info, in order that it can be available when redefinition actually takes place.
1345
// It assumes that it will be called from the schema doing the redefining, and it assumes
1346
// that the other schema's info has already been saved, putting the info it finds into the
1347
// SchemaInfoList element that is passed in.
1348
private void openRedefinedSchema(Element JavaDoc redefineDecl, SchemaInfo store) throws Exception JavaDoc {
1349        Attr JavaDoc locationAttr = redefineDecl.getAttributeNode(SchemaSymbols.ATT_SCHEMALOCATION);
1350        if (locationAttr == null) {
1351            // REVISIT: Localize
1352
fRedefineSucceeded = false;
1353            reportGenericSchemaError("a schemaLocation attribute must be specified on a <redefine> element");
1354            return;
1355        }
1356        String JavaDoc location = locationAttr.getValue();
1357
1358        // expand it before passing it to the parser
1359
InputSource JavaDoc source = null;
1360        if (fEntityResolver != null) {
1361            source = fEntityResolver.resolveEntity("", location);
1362        }
1363
1364        if (source == null) {
1365            location = expandSystemId(location, fCurrentSchemaURL);
1366            source = new InputSource JavaDoc(location);
1367        }
1368        // Make sure we don't redefine the same schema twice; it's allowed
1369
// but the specs encourage us to avoid it.
1370
// algorithm: string is pubId+sysId or if both null then filename
1371
String JavaDoc pubId = "";
1372        String JavaDoc sysId = "";
1373        if (source.getPublicId () != null)
1374            pubId = source.getPublicId ();
1375        if (source.getSystemId () != null)
1376            sysId = source.getSystemId ();
1377
1378        if(pubId.length() != 0 || sysId.length() != 0)
1379            location += pubId+sysId;
1380
1381        // make sure we're not redefining ourselves!
1382
if(source.getSystemId().equals(fCurrentSchemaURL)) {
1383            // REVISIT: localize
1384
reportGenericSchemaError("src-redefine.2: a schema cannot redefine itself");
1385            fRedefineSucceeded = false;
1386            return;
1387        }
1388        if (fRedefineLocations.get((Object JavaDoc)location) != null) {
1389            // then we'd better make sure we're directed at that schema...
1390
fCurrentSchemaInfo = (SchemaInfo)(fRedefineLocations.get((Object JavaDoc)location));
1391            fCurrentSchemaInfo.restore();
1392            return;
1393        }
1394
1395        DOMParser parser = new IgnoreWhitespaceParser();
1396        parser.setEntityResolver( (fEntityResolver != null)? (fEntityResolver):(new Resolver()) );
1397        parser.setErrorHandler( new ErrorHandler() );
1398
1399        try {
1400            parser.setFeature("http://xml.org/sax/features/validation", false);
1401            parser.setFeature("http://xml.org/sax/features/namespaces", true);
1402            parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
1403            parser.setFeature("http://apache.org/xml/features/continue-after-fatal-error", true);
1404        }catch( org.xml.sax.SAXNotRecognizedException JavaDoc e ) {
1405            e.printStackTrace();
1406        }catch( org.xml.sax.SAXNotSupportedException JavaDoc e ) {
1407            e.printStackTrace();
1408        }
1409
1410        try {
1411            parser.parse( source );
1412        }catch( IOException JavaDoc e ) {
1413            e.printStackTrace();
1414        }catch( SAXException JavaDoc e ) {
1415            //e.printStackTrace();
1416
}
1417
1418        Document JavaDoc document = parser.getDocument(); //Our Grammar to be redefined
1419
Element JavaDoc root = null;
1420        if (document != null) {
1421            root = document.getDocumentElement();
1422        }
1423
1424        if (root == null) { // nothing to be redefined, so just continue; specs disallow an error here.
1425
fRedefineSucceeded = false;
1426            return;
1427        }
1428
1429        // now if root isn't null, it'll contain the root of the schema we need to redefine.
1430
// We do this in two phases: first, we look through the children of
1431
// redefineDecl. Each one will correspond to an element of the
1432
// redefined schema that we need to redefine. To do this, we rename the
1433
// element of the redefined schema, and rework the base or ref tag of
1434
// the kid we're working on to refer to the renamed group or derive the
1435
// renamed type. Once we've done this, we actually go through the
1436
// schema being redefined and convert it to a grammar. Only then do we
1437
// run through redefineDecl's kids and put them in the grammar.
1438
//
1439
// This approach is kosher with the specs. It does raise interesting
1440
// questions about error reporting, and perhaps also about grammar
1441
// access, but it is comparatively efficient (we need make at most
1442
// only 2 traversals of any given information item) and moreover
1443
// we can use existing code to build the grammar structures once the
1444
// first pass is out of the way, so this should be quite robust.
1445

1446        // check to see if the targetNameSpace is right
1447
String JavaDoc redefinedTargetNSURIString = getTargetNamespaceString(root);
1448        if (redefinedTargetNSURIString.length() > 0 && !redefinedTargetNSURIString.equals(fTargetNSURIString) ) {
1449            // REVISIT: Localize
1450
fRedefineSucceeded = false;
1451            reportGenericSchemaError("redefined schema '"+location+"' has a different targetNameSpace '"
1452                                     +redefinedTargetNSURIString+"' from the original schema");
1453        }
1454        else {
1455            // targetNamespace is right, so let's do the renaming...
1456
// and let's keep in mind that the targetNamespace of the redefined
1457
// elements is that of the redefined schema!
1458
fSchemaRootElement = root;
1459            fCurrentSchemaURL = location;
1460            fNamespacesScope = new NamespacesScope(this);
1461            fNamespacesScope.setNamespaceForPrefix(fStringPool.addSymbol("xml"), fStringPool.addSymbol("http://www.w3.org/XML/1998/namespace"));
1462            if((redefinedTargetNSURIString.length() == 0) && (root.getAttributeNode("xmlns") == null)) {
1463                fNamespacesScope.setNamespaceForPrefix(StringPool.EMPTY_STRING, fTargetNSURI);
1464            } else {
1465            }
1466            // get default form xmlns bindings et al.
1467
traverseIncludedSchemaHeader(root);
1468            // and then save them...
1469
store.setNext(new SchemaInfo(fElementDefaultQualified, fAttributeDefaultQualified,
1470                    fBlockDefault, fFinalDefault,
1471                    fCurrentSchemaURL, fSchemaRootElement,
1472                    fNamespacesScope, null, store));
1473            (store.getNext()).setPrev(store);
1474            fCurrentSchemaInfo = store.getNext();
1475            fRedefineLocations.put((Object JavaDoc)location, store.getNext());
1476        } // end if
1477
} // end openRedefinedSchema
1478

1479    /****
1480     * <redefine
1481       * schemaLocation = uriReference
1482       * {any attributes with non-schema namespace . . .}>
1483       * Content: (annotation | (
1484     * attributeGroup | complexType | group | simpleType))*
1485     * </redefine>
1486     */

1487    private void traverseRedefine(Element JavaDoc redefineDecl) throws Exception JavaDoc {
1488        // General Attribute Checking
1489
int scope = GeneralAttrCheck.ELE_CONTEXT_GLOBAL;
1490        Hashtable JavaDoc attrValues = generalCheck(redefineDecl, scope);
1491
1492        // initialize storage areas...
1493
fRedefineAttributeGroupMap = new Hashtable JavaDoc();
1494        NamespacesScope saveNSScope = (NamespacesScope)fNamespacesScope.clone();
1495
1496        // only case in which need to save contents is when fSchemaInfoListRoot is null; otherwise we'll have
1497
// done this already one way or another.
1498
if (fSchemaInfoListRoot == null) {
1499            fSchemaInfoListRoot = new SchemaInfo(fElementDefaultQualified, fAttributeDefaultQualified,
1500                    fBlockDefault, fFinalDefault,
1501                    fCurrentSchemaURL, fSchemaRootElement,
1502                    fNamespacesScope, null, null);
1503            openRedefinedSchema(redefineDecl, fSchemaInfoListRoot);
1504            if(!fRedefineSucceeded)
1505                return;
1506            fCurrentSchemaInfo = fSchemaInfoListRoot.getNext();
1507            fNamespacesScope = (NamespacesScope)saveNSScope.clone();
1508            renameRedefinedComponents(redefineDecl,fSchemaInfoListRoot.getNext().getRoot(), fSchemaInfoListRoot.getNext());
1509        } else {
1510            // may have a chain here; need to be wary!
1511
SchemaInfo curr = fSchemaInfoListRoot;
1512            for(; curr.getNext() != null; curr = curr.getNext());
1513            fCurrentSchemaInfo = curr;
1514            fCurrentSchemaInfo.restore();
1515            openRedefinedSchema(redefineDecl, fCurrentSchemaInfo);
1516            if(!fRedefineSucceeded)
1517                return;
1518            fNamespacesScope = (NamespacesScope)saveNSScope.clone();
1519            renameRedefinedComponents(redefineDecl,fCurrentSchemaInfo.getRoot(), fCurrentSchemaInfo);
1520        }
1521        // Now we have to march through our nicely-renamed schemas from the
1522
// bottom up. When we do these traversals other <redefine>'s may
1523
// perhaps be encountered; we leave recursion to sort this out.
1524

1525        fCurrentSchemaInfo.restore();
1526        traverseIncludedSchema(fSchemaRootElement);
1527        fNamespacesScope = (NamespacesScope)saveNSScope.clone();
1528        // and last but not least: traverse our own <redefine>--the one all
1529
// this labour has been expended upon.
1530
for (Element JavaDoc child = XUtil.getFirstChildElement(redefineDecl); child != null;
1531                child = XUtil.getNextSiblingElement(child)) {
1532            String JavaDoc name = child.getLocalName();
1533
1534            // annotations can occur anywhere in <redefine>s!
1535
if (name.equals(SchemaSymbols.ELT_ANNOTATION) ) {
1536                traverseAnnotationDecl(child);
1537            } else if (name.equals(SchemaSymbols.ELT_SIMPLETYPE )) {
1538                traverseSimpleTypeDecl(child);
1539            } else if (name.equals(SchemaSymbols.ELT_COMPLEXTYPE )) {
1540                traverseComplexTypeDecl(child);
1541            } else if (name.equals(SchemaSymbols.ELT_GROUP)) {
1542                String JavaDoc dName = child.getAttribute(SchemaSymbols.ATT_NAME);
1543                if(fGroupNameRegistry.get(fTargetNSURIString +","+ dName) == null ||
1544                        ((fRestrictedRedefinedGroupRegistry.get(fTargetNSURIString+","+dName) != null) &&
1545                        !((Boolean JavaDoc)fRestrictedRedefinedGroupRegistry.get(fTargetNSURIString+","+dName)).booleanValue())) { // extension!
1546
traverseGroupDecl(child);
1547                    continue;
1548                }
1549                traverseGroupDecl(child);
1550                GroupInfo bGIObj = null;
1551                try {
1552                    bGIObj = (GroupInfo)fGroupNameRegistry.get(fTargetNSURIString +","+ dName+redefIdentifier);
1553                } catch(ClassCastException JavaDoc c) {
1554                    // if it's still a String, then we mustn't have found a corresponding attributeGroup in the redefined schema.
1555
// REVISIT: localize
1556
reportGenericSchemaError("src-redefine.6.2: a <group> within a <redefine> must either have a ref to a <group> with the same name or must restrict such an <group>");
1557                    continue;
1558                }
1559                if(bGIObj != null) { // we have something!
1560
int bCSIndex = bGIObj.contentSpecIndex;
1561                    GroupInfo dGIObj;
1562                    try {
1563                        dGIObj = (GroupInfo)fGroupNameRegistry.get(fTargetNSURIString+","+dName);
1564                    } catch (ClassCastException JavaDoc c) {
1565                        continue;
1566                    }
1567                    if(dGIObj == null) // something went wrong...
1568
continue;
1569                    int dCSIndex = dGIObj.contentSpecIndex;
1570                    try {
1571                      checkParticleDerivationOK(dCSIndex, -1, bCSIndex, -1, null);
1572                    }
1573                    catch (ParticleRecoverableError e) {
1574                      reportGenericSchemaError(e.getMessage());
1575                    }
1576                } else
1577                    // REVISIT: localize
1578
reportGenericSchemaError("src-redefine.6.2: a <group> within a <redefine> must either have a ref to a <group> with the same name or must restrict such an <group>");
1579            } else if (name.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
1580                if(fRedefineAttributeGroupMap != null) {
1581                    String JavaDoc dName = child.getAttribute(SchemaSymbols.ATT_NAME);
1582                    Object JavaDoc [] bAttGrpStore = null;
1583                    try {
1584                        bAttGrpStore = (Object JavaDoc [])fRedefineAttributeGroupMap.get(dName);
1585                    } catch(ClassCastException JavaDoc c) {
1586                        // if it's still a String, then we mustn't have found a corresponding attributeGroup in the redefined schema.
1587
// REVISIT: localize
1588
reportGenericSchemaError("src-redefine.7.2: an <attributeGroup> within a <redefine> must either have a ref to an <attributeGroup> with the same name or must restrict such an <attributeGroup>");
1589                        continue;
1590                    }
1591                    if(bAttGrpStore != null) { // we have something!
1592
ComplexTypeInfo bTypeInfo = (ComplexTypeInfo)bAttGrpStore[0];
1593                        SchemaGrammar bSchemaGrammar = (SchemaGrammar)bAttGrpStore[1];
1594                        Vector JavaDoc bAnyAttDecls = (Vector JavaDoc)bAttGrpStore[2];
1595                        XMLAttributeDecl bAnyAttDecl =
1596                            (bAnyAttDecls.size()>0 )? (XMLAttributeDecl)bAnyAttDecls.elementAt(0):null;
1597                        ComplexTypeInfo dTypeInfo = new ComplexTypeInfo();
1598                        int templateElementNameIndex = fStringPool.addSymbol("$"+dName);
1599                        int dTypeNameIndex = fStringPool.addSymbol("%"+dName);
1600                        dTypeInfo.scopeDefined = -2;
1601                        dTypeInfo.contentSpecHandle = -1;
1602                        dTypeInfo.contentType = XMLElementDecl.TYPE_SIMPLE;
1603                        dTypeInfo.datatypeValidator = null;
1604                        dTypeInfo.templateElementIndex = fSchemaGrammar.addElementDecl(
1605                            new QName(-1, templateElementNameIndex,dTypeNameIndex,fTargetNSURI),
1606                            (fTargetNSURI==StringPool.EMPTY_STRING) ? StringPool.EMPTY_STRING : -2, dTypeInfo.scopeDefined,
1607                            dTypeInfo.contentType,
1608                            dTypeInfo.contentSpecHandle, -1, dTypeInfo.datatypeValidator);
1609
1610                        Vector JavaDoc dAnyAttDecls = new Vector JavaDoc();
1611                        XMLAttributeDecl dAnyAttDecl =
1612                            (dAnyAttDecls.size()>0 )? (XMLAttributeDecl)dAnyAttDecls.elementAt(0):null;
1613                        traverseAttributeGroupDecl(child, dTypeInfo, dAnyAttDecls);
1614                        dTypeInfo.attlistHead = fSchemaGrammar.getFirstAttributeDeclIndex(
1615                                dTypeInfo.templateElementIndex);
1616                        try {
1617                            checkAttributesDerivationOKRestriction(dTypeInfo.attlistHead,fSchemaGrammar,
1618                                dAnyAttDecl,bTypeInfo.attlistHead,bSchemaGrammar,bAnyAttDecl);
1619                        }
1620                        catch (ComplexTypeRecoverableError e) {
1621                            String JavaDoc message = e.getMessage();
1622                            reportGenericSchemaError("src-redefine.7.2: redefinition failed because of " + message);
1623                        }
1624                        continue;
1625                    }
1626                }
1627                traverseAttributeGroupDecl(child, null, null);
1628            } // no else; error reported in the previous traversal
1629
} //for
1630

1631        // and restore the original globals
1632
fCurrentSchemaInfo = fCurrentSchemaInfo.getPrev();
1633        fCurrentSchemaInfo.restore();
1634    } // traverseRedefine
1635

1636    // the purpose of this method is twofold: 1. To find and appropriately modify all information items
1637
// in redefinedSchema with names that are redefined by children of
1638
// redefineDecl. 2. To make sure the redefine element represented by
1639
// redefineDecl is valid as far as content goes and with regard to
1640
// properly referencing components to be redefined. No traversing is done here!
1641
// This method also takes actions to find and, if necessary, modify the names
1642
// of elements in <redefine>'s in the schema that's being redefined.
1643
private void renameRedefinedComponents(Element JavaDoc redefineDecl, Element JavaDoc schemaToRedefine, SchemaInfo currSchemaInfo) throws Exception JavaDoc {
1644        for (Element JavaDoc child = XUtil.getFirstChildElement(redefineDecl);
1645                child != null;
1646                child = XUtil.getNextSiblingElement(child)) {
1647            String JavaDoc name = child.getLocalName();
1648            if (name.equals(SchemaSymbols.ELT_ANNOTATION) )
1649                continue;
1650            else if (name.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
1651                String JavaDoc typeName = child.getAttribute( SchemaSymbols.ATT_NAME );
1652                if(fTraversedRedefineElements.contains(typeName))
1653                    continue;
1654                if(validateRedefineNameChange(SchemaSymbols.ELT_SIMPLETYPE, typeName, typeName+redefIdentifier, child)) {
1655                    fixRedefinedSchema(SchemaSymbols.ELT_SIMPLETYPE,
1656                        typeName, typeName+redefIdentifier,
1657                        schemaToRedefine, currSchemaInfo);
1658                }
1659            } else if (name.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
1660                String JavaDoc typeName = child.getAttribute( SchemaSymbols.ATT_NAME );
1661                if(fTraversedRedefineElements.contains(typeName))
1662                    continue;
1663                if(validateRedefineNameChange(SchemaSymbols.ELT_COMPLEXTYPE, typeName, typeName+redefIdentifier, child)) {
1664                    fixRedefinedSchema(SchemaSymbols.ELT_COMPLEXTYPE,
1665                        typeName, typeName+redefIdentifier,
1666                        schemaToRedefine, currSchemaInfo);
1667                }
1668            } else if (name.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
1669                String JavaDoc baseName = child.getAttribute( SchemaSymbols.ATT_NAME );
1670                if(fTraversedRedefineElements.contains(baseName))
1671                    continue;
1672                if(validateRedefineNameChange(SchemaSymbols.ELT_ATTRIBUTEGROUP, baseName, baseName+redefIdentifier, child)) {
1673                    fixRedefinedSchema(SchemaSymbols.ELT_ATTRIBUTEGROUP,
1674                        baseName, baseName+redefIdentifier,
1675                        schemaToRedefine, currSchemaInfo);
1676                }
1677            } else if (name.equals(SchemaSymbols.ELT_GROUP)) {
1678                String JavaDoc baseName = child.getAttribute( SchemaSymbols.ATT_NAME );
1679                if(fTraversedRedefineElements.contains(baseName))
1680                    continue;
1681                if(validateRedefineNameChange(SchemaSymbols.ELT_GROUP, baseName, baseName+redefIdentifier, child)) {
1682                    fixRedefinedSchema(SchemaSymbols.ELT_GROUP,
1683                        baseName, baseName+redefIdentifier,
1684                        schemaToRedefine, currSchemaInfo);
1685                }
1686            } else {
1687                fRedefineSucceeded = false;
1688                // REVISIT: Localize
1689
reportGenericSchemaError("invalid top-level content for <redefine>");
1690                return;
1691            }
1692        } // for
1693
} // renameRedefinedComponents
1694

1695    // This function looks among the children of curr for an element of type elementSought.
1696
// If it finds one, it evaluates whether its ref attribute contains a reference
1697
// to originalName. If it does, it returns 1 + the value returned by
1698
// calls to itself on all other children. In all other cases it returns 0 plus
1699
// the sum of the values returned by calls to itself on curr's children.
1700
// It also resets the value of ref so that it will refer to the renamed type from the schema
1701
// being redefined.
1702
private int changeRedefineGroup(QName originalName, String JavaDoc elementSought, String JavaDoc newName, Element JavaDoc curr) throws Exception JavaDoc {
1703        int result = 0;
1704        for (Element JavaDoc child = XUtil.getFirstChildElement(curr);
1705                child != null; child = XUtil.getNextSiblingElement(child)) {
1706            String JavaDoc name = child.getLocalName();
1707            if (!name.equals(elementSought))
1708                result += changeRedefineGroup(originalName, elementSought, newName, child);
1709            else {
1710                String JavaDoc ref = child.getAttribute( SchemaSymbols.ATT_REF );
1711                if (ref.length() != 0) {
1712                    String JavaDoc prefix = "";
1713                    String JavaDoc localpart = ref;
1714                    int colonptr = ref.indexOf(":");
1715                    if ( colonptr > 0) {
1716                        prefix = ref.substring(0,colonptr);
1717                        localpart = ref.substring(colonptr+1);
1718                    }
1719                    String JavaDoc uriStr = resolvePrefixToURI(prefix);
1720                    if(originalName.equals(new QName(-1, fStringPool.addSymbol(localpart), fStringPool.addSymbol(localpart), fStringPool.addSymbol(uriStr)))) {
1721                        if(prefix.length() == 0)
1722                            child.setAttribute(SchemaSymbols.ATT_REF, newName);
1723                        else
1724                            child.setAttribute(SchemaSymbols.ATT_REF, prefix + ":" + newName);
1725                        result++;
1726                        if(elementSought.equals(SchemaSymbols.ELT_GROUP)) {
1727                            String JavaDoc minOccurs = child.getAttribute( SchemaSymbols.ATT_MINOCCURS );
1728                            String JavaDoc maxOccurs = child.getAttribute( SchemaSymbols.ATT_MAXOCCURS );
1729                            if(!((maxOccurs.length() == 0 || maxOccurs.equals("1"))
1730                                    && (minOccurs.length() == 0 || minOccurs.equals("1")))) {
1731                                //REVISIT: localize
1732
reportGenericSchemaError("src-redefine.6.1.2: the group " + ref + " which contains a reference to a group being redefined must have minOccurs = maxOccurs = 1");
1733                            }
1734                        }
1735                    }
1736                } // if ref was null some other stage of processing will flag the error
1737
}
1738        }
1739        return result;
1740    } // changeRedefineGroup
1741

1742    // This simple function looks for the first occurrence of an eltLocalname
1743
// schema information item and appropriately changes the value of
1744
// its name or type attribute from oldName to newName.
1745
// Root contains the root of the schema being operated upon.
1746
// If it turns out that what we're looking for is in a <redefine> though, then we
1747
// just rename it--and it's reference--to be the same and wait until
1748
// renameRedefineDecls can get its hands on it and do it properly.
1749
private void fixRedefinedSchema(String JavaDoc eltLocalname, String JavaDoc oldName, String JavaDoc newName, Element JavaDoc schemaToRedefine,
1750                SchemaInfo currSchema) throws Exception JavaDoc {
1751
1752        boolean foundIt = false;
1753        for (Element JavaDoc child = XUtil.getFirstChildElement(schemaToRedefine);
1754                child != null;
1755                child = XUtil.getNextSiblingElement(child)) {
1756            String JavaDoc name = child.getLocalName();
1757            if(name.equals(SchemaSymbols.ELT_REDEFINE)) { // need to search the redefine decl...
1758
for (Element JavaDoc redefChild = XUtil.getFirstChildElement(child);
1759                        redefChild != null;
1760                        redefChild = XUtil.getNextSiblingElement(redefChild)) {
1761                    String JavaDoc redefName = redefChild.getLocalName();
1762                    if (redefName.equals(eltLocalname) ) {
1763                        String JavaDoc infoItemName = redefChild.getAttribute( SchemaSymbols.ATT_NAME );
1764                        if(!infoItemName.equals(oldName))
1765                            continue;
1766                        else { // found it!
1767
foundIt = true;
1768                            openRedefinedSchema(child, currSchema);
1769                            if(!fRedefineSucceeded)
1770                                return;
1771                            NamespacesScope saveNSS = (NamespacesScope)fNamespacesScope.clone();
1772                            currSchema.restore();
1773                            if (validateRedefineNameChange(eltLocalname, oldName, newName+redefIdentifier, redefChild) &&
1774                                    (currSchema.getNext() != null)) {
1775                                currSchema.getNext().restore();
1776                                fixRedefinedSchema(eltLocalname, oldName, newName+redefIdentifier, fSchemaRootElement, currSchema.getNext());
1777                            }
1778                            fNamespacesScope = saveNSS;
1779                            redefChild.setAttribute( SchemaSymbols.ATT_NAME, newName );
1780                            // and we now know we will traverse this, so set fTraversedRedefineElements appropriately...
1781
fTraversedRedefineElements.addElement(newName);
1782                            currSchema.restore();
1783                            fCurrentSchemaInfo = currSchema;
1784                            break;
1785                        }
1786                    }
1787                } //for
1788
if (foundIt) break;
1789            }
1790            else if (name.equals(eltLocalname) ) {
1791                String JavaDoc infoItemName = child.getAttribute( SchemaSymbols.ATT_NAME );
1792                if(!infoItemName.equals(oldName))
1793                    continue;
1794                else { // found it!
1795
foundIt = true;
1796                    child.setAttribute( SchemaSymbols.ATT_NAME, newName );
1797                    break;
1798                }
1799            }
1800        } //for
1801
if(!foundIt) {
1802            fRedefineSucceeded = false;
1803            // REVISIT: localize
1804
reportGenericSchemaError("could not find a declaration in the schema to be redefined corresponding to " + oldName);
1805        }
1806    } // end fixRedefinedSchema
1807

1808    // this method returns true if the redefine component is valid, and if
1809
// it was possible to revise it correctly. The definition of
1810
// correctly will depend on whether renameRedefineDecls
1811
// or fixRedefineSchema is the caller.
1812
// this method also prepends a prefix onto newName if necessary; newName will never contain one.
1813
private boolean validateRedefineNameChange(String JavaDoc eltLocalname, String JavaDoc oldName, String JavaDoc newName, Element JavaDoc child) throws Exception JavaDoc {
1814        if (eltLocalname.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
1815            QName processedTypeName = new QName(-1, fStringPool.addSymbol(oldName), fStringPool.addSymbol(oldName), fTargetNSURI);
1816            Element JavaDoc grandKid = XUtil.getFirstChildElement(child);
1817            if (grandKid == null) {
1818                fRedefineSucceeded = false;
1819                // REVISIT: Localize
1820
reportGenericSchemaError("a simpleType child of a <redefine> must have a restriction element as a child");
1821            } else {
1822                String JavaDoc grandKidName = grandKid.getLocalName();
1823                if(grandKidName.equals(SchemaSymbols.ELT_ANNOTATION)) {
1824                    grandKid = XUtil.getNextSiblingElement(grandKid);
1825                    grandKidName = grandKid.getLocalName();
1826                }
1827                if (grandKid == null) {
1828                    fRedefineSucceeded = false;
1829                    // REVISIT: Localize
1830
reportGenericSchemaError("a simpleType child of a <redefine> must have a restriction element as a child");
1831                } else if(!grandKidName.equals(SchemaSymbols.ELT_RESTRICTION)) {
1832                    fRedefineSucceeded = false;
1833                    // REVISIT: Localize
1834
reportGenericSchemaError("a simpleType child of a <redefine> must have a restriction element as a child");
1835                } else {
1836                    String JavaDoc derivedBase = grandKid.getAttribute( SchemaSymbols.ATT_BASE );
1837                    QName processedDerivedBase = parseBase(derivedBase);
1838                    if(!processedTypeName.equals(processedDerivedBase)) {
1839                        fRedefineSucceeded = false;
1840                        // REVISIT: Localize
1841
reportGenericSchemaError("the base attribute of the restriction child of a simpleType child of a redefine must have the same value as the simpleType's type attribute");
1842                    } else {
1843                        // now we have to do the renaming...
1844
String JavaDoc prefix = "";
1845                        int colonptr = derivedBase.indexOf(":");
1846                        if ( colonptr > 0)
1847                            prefix = derivedBase.substring(0,colonptr) + ":";
1848                        grandKid.setAttribute( SchemaSymbols.ATT_BASE, prefix + newName );
1849                        return true;
1850                    }
1851                }
1852            }
1853        } else if (eltLocalname.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
1854            QName processedTypeName = new QName(-1, fStringPool.addSymbol(oldName), fStringPool.addSymbol(oldName), fTargetNSURI);
1855            Element JavaDoc grandKid = XUtil.getFirstChildElement(child);
1856            if (grandKid == null) {
1857                fRedefineSucceeded = false;
1858                // REVISIT: Localize
1859
reportGenericSchemaError("a complexType child of a <redefine> must have a restriction or extension element as a grandchild");
1860            } else {
1861                if(grandKid.getLocalName().equals(SchemaSymbols.ELT_ANNOTATION)) {
1862                    grandKid = XUtil.getNextSiblingElement(grandKid);
1863                }
1864                if (grandKid == null) {
1865                    fRedefineSucceeded = false;
1866                    // REVISIT: Localize
1867
reportGenericSchemaError("a complexType child of a <redefine> must have a restriction or extension element as a grandchild");
1868                } else {
1869                    // have to go one more level down; let another pass worry whether complexType is valid.
1870
Element JavaDoc greatGrandKid = XUtil.getFirstChildElement(grandKid);
1871                    if (greatGrandKid == null) {
1872                        fRedefineSucceeded = false;
1873                        // REVISIT: Localize
1874
reportGenericSchemaError("a complexType child of a <redefine> must have a restriction or extension element as a grandchild");
1875                    } else {
1876                        String JavaDoc greatGrandKidName = greatGrandKid.getLocalName();
1877                        if(greatGrandKidName.equals(SchemaSymbols.ELT_ANNOTATION)) {
1878                            greatGrandKid = XUtil.getNextSiblingElement(greatGrandKid);
1879                            greatGrandKidName = greatGrandKid.getLocalName();
1880                        }
1881                        if (greatGrandKid == null) {
1882                            fRedefineSucceeded = false;
1883                            // REVISIT: Localize
1884
reportGenericSchemaError("a complexType child of a <redefine> must have a restriction or extension element as a grandchild");
1885                        } else if(!greatGrandKidName.equals(SchemaSymbols.ELT_RESTRICTION) &&
1886                                !greatGrandKidName.equals(SchemaSymbols.ELT_EXTENSION)) {
1887                            fRedefineSucceeded = false;
1888                            // REVISIT: Localize
1889
reportGenericSchemaError("a complexType child of a <redefine> must have a restriction or extension element as a grandchild");
1890                        } else {
1891                            String JavaDoc derivedBase = greatGrandKid.getAttribute( SchemaSymbols.ATT_BASE );
1892                            QName processedDerivedBase = parseBase(derivedBase);
1893                            if(!processedTypeName.equals(processedDerivedBase)) {
1894                                fRedefineSucceeded = false;
1895                                // REVISIT: Localize
1896
reportGenericSchemaError("the base attribute of the restriction or extension grandchild of a complexType child of a redefine must have the same value as the complexType's type attribute");
1897                            } else {
1898                                // now we have to do the renaming...
1899
String JavaDoc prefix = "";
1900                                int colonptr = derivedBase.indexOf(":");
1901                                if ( colonptr > 0)
1902                                    prefix = derivedBase.substring(0,colonptr) + ":";
1903                                greatGrandKid.setAttribute( SchemaSymbols.ATT_BASE, prefix + newName );
1904                                return true;
1905                            }
1906                        }
1907                    }
1908                }
1909            }
1910        } else if (eltLocalname.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP)) {
1911            QName processedBaseName = new QName(-1, fStringPool.addSymbol(oldName), fStringPool.addSymbol(oldName), fTargetNSURI);
1912            int attGroupRefsCount = changeRedefineGroup(processedBaseName, eltLocalname, newName, child);
1913            if(attGroupRefsCount > 1) {
1914                fRedefineSucceeded = false;
1915                // REVISIT: localize
1916
reportGenericSchemaError("if an attributeGroup child of a <redefine> element contains an attributeGroup ref'ing itself, it must have exactly 1; this one has " + attGroupRefsCount);
1917            } else if (attGroupRefsCount == 1) {
1918                return true;
1919            } else
1920                fRedefineAttributeGroupMap.put(oldName, newName);
1921        } else if (eltLocalname.equals(SchemaSymbols.ELT_GROUP)) {
1922            QName processedBaseName = new QName(-1, fStringPool.addSymbol(oldName), fStringPool.addSymbol(oldName), fTargetNSURI);
1923            int groupRefsCount = changeRedefineGroup(processedBaseName, eltLocalname, newName, child);
1924            String JavaDoc restrictedName = newName.substring(0, newName.length()-redefIdentifier.length());
1925            if(!fRedefineSucceeded) {
1926                fRestrictedRedefinedGroupRegistry.put(fTargetNSURIString+","+restrictedName, new Boolean JavaDoc(false));
1927            }
1928            if(groupRefsCount > 1) {
1929                fRedefineSucceeded = false;
1930                fRestrictedRedefinedGroupRegistry.put(fTargetNSURIString+","+restrictedName, new Boolean JavaDoc(false));
1931                // REVISIT: localize
1932
reportGenericSchemaError("if a group child of a <redefine> element contains a group ref'ing itself, it must have exactly 1; this one has " + groupRefsCount);
1933            } else if (groupRefsCount == 1) {
1934                fRestrictedRedefinedGroupRegistry.put(fTargetNSURIString+","+restrictedName, new Boolean JavaDoc(false));
1935                return true;
1936            } else {
1937                fGroupNameRegistry.put(fTargetNSURIString + "," + oldName, newName);
1938                fRestrictedRedefinedGroupRegistry.put(fTargetNSURIString+","+restrictedName, new Boolean JavaDoc(true));
1939            }
1940        } else {
1941            fRedefineSucceeded = false;
1942            // REVISIT: Localize
1943
reportGenericSchemaError("internal Xerces error; please submit a bug with schema as testcase");
1944        }
1945        // if we get here then we must have reported an error and failed somewhere...
1946
return false;
1947    } // validateRedefineNameChange
1948

1949    private void traverseImport(Element JavaDoc importDecl) throws Exception JavaDoc {
1950        // General Attribute Checking
1951
int scope = GeneralAttrCheck.ELE_CONTEXT_GLOBAL;
1952        Hashtable JavaDoc attrValues = generalCheck(importDecl, scope);
1953        checkContent(importDecl, XUtil.getFirstChildElement(importDecl), true);
1954
1955         String JavaDoc namespaceString = importDecl.getAttribute(SchemaSymbols.ATT_NAMESPACE);
1956         SchemaGrammar importedGrammar = (SchemaGrammar) fGrammarResolver.getGrammar(namespaceString);
1957
1958         if ((importedGrammar == null) || namespaceString.trim().equals(fTargetNSURIString)) {
1959             importedGrammar = new SchemaGrammar();
1960         } else {
1961             return;
1962         }
1963
1964         Element JavaDoc root = null;
1965         if(namespaceString.length() == 0) {
1966            if(fTargetNSURI == StringPool.EMPTY_STRING) {
1967                // REVISIT: localize
1968
reportGenericSchemaError("src-import.1.2: if the namespace attribute on an <import> element is not present, the <import>ing schema must have a targetNamespace");
1969                // look in external-noNamespaceSchemaLocation property!
1970
if(fExternalNoNamespaceSchema != null) {
1971                    root = openImportedSchema(fExternalNoNamespaceSchema);
1972                }
1973            }
1974        } else {
1975            if(fTargetNSURIString.equals(namespaceString.trim())) {
1976                // REVISIT: localize
1977
reportGenericSchemaError("src-import.1.1: the namespace attribute of an <import> element must not be the same as the targetNamespace of the <import>ing schema");
1978                // look in external-schemaLocation property!
1979
if(fExternalSchemas != null) {
1980                    Enumeration JavaDoc externalNamespaces = fExternalSchemas.keys();
1981                    while(externalNamespaces.hasMoreElements()) {
1982                        String JavaDoc namespace = (String JavaDoc)externalNamespaces.nextElement();
1983                        if(namespace.trim().equals(namespaceString.trim())) {
1984                            root = openImportedSchema((String JavaDoc)fExternalSchemas.get(namespace));
1985                            break;
1986                        }
1987                    }
1988                }
1989            }
1990        }
1991        String JavaDoc location = "";
1992        if(root == null) { // try our own schemaLocation
1993
Attr JavaDoc locationAttr = importDecl.getAttributeNode(SchemaSymbols.ATT_SCHEMALOCATION);
1994            if(locationAttr != null) {
1995                location = locationAttr.getValue();
1996                root = openImportedSchema(location);
1997            }
1998         }
1999         if (root != null) {
2000             String JavaDoc targetNSURI = getTargetNamespaceString(root);
2001             if (!targetNSURI.equals(namespaceString) ) {
2002                 // REVISIT: Localize
2003
reportGenericSchemaError("imported schema '"+location+"' has a different targetNameSpace '"
2004                                          +targetNSURI+"' from what is declared '"+namespaceString+"'.");
2005             }
2006             else {
2007                 location = fCurrentSchemaURL;
2008                 TraverseSchema impSchema = new TraverseSchema(root, fStringPool, importedGrammar, fGrammarResolver, fErrorReporter, location, fEntityResolver, fFullConstraintChecking, fGeneralAttrCheck, fUnparsedExternalSchemas, fExternalNoNamespaceSchema);
2009                 fCurrentSchemaURL = (String JavaDoc)fSchemaURLStack.pop();
2010                 Enumeration JavaDoc ics = impSchema.fIdentityConstraints.keys();
2011                 while(ics.hasMoreElements()) {
2012                    Object JavaDoc icsKey = ics.nextElement();
2013                    fIdentityConstraints.put(icsKey, impSchema.fIdentityConstraints.get(icsKey));
2014                }
2015                 Enumeration JavaDoc icNames = impSchema.fIdentityConstraintNames.keys();
2016                 while(icNames.hasMoreElements()) {
2017                    String JavaDoc icsNameKey = (String JavaDoc)icNames.nextElement();
2018                    fIdentityConstraintNames.put(icsNameKey, impSchema.fIdentityConstraintNames.get(icsNameKey));
2019                }
2020            }
2021         }
2022    }
2023
2024    private Element JavaDoc openImportedSchema(String JavaDoc location) throws Exception JavaDoc {
2025        // expand it before passing it to the parser
2026
InputSource JavaDoc source = null;
2027
2028        // If fEntityResolver is not null and is not the default, only then use it - Gopal Sharma, Sun Microsystems Inc.
2029
if ( (fEntityResolver != null) &&
2030             !(fEntityResolver.getClass().getName().equals("org.enhydra.apache.xerces.validators.common.XMLValidator$Resolver")) ) {
2031            source = fEntityResolver.resolveEntity("", location);
2032        }
2033
2034        if (source == null) {
2035            location = expandSystemId(location, fCurrentSchemaURL);
2036            source = new InputSource JavaDoc(location);
2037        }
2038         // create a string for uniqueness of this imported schema in fImportLocations
2039
// algorithm: string is pubId+sysId or if both null then filename
2040
String JavaDoc pubId = "";
2041        String JavaDoc sysId = "";
2042        if (source.getPublicId () != null)
2043            pubId = source.getPublicId ();
2044        if (source.getSystemId () != null)
2045            sysId = source.getSystemId ();
2046
2047        if(pubId.length() != 0 || sysId.length() != 0)
2048            location = pubId+sysId;
2049
2050         if (fImportLocations.contains((Object JavaDoc)location)) {
2051             return null;
2052         }
2053        // check to make sure we're not importing ourselves...
2054
if(source.getSystemId().equals(fCurrentSchemaURL)) {
2055            // REVISIT: localize
2056
return null;
2057        }
2058
2059         DOMParser parser = new IgnoreWhitespaceParser();
2060         parser.setEntityResolver( (fEntityResolver != null)? (fEntityResolver):(new Resolver()) );
2061         parser.setErrorHandler( new ErrorHandler ()
2062            {
2063                public void error(SAXParseException JavaDoc ex) throws SAXException JavaDoc {
2064                    StringBuffer JavaDoc str = new StringBuffer JavaDoc();
2065                    String JavaDoc systemId_ = ex.getSystemId();
2066                    if (systemId_ != null) {
2067                        int index = systemId_.lastIndexOf('/');
2068                        if (index != -1)
2069                            systemId_ = systemId_.substring(index + 1);
2070                        str.append(systemId_);
2071                    }
2072                    str.append(':').append(ex.getLineNumber()).append(':').append(ex.getColumnNumber());
2073                    String JavaDoc message = ex.getMessage();
2074                    if(message.toLowerCase().trim().endsWith("not found.")) {
2075                        System.err.println("[Warning] "+
2076                               str.toString()+": "+ message);
2077                    } else { // do standard thing
2078
System.err.println("[Error] "+
2079                               str.toString()+":"+message);
2080                        throw ex;
2081                    }
2082                }
2083            });
2084
2085         try {
2086             parser.setFeature("http://xml.org/sax/features/validation", false);
2087             parser.setFeature("http://xml.org/sax/features/namespaces", true);
2088             parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
2089             parser.setFeature("http://apache.org/xml/features/continue-after-fatal-error", true);
2090         }catch( org.xml.sax.SAXNotRecognizedException JavaDoc e ) {
2091             e.printStackTrace();
2092         }catch( org.xml.sax.SAXNotSupportedException JavaDoc e ) {
2093             e.printStackTrace();
2094         }
2095
2096         try {
2097             parser.parse( source );
2098         }catch( IOException JavaDoc e ) {
2099             // e.printStackTrace();
2100
}catch( SAXException JavaDoc e ) {
2101             e.printStackTrace();
2102         }
2103
2104         Document JavaDoc document = parser.getDocument(); //Our Grammar
2105
Element JavaDoc root = null;
2106         if (document != null) {
2107             root = document.getDocumentElement();
2108         }
2109         if(root != null) {
2110            fImportLocations.addElement((Object JavaDoc)location);
2111        }
2112        fSchemaURLStack.push(fCurrentSchemaURL);
2113        fCurrentSchemaURL = location;
2114        return root;
2115    } // openImportedSchema
2116

2117    // utility method for finding the targetNamespace (and flagging errors if they occur)
2118
private String JavaDoc getTargetNamespaceString( Element JavaDoc root) throws Exception JavaDoc {
2119        String JavaDoc targetNSURI = "";
2120        Attr JavaDoc targetNSAttr = root.getAttributeNode(SchemaSymbols.ATT_TARGETNAMESPACE);
2121        if(targetNSAttr != null) {
2122            targetNSURI=targetNSAttr.getValue();
2123            if(targetNSURI.length() == 0) {
2124                // REVISIT: localize
2125
reportGenericSchemaError("sch-prop-correct.1: \"\" is not a legal value for the targetNamespace attribute; the attribute must either be absent or contain a nonempty value");
2126            }
2127        }
2128        return targetNSURI;
2129    } // end getTargetNamespaceString(Element)
2130

2131    /**
2132    * <annotation>(<appinfo> | <documentation>)*</annotation>
2133    *
2134    * @param annotationDecl: the DOM node corresponding to the <annotation> info item
2135    */

2136    private void traverseAnnotationDecl(Element JavaDoc annotationDecl) throws Exception JavaDoc {
2137
2138        // General Attribute Checking
2139
int scope = GeneralAttrCheck.ELE_CONTEXT_LOCAL;
2140        Hashtable JavaDoc attrValues = generalCheck(annotationDecl, scope);
2141
2142        for(Element JavaDoc child = XUtil.getFirstChildElement(annotationDecl); child != null;
2143                 child = XUtil.getNextSiblingElement(child)) {
2144            String JavaDoc name = child.getLocalName();
2145            if(!((name.equals(SchemaSymbols.ELT_APPINFO)) ||
2146                    (name.equals(SchemaSymbols.ELT_DOCUMENTATION)))) {
2147                // REVISIT: Localize
2148
reportGenericSchemaError("an <annotation> can only contain <appinfo> and <documentation> elements");
2149            }
2150
2151            // General Attribute Checking
2152
attrValues = generalCheck(child, scope);
2153        }
2154    }
2155
2156
2157    //
2158
// Evaluates content of Annotation if present.
2159
//
2160
// @param: elm - top element
2161
// @param: content - content must be annotation? or some other simple content
2162
// @param: isEmpty: -- true if the content allowed is (annotation?) only
2163
// false if must have some element (with possible preceding <annotation?>)
2164
//
2165
//REVISIT: this function should be used in all traverse* methods!
2166
private Element JavaDoc checkContent( Element JavaDoc elm, Element JavaDoc content, boolean isEmpty ) throws Exception JavaDoc {
2167       //isEmpty = true-> means content can be null!
2168
if ( content == null) {
2169           if (!isEmpty) {
2170               reportSchemaError(SchemaMessageProvider.ContentError,
2171                                 new Object JavaDoc [] { elm.getAttribute( SchemaSymbols.ATT_NAME )});
2172           }
2173           return null;
2174       }
2175       if (content.getLocalName().equals(SchemaSymbols.ELT_ANNOTATION)) {
2176           traverseAnnotationDecl( content );
2177           content = XUtil.getNextSiblingElement(content);
2178           if (content == null ) { //must be followed by <simpleType?>
2179
if (!isEmpty) {
2180                   reportSchemaError(SchemaMessageProvider.ContentError,
2181                                     new Object JavaDoc [] { elm.getAttribute( SchemaSymbols.ATT_NAME )});
2182               }
2183               return null;
2184           }
2185           if (content.getLocalName().equals(SchemaSymbols.ELT_ANNOTATION)) {
2186               reportSchemaError(SchemaMessageProvider.AnnotationError,
2187                                 new Object JavaDoc [] { elm.getAttribute( SchemaSymbols.ATT_NAME )});
2188               return null;
2189           }
2190           //return null if expected only annotation?, else returns updated content
2191
}
2192       return content;
2193   }
2194
2195
2196   //@param: elm - top element
2197
//@param: baseTypeStr - type (base/itemType/memberTypes)
2198
//@param: baseRefContext: whether the caller is using this type as a base for restriction, union or list
2199
//return DatatypeValidator available for the baseTypeStr, null if not found or disallowed.
2200
// also throws an error if the base type won't allow itself to be used in this context.
2201
//REVISIT: this function should be used in some|all traverse* methods!
2202
private DatatypeValidator findDTValidator (Element JavaDoc elm, String JavaDoc baseTypeStr, int baseRefContext ) throws Exception JavaDoc{
2203        int baseType = fStringPool.addSymbol( baseTypeStr );
2204        String JavaDoc prefix = "";
2205        DatatypeValidator baseValidator = null;
2206        String JavaDoc localpart = baseTypeStr;
2207        int colonptr = baseTypeStr.indexOf(":");
2208        if ( colonptr > 0) {
2209            prefix = baseTypeStr.substring(0,colonptr);
2210            localpart = baseTypeStr.substring(colonptr+1);
2211        }
2212        String JavaDoc uri = resolvePrefixToURI(prefix);
2213        if (uri.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA) &&
2214            localpart.equals("anySimpleType") &&
2215            baseRefContext == SchemaSymbols.RESTRICTION) {
2216            reportSchemaError(SchemaMessageProvider.UnknownBaseDatatype,
2217                              new Object JavaDoc [] { elm.getAttribute( SchemaSymbols.ATT_BASE ),
2218                                              elm.getAttribute(SchemaSymbols.ATT_NAME)});
2219            return null;
2220        }
2221        baseValidator = getDatatypeValidator(uri, localpart);
2222        if (baseValidator == null) {
2223            Element JavaDoc baseTypeNode = getTopLevelComponentByName(SchemaSymbols.ELT_SIMPLETYPE, localpart);
2224            if (baseTypeNode != null) {
2225                traverseSimpleTypeDecl( baseTypeNode );
2226
2227                baseValidator = getDatatypeValidator(uri, localpart);
2228            }
2229        }
2230        Integer JavaDoc finalValue;
2231        if ( baseValidator == null ) {
2232            reportSchemaError(SchemaMessageProvider.UnknownBaseDatatype,
2233                              new Object JavaDoc [] { elm.getAttribute( SchemaSymbols.ATT_BASE ),
2234                                  elm.getAttribute(SchemaSymbols.ATT_NAME)});
2235        } else {
2236            finalValue =
2237                    ((Integer JavaDoc)fSimpleTypeFinalRegistry.get(uri + "," +localpart));
2238            if((finalValue != null) &&
2239                    ((finalValue.intValue() & baseRefContext) != 0)) {
2240                //REVISIT: localize
2241
reportGenericSchemaError("the base type " + baseTypeStr + " does not allow itself to be used as the base for a restriction and/or as a type in a list and/or union");
2242                return baseValidator;
2243            }
2244        }
2245       return baseValidator;
2246    }
2247
2248    private void checkEnumerationRequiredNotation(String JavaDoc name, String JavaDoc type) throws Exception JavaDoc{
2249        String JavaDoc localpart = type;
2250        int colonptr = type.indexOf(":");
2251        if ( colonptr > 0) {
2252            localpart = type.substring(colonptr+1);
2253        }
2254        if (localpart.equals("NOTATION")) {
2255          reportGenericSchemaError("[enumeration-required-notation] It is an error for NOTATION to be used "+
2256                                "directly in a schema in element/attribute '"+name+"'");
2257        }
2258
2259    }
2260
2261   // @used in traverseSimpleType
2262
// on return we need to pop the last simpleType name from
2263
// the name stack
2264
private int resetSimpleTypeNameStack(int returnValue){
2265       if (!fSimpleTypeNameStack.empty()) {
2266           fSimpleTypeNameStack.pop();
2267       }
2268       return returnValue;
2269    }
2270
2271    // @used in traverseSimpleType
2272
// report an error cos-list-of-atomic and reset the last name of the list datatype we traversing
2273
private void reportCosListOfAtomic () throws Exception JavaDoc{
2274       reportGenericSchemaError("cos-list-of-atomic: The itemType must have a {variety} of atomic or union (in which case all the {member type definitions} must be atomic)");
2275       fListName="";
2276    }
2277
2278    // @used in traverseSimpleType
2279
// find if union datatype validator has list datatype member.
2280
private boolean isListDatatype (DatatypeValidator validator){
2281       if (validator instanceof UnionDatatypeValidator) {
2282              Vector JavaDoc temp = ((UnionDatatypeValidator)validator).getBaseValidators();
2283              for (int i=0;i<temp.size();i++) {
2284                   if (temp.elementAt(i) instanceof ListDatatypeValidator) {
2285                       return true;
2286                   }
2287                   if (temp.elementAt(i) instanceof UnionDatatypeValidator) {
2288                       if (isListDatatype((DatatypeValidator)temp.elementAt(i))) {
2289                           return true;
2290                       }
2291                   }
2292              }
2293       }
2294       return false;
2295    }
2296
2297
2298
2299   /**
2300     * Traverse SimpleType declaration:
2301     * <simpleType
2302     * final = #all | list of (restriction, union or list)
2303     * id = ID
2304     * name = NCName>
2305     * Content: (annotation? , ((list | restriction | union)))
2306     * </simpleType>
2307     * traverse <list>|<restriction>|<union>
2308     *
2309     * @param simpleTypeDecl
2310     * @return
2311     */

2312    private int traverseSimpleTypeDecl( Element JavaDoc simpleTypeDecl ) throws Exception JavaDoc {
2313
2314        // General Attribute Checking
2315
int scope = isTopLevel(simpleTypeDecl)?
2316                    GeneralAttrCheck.ELE_CONTEXT_GLOBAL:
2317                    GeneralAttrCheck.ELE_CONTEXT_LOCAL;
2318        Hashtable JavaDoc attrValues = generalCheck(simpleTypeDecl, scope);
2319
2320        String JavaDoc nameProperty = simpleTypeDecl.getAttribute( SchemaSymbols.ATT_NAME );
2321        String JavaDoc qualifiedName = nameProperty;
2322
2323
2324        //---------------------------------------------------
2325
// set qualified name
2326
//---------------------------------------------------
2327
if ( nameProperty.length() == 0) { // anonymous simpleType
2328
qualifiedName = fTargetNSURIString+","+"#S#"+(fSimpleTypeAnonCount++);
2329            fStringPool.addSymbol(qualifiedName);
2330        }
2331        else {
2332            // this behaviour has been changed so that we neither
2333
// process unqualified names as if they came from the schemaforschema namespace nor
2334
// fail to pick up unqualified names from schemas with no
2335
// targetnamespace. - NG
2336
//if (fTargetNSURIString.length () != 0) {
2337
qualifiedName = fTargetNSURIString+","+qualifiedName;
2338            //}
2339
fStringPool.addSymbol( nameProperty );
2340        }
2341
2342        //----------------------------------------------------------------------
2343
//check if we have already traversed the same simpleType decl
2344
//----------------------------------------------------------------------
2345
if (fDatatypeRegistry.getDatatypeValidator(qualifiedName)!=null) {
2346            return resetSimpleTypeNameStack(fStringPool.addSymbol(qualifiedName));
2347        }
2348        else {
2349           if (fSimpleTypeNameStack.search(qualifiedName) != -1 ){
2350               // cos-no-circular-unions && no circular definitions
2351
reportGenericSchemaError("cos-no-circular-unions: no circular definitions are allowed for an element '"+ nameProperty+"'");
2352               return resetSimpleTypeNameStack(-1);
2353           }
2354        }
2355
2356
2357        //----------------------------------------------------------
2358
// update _final_ registry
2359
//----------------------------------------------------------
2360
Attr JavaDoc finalAttr = simpleTypeDecl.getAttributeNode(SchemaSymbols.ATT_FINAL);
2361        int finalProperty = 0;
2362        if(finalAttr != null)
2363            finalProperty = parseFinalSet(finalAttr.getValue());
2364        else
2365            finalProperty = parseFinalSet(null);
2366
2367        // if we have a nonzero final , store it in the hash...
2368
if(finalProperty != 0)
2369            fSimpleTypeFinalRegistry.put(qualifiedName, new Integer JavaDoc(finalProperty));
2370
2371
2372        // -------------------------------
2373
// remember name being traversed to
2374
// avoid circular definitions in union
2375
// -------------------------------
2376
fSimpleTypeNameStack.push(qualifiedName);
2377
2378
2379        //----------------------------------------------------------------------
2380
//annotation?,(list|restriction|union)
2381
//----------------------------------------------------------------------
2382
Element JavaDoc content = XUtil.getFirstChildElement(simpleTypeDecl);
2383        content = checkContent(simpleTypeDecl, content, false);
2384        if (content == null) {
2385            return resetSimpleTypeNameStack(-1);
2386        }
2387
2388        // General Attribute Checking
2389
scope = GeneralAttrCheck.ELE_CONTEXT_LOCAL;
2390        Hashtable JavaDoc contentAttrs = generalCheck(content, scope);
2391
2392        //----------------------------------------------------------------------
2393
//use content.getLocalName for the cases there "xsd:" is a prefix, ei. "xsd:list"
2394
//----------------------------------------------------------------------
2395
String JavaDoc varietyProperty = content.getLocalName();
2396        String JavaDoc baseTypeQNameProperty = null;
2397        Vector JavaDoc dTValidators = null;
2398        int size = 0;
2399        StringTokenizer JavaDoc unionMembers = null;
2400        boolean list = false;
2401        boolean union = false;
2402        boolean restriction = false;
2403        int numOfTypes = 0; //list/restriction = 1, union = "+"
2404

2405        if (varietyProperty.equals(SchemaSymbols.ELT_LIST)) { //traverse List
2406
baseTypeQNameProperty = content.getAttribute( SchemaSymbols.ATT_ITEMTYPE );
2407           list = true;
2408           if (fListName.length() != 0) { // parent is <list> datatype
2409
reportCosListOfAtomic();
2410                    return resetSimpleTypeNameStack(-1);
2411           }
2412           else {
2413                fListName = qualifiedName;
2414           }
2415        }
2416        else if (varietyProperty.equals(SchemaSymbols.ELT_RESTRICTION)) { //traverse Restriction
2417
baseTypeQNameProperty = content.getAttribute( SchemaSymbols.ATT_BASE );
2418            restriction= true;
2419        }
2420        else if (varietyProperty.equals(SchemaSymbols.ELT_UNION)) { //traverse union
2421
union = true;
2422            baseTypeQNameProperty = content.getAttribute( SchemaSymbols.ATT_MEMBERTYPES);
2423            if (baseTypeQNameProperty.length() != 0) {
2424                unionMembers = new StringTokenizer JavaDoc( baseTypeQNameProperty );
2425                size = unionMembers.countTokens();
2426            }
2427            else {
2428                size = 1; //at least one must be seen as <simpleType> decl
2429
}
2430            dTValidators = new Vector JavaDoc (size, 2);
2431        }
2432        else {
2433             reportSchemaError(SchemaMessageProvider.FeatureUnsupported,
2434                       new Object JavaDoc [] { varietyProperty });
2435                       return -1;
2436        }
2437        if(XUtil.getNextSiblingElement(content) != null) {
2438            // REVISIT: Localize
2439
reportGenericSchemaError("error in content of simpleType");
2440        }
2441
2442        int typeNameIndex;
2443        DatatypeValidator baseValidator = null;
2444
2445        if ( baseTypeQNameProperty.length() == 0 ) {
2446            //---------------------------
2447
//must 'see' <simpleType>
2448
//---------------------------
2449

2450            //content = {annotation?,simpleType?...}
2451
content = XUtil.getFirstChildElement(content);
2452
2453            //check content (annotation?, ...)
2454
content = checkContent(simpleTypeDecl, content, false);
2455            if (content == null) {
2456                return resetSimpleTypeNameStack(-1);
2457            }
2458            if (content.getLocalName().equals( SchemaSymbols.ELT_SIMPLETYPE )) {
2459              typeNameIndex = traverseSimpleTypeDecl(content);
2460              if (typeNameIndex!=-1) {
2461                  baseValidator=fDatatypeRegistry.getDatatypeValidator(fStringPool.toString(typeNameIndex));
2462                  if (baseValidator !=null && union) {
2463                      dTValidators.addElement((DatatypeValidator)baseValidator);
2464                  }
2465              }
2466              if ( typeNameIndex == -1 || baseValidator == null) {
2467                  reportSchemaError(SchemaMessageProvider.UnknownBaseDatatype,
2468                                        new Object JavaDoc [] { content.getAttribute( SchemaSymbols.ATT_BASE ),
2469                                            content.getAttribute(SchemaSymbols.ATT_NAME) });
2470                      return resetSimpleTypeNameStack(-1);
2471              }
2472            }
2473            else {
2474                 reportSchemaError(SchemaMessageProvider.ListUnionRestrictionError,
2475                        new Object JavaDoc [] { simpleTypeDecl.getAttribute( SchemaSymbols.ATT_NAME )});
2476                 return resetSimpleTypeNameStack(-1);
2477            }
2478        } //end - must see simpleType?
2479
else {
2480            //-----------------------------
2481
//base was provided - get proper validator.
2482
//-----------------------------
2483
numOfTypes = 1;
2484            if (union) {
2485                numOfTypes= size;
2486            }
2487            //--------------------------------------------------------------------
2488
// this loop is also where we need to find out whether the type being used as
2489
// a base (or itemType or whatever) allows such things.
2490
//--------------------------------------------------------------------
2491
int baseRefContext = (restriction? SchemaSymbols.RESTRICTION:0);
2492            baseRefContext = baseRefContext | (union? SchemaSymbols.UNION:0);
2493            baseRefContext = baseRefContext | (list ? SchemaSymbols.LIST:0);
2494            for (int i=0; i<numOfTypes; i++) { //find all validators
2495
if (union) {
2496                    baseTypeQNameProperty = unionMembers.nextToken();
2497                }
2498                baseValidator = findDTValidator ( simpleTypeDecl, baseTypeQNameProperty, baseRefContext);
2499                if ( baseValidator == null) {
2500                    return resetSimpleTypeNameStack(-1);
2501                }
2502                // ------------------------------
2503
// (variety is list)cos-list-of-atomic
2504
// ------------------------------
2505
if (fListName.length() != 0 ) {
2506                    if (baseValidator instanceof ListDatatypeValidator) {
2507                        reportCosListOfAtomic();
2508                        return resetSimpleTypeNameStack(-1);
2509                    }
2510                    //-----------------------------------------------------
2511
// if baseValidator is of type (union) need to look
2512
// at Union validators to make sure that List is not one of them
2513
//-----------------------------------------------------
2514
if (isListDatatype(baseValidator)) {
2515                        reportCosListOfAtomic();
2516                        return resetSimpleTypeNameStack(-1);
2517
2518                    }
2519
2520                }
2521                if (union) {
2522                    dTValidators.addElement((DatatypeValidator)baseValidator); //add validator to structure
2523
}
2524            }
2525        } //end - base is available
2526

2527
2528        // ------------------------------------------
2529
// move to next child
2530
// <base==empty)->[simpleType]->[facets] OR
2531
// <base!=empty)->[facets]
2532
// ------------------------------------------
2533
if (baseTypeQNameProperty.length() == 0) {
2534            content = XUtil.getNextSiblingElement( content );
2535        }
2536        else {
2537            content = XUtil.getFirstChildElement(content);
2538        }
2539
2540        // ------------------------------------------
2541
//get more types for union if any
2542
// ------------------------------------------
2543
if (union) {
2544            int index=size;
2545            if (baseTypeQNameProperty.length() != 0 ) {
2546                content = checkContent(simpleTypeDecl, content, true);
2547            }
2548            while (content!=null) {
2549                typeNameIndex = traverseSimpleTypeDecl(content);
2550                if (typeNameIndex!=-1) {
2551                    baseValidator=fDatatypeRegistry.getDatatypeValidator(fStringPool.toString(typeNameIndex));
2552                    if (baseValidator != null) {
2553                        if (fListName.length() != 0 && baseValidator instanceof ListDatatypeValidator) {
2554                            reportCosListOfAtomic();
2555                            return resetSimpleTypeNameStack(-1);
2556                        }
2557                        dTValidators.addElement((DatatypeValidator)baseValidator);
2558                    }
2559                }
2560                if ( baseValidator == null || typeNameIndex == -1) {
2561                     reportSchemaError(SchemaMessageProvider.UnknownBaseDatatype,
2562                                      new Object JavaDoc [] { simpleTypeDecl.getAttribute( SchemaSymbols.ATT_BASE ),
2563                                          simpleTypeDecl.getAttribute(SchemaSymbols.ATT_NAME)});
2564                    return (-1);
2565                }
2566                content = XUtil.getNextSiblingElement( content );
2567            }
2568        } // end - traverse Union
2569

2570
2571        if (fListName.length() != 0) {
2572            // reset fListName, meaning that we are done with
2573
// traversing <list> and its itemType resolves to atomic value
2574
if (fListName.equals(qualifiedName)) {
2575                fListName = "";
2576            }
2577        }
2578
2579        int numFacets=0;
2580        fFacetData.clear();
2581        if (restriction && content != null) {
2582            short flags = 0; // flag facets that have fixed="true"
2583
int numEnumerationLiterals = 0;
2584            Vector JavaDoc enumData = new Vector JavaDoc();
2585            content = checkContent(simpleTypeDecl, content , true);
2586            StringBuffer JavaDoc pattern = null;
2587            String JavaDoc facet;
2588            while (content != null) {
2589                if (content.getNodeType() == Node.ELEMENT_NODE) {
2590                        // General Attribute Checking
2591
contentAttrs = generalCheck(content, scope);
2592                        numFacets++;
2593                        facet =content.getLocalName();
2594                        if (facet.equals(SchemaSymbols.ELT_ENUMERATION)) {
2595                            numEnumerationLiterals++;
2596                            String JavaDoc enumVal = content.getAttribute(SchemaSymbols.ATT_VALUE);
2597                            String JavaDoc localName;
2598                            if (baseValidator instanceof NOTATIONDatatypeValidator) {
2599                                String JavaDoc prefix = "";
2600                                String JavaDoc localpart = enumVal;
2601                                int colonptr = enumVal.indexOf(":");
2602                                if ( colonptr > 0) {
2603                                        prefix = enumVal.substring(0,colonptr);
2604                                        localpart = enumVal.substring(colonptr+1);
2605                                }
2606                                String JavaDoc uriStr = (prefix.length() != 0)?resolvePrefixToURI(prefix):fTargetNSURIString;
2607                                nameProperty=uriStr + ":" + localpart;
2608                                localName = (String JavaDoc)fNotationRegistry.get(nameProperty);
2609                                if(localName == null){
2610                                       localName = traverseNotationFromAnotherSchema( localpart, uriStr);
2611                                       if (localName == null) {
2612                                            reportGenericSchemaError("Notation '" + localpart +
2613                                                                    "' not found in the grammar "+ uriStr);
2614
2615                                       }
2616                                }
2617                                enumVal=nameProperty;
2618                            }
2619                            enumData.addElement(enumVal);
2620                            checkContent(simpleTypeDecl, XUtil.getFirstChildElement( content ), true);
2621                        }
2622                        else if (facet.equals(SchemaSymbols.ELT_ANNOTATION) || facet.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
2623                                  reportSchemaError(SchemaMessageProvider.ListUnionRestrictionError,
2624                                  new Object JavaDoc [] { simpleTypeDecl.getAttribute( SchemaSymbols.ATT_NAME )});
2625                        }
2626                        else if (facet.equals(SchemaSymbols.ELT_PATTERN)) {
2627                            if (pattern == null) {
2628                                pattern = new StringBuffer JavaDoc (content.getAttribute( SchemaSymbols.ATT_VALUE ));
2629                            }
2630                            else {
2631                                // ---------------------------------------------
2632
//datatypes: 5.2.4 pattern: src-multiple-pattern
2633
// ---------------------------------------------
2634
pattern.append("|");
2635                                pattern.append(content.getAttribute( SchemaSymbols.ATT_VALUE ));
2636                                checkContent(simpleTypeDecl, XUtil.getFirstChildElement( content ), true);
2637                            }
2638                        }
2639                        else {
2640                            if ( fFacetData.containsKey(facet) )
2641                                reportSchemaError(SchemaMessageProvider.DatatypeError,
2642                                                  new Object JavaDoc [] {"The facet '" + facet + "' is defined more than once."} );
2643                             fFacetData.put(facet,content.getAttribute( SchemaSymbols.ATT_VALUE ));
2644
2645                             if (content.getAttribute( SchemaSymbols.ATT_FIXED).equals(SchemaSymbols.ATTVAL_TRUE) ||
2646                                 content.getAttribute( SchemaSymbols.ATT_FIXED).equals(SchemaSymbols.ATTVAL_TRUE_1)){
2647                                 // --------------------------------------------
2648
// set fixed facet flags
2649
// length - must remain const through derivation
2650
// thus we don't care if it fixed
2651
// --------------------------------------------
2652
if ( facet.equals(SchemaSymbols.ELT_MINLENGTH) ) {
2653                                      flags |= DatatypeValidator.FACET_MINLENGTH;
2654                                  }
2655                                  else if (facet.equals(SchemaSymbols.ELT_MAXLENGTH)) {
2656                                      flags |= DatatypeValidator.FACET_MAXLENGTH;
2657                                  }
2658                                  else if (facet.equals(SchemaSymbols.ELT_MAXEXCLUSIVE)) {
2659                                      flags |= DatatypeValidator.FACET_MAXEXCLUSIVE;
2660                                  }
2661                                  else if (facet.equals(SchemaSymbols.ELT_MAXINCLUSIVE)) {
2662                                      flags |= DatatypeValidator.FACET_MAXINCLUSIVE;
2663                                  }
2664                                  else if (facet.equals(SchemaSymbols.ELT_MINEXCLUSIVE)) {
2665                                      flags |= DatatypeValidator.FACET_MINEXCLUSIVE;
2666                                  }
2667                                  else if (facet.equals(SchemaSymbols.ELT_MININCLUSIVE)) {
2668                                      flags |= DatatypeValidator.FACET_MININCLUSIVE;
2669                                  }
2670                                  else if (facet.equals(SchemaSymbols.ELT_TOTALDIGITS)) {
2671                                      flags |= DatatypeValidator.FACET_TOTALDIGITS;
2672                                  }
2673                                  else if (facet.equals(SchemaSymbols.ELT_FRACTIONDIGITS)) {
2674                                      flags |= DatatypeValidator.FACET_FRACTIONDIGITS;
2675                                  }
2676                                  else if (facet.equals(SchemaSymbols.ELT_WHITESPACE) &&
2677                                           baseValidator instanceof StringDatatypeValidator) {
2678                                      flags |= DatatypeValidator.FACET_WHITESPACE;
2679                                  }
2680                              }
2681                             checkContent(simpleTypeDecl, XUtil.getFirstChildElement( content ), true);
2682                        }
2683                }
2684                    content = XUtil.getNextSiblingElement(content);
2685            }
2686            if (numEnumerationLiterals > 0) {
2687                  fFacetData.put(SchemaSymbols.ELT_ENUMERATION, enumData);
2688            }
2689            if (pattern !=null) {
2690                fFacetData.put(SchemaSymbols.ELT_PATTERN, pattern.toString());
2691            }
2692            if (flags != 0) {
2693                fFacetData.put(DatatypeValidator.FACET_FIXED, new Short JavaDoc(flags));
2694            }
2695        }
2696
2697
2698        else if (list && content!=null) {
2699            // report error - must not have any children!
2700
if (baseTypeQNameProperty.length() != 0) {
2701                content = checkContent(simpleTypeDecl, content, true);
2702                if (content!=null) {
2703                    reportSchemaError(SchemaMessageProvider.ListUnionRestrictionError,
2704                                      new Object JavaDoc [] { simpleTypeDecl.getAttribute( SchemaSymbols.ATT_NAME )});
2705            }
2706            }
2707            else {
2708                reportSchemaError(SchemaMessageProvider.ListUnionRestrictionError,
2709                        new Object JavaDoc [] { simpleTypeDecl.getAttribute( SchemaSymbols.ATT_NAME )});
2710                //REVISIT: should we return?
2711
}
2712        }
2713        else if (union && content!=null) {
2714            //report error - must not have any children!
2715
if (baseTypeQNameProperty.length() != 0) {
2716                content = checkContent(simpleTypeDecl, content, true);
2717                if (content!=null) {
2718                    reportSchemaError(SchemaMessageProvider.ListUnionRestrictionError,
2719                                            new Object JavaDoc [] { simpleTypeDecl.getAttribute( SchemaSymbols.ATT_NAME )});
2720                }
2721            }
2722            else {
2723                reportSchemaError(SchemaMessageProvider.ListUnionRestrictionError,
2724                        new Object JavaDoc [] { simpleTypeDecl.getAttribute( SchemaSymbols.ATT_NAME )});
2725                //REVISIT: should we return?
2726
}
2727        }
2728
2729        // ----------------------------------------------------------------------
2730
// create & register validator for "generated" type if it doesn't exist
2731
// ----------------------------------------------------------------------
2732
try {
2733           DatatypeValidator newValidator =
2734                 fDatatypeRegistry.getDatatypeValidator( qualifiedName );
2735
2736           if( newValidator == null ) { // not previously registered
2737
if (list) {
2738                    fDatatypeRegistry.createDatatypeValidator( qualifiedName, baseValidator,
2739                                                               fFacetData,true);
2740               }
2741               else if (restriction) {
2742                   fDatatypeRegistry.createDatatypeValidator( qualifiedName, baseValidator,
2743                                                               fFacetData,false);
2744               }
2745               else { //union
2746
fDatatypeRegistry.createDatatypeValidator( qualifiedName, dTValidators);
2747               }
2748
2749           }
2750
2751           } catch (Exception JavaDoc e) {
2752               reportSchemaError(SchemaMessageProvider.DatatypeError,new Object JavaDoc [] { e.getMessage() });
2753           }
2754        return resetSimpleTypeNameStack(fStringPool.addSymbol(qualifiedName));
2755     }
2756
2757
2758    /*
2759    * <any
2760    * id = ID
2761    * maxOccurs = string
2762    * minOccurs = nonNegativeInteger
2763    * namespace = (##any | ##other) | List of (anyURI | (##targetNamespace | ##local))
2764    * processContents = lax | skip | strict>
2765    * Content: (annotation?)
2766    * </any>
2767    */

2768    private int traverseAny(Element JavaDoc child) throws Exception JavaDoc {
2769        // General Attribute Checking
2770
int scope = GeneralAttrCheck.ELE_CONTEXT_LOCAL;
2771        Hashtable JavaDoc attrValues = generalCheck(child, scope);
2772
2773        Element JavaDoc annotation = checkContent( child, XUtil.getFirstChildElement(child), true );
2774        if(annotation != null ) {
2775            // REVISIT: Localize
2776
reportGenericSchemaError("<any> elements can contain at most one <annotation> element in their children");
2777        }
2778        int anyIndex = -1;
2779        String JavaDoc namespace = child.getAttribute(SchemaSymbols.ATT_NAMESPACE).trim();
2780        String JavaDoc processContents = child.getAttribute("processContents").trim();
2781
2782        int processContentsAny = XMLContentSpec.CONTENTSPECNODE_ANY;
2783        int processContentsAnyOther = XMLContentSpec.CONTENTSPECNODE_ANY_OTHER;
2784        int processContentsAnyLocal = XMLContentSpec.CONTENTSPECNODE_ANY_NS;
2785
2786        if (processContents.length() > 0 && !processContents.equals("strict")) {
2787            if (processContents.equals("lax")) {
2788                processContentsAny = XMLContentSpec.CONTENTSPECNODE_ANY_LAX;
2789                processContentsAnyOther = XMLContentSpec.CONTENTSPECNODE_ANY_OTHER_LAX;
2790                processContentsAnyLocal = XMLContentSpec.CONTENTSPECNODE_ANY_NS_LAX;
2791            }
2792            else if (processContents.equals("skip")) {
2793                processContentsAny = XMLContentSpec.CONTENTSPECNODE_ANY_SKIP;
2794                processContentsAnyOther = XMLContentSpec.CONTENTSPECNODE_ANY_OTHER_SKIP;
2795                processContentsAnyLocal = XMLContentSpec.CONTENTSPECNODE_ANY_NS_SKIP;
2796            }
2797        }
2798
2799        if (namespace.length() == 0 || namespace.equals("##any")) {
2800            anyIndex = fSchemaGrammar.addContentSpecNode(processContentsAny, -1, StringPool.EMPTY_STRING, false);
2801        }
2802        else if (namespace.equals("##other")) {
2803            String JavaDoc uri = fTargetNSURIString;
2804            int uriIndex = fStringPool.addSymbol(uri);
2805            anyIndex = fSchemaGrammar.addContentSpecNode(processContentsAnyOther, -1, uriIndex, false);
2806        }
2807        else if (namespace.length() > 0) {
2808            int uriIndex, leafIndex, choiceIndex;
2809
2810            StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(namespace);
2811                String JavaDoc token = tokenizer.nextToken();
2812            if (token.equals(SchemaSymbols.ATTVAL_TWOPOUNDLOCAL)) {
2813                uriIndex = StringPool.EMPTY_STRING;
2814            } else {
2815                if (token.equals("##targetNamespace"))
2816                    token = fTargetNSURIString;
2817                uriIndex = fStringPool.addSymbol(token);
2818            }
2819            choiceIndex = fSchemaGrammar.addContentSpecNode(processContentsAnyLocal, -1, uriIndex, false);
2820
2821            // store a list of seen uri, so that if there are duplicate
2822
// namespaces, we only add one of them to the content model
2823
int[] uriList = new int[8];
2824            uriList[0] = uriIndex;
2825            int uriCount = 1;
2826
2827            while (tokenizer.hasMoreElements()) {
2828                token = tokenizer.nextToken();
2829                if (token.equals(SchemaSymbols.ATTVAL_TWOPOUNDLOCAL)) {
2830                    uriIndex = StringPool.EMPTY_STRING;
2831                } else {
2832                    if (token.equals("##targetNamespace"))
2833                        token = fTargetNSURIString;
2834                    uriIndex = fStringPool.addSymbol(token);
2835                }
2836                // check whether we have seen this namespace, if so, skip
2837
for (int i = 0; i < uriCount; i++) {
2838                    if (uriList[i] == uriIndex)
2839                        continue;
2840                }
2841                // add this namespace to the list
2842
if (uriList.length == uriCount) {
2843                    int[] newList = new int[uriCount*2];
2844                    System.arraycopy(uriList,0,newList,0,uriCount);
2845                    uriList = newList;
2846                }
2847                uriList[uriCount++] = uriIndex;
2848
2849                leafIndex = fSchemaGrammar.addContentSpecNode(processContentsAnyLocal, -1, uriIndex, false);
2850                choiceIndex = fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_CHOICE, choiceIndex, leafIndex, false);
2851            }
2852            anyIndex = choiceIndex;
2853        }
2854        else {
2855            // REVISIT: Localize
2856
reportGenericSchemaError("Empty namespace attribute for any element");
2857        }
2858
2859        return anyIndex;
2860    }
2861
2862    public DatatypeValidator getDatatypeValidator(String JavaDoc uri, String JavaDoc localpart) {
2863
2864        DatatypeValidator dv = null;
2865
2866        if (uri.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)) {
2867            dv = fDatatypeRegistry.getDatatypeValidator( localpart );
2868        }
2869        else {
2870            dv = fDatatypeRegistry.getDatatypeValidator( uri+","+localpart );
2871        }
2872
2873        return dv;
2874    }
2875
2876    /*
2877    * <anyAttribute
2878    * id = ID
2879    * namespace = ##any | ##other | ##local | list of {uri, ##targetNamespace}>
2880    * Content: (annotation?)
2881    * </anyAttribute>
2882    */

2883    private XMLAttributeDecl traverseAnyAttribute(Element JavaDoc anyAttributeDecl) throws Exception JavaDoc {
2884        // General Attribute Checking
2885
int scope = GeneralAttrCheck.ELE_CONTEXT_LOCAL;
2886        Hashtable JavaDoc attrValues = generalCheck(anyAttributeDecl, scope);
2887
2888        Element JavaDoc annotation = checkContent( anyAttributeDecl, XUtil.getFirstChildElement(anyAttributeDecl), true );
2889        if(annotation != null ) {
2890            // REVISIT: Localize
2891
reportGenericSchemaError("<anyAttribute> elements can contain at most one <annotation> element in their children");
2892        }
2893        XMLAttributeDecl anyAttDecl = new XMLAttributeDecl();
2894        String JavaDoc processContents = anyAttributeDecl.getAttribute(SchemaSymbols.ATT_PROCESSCONTENTS).trim();
2895        String JavaDoc namespace = anyAttributeDecl.getAttribute(SchemaSymbols.ATT_NAMESPACE).trim();
2896        // simplify! NG
2897
//String curTargetUri = anyAttributeDecl.getOwnerDocument().getDocumentElement().getAttribute("targetNamespace");
2898
String JavaDoc curTargetUri = fTargetNSURIString;
2899
2900        if ( namespace.length() == 0 || namespace.equals(SchemaSymbols.ATTVAL_TWOPOUNDANY) ) {
2901            anyAttDecl.type = XMLAttributeDecl.TYPE_ANY_ANY;
2902        }
2903        else if (namespace.equals(SchemaSymbols.ATTVAL_TWOPOUNDOTHER)) {
2904            anyAttDecl.type = XMLAttributeDecl.TYPE_ANY_OTHER;
2905            anyAttDecl.name.uri = fStringPool.addSymbol(curTargetUri);
2906        }
2907        else if (namespace.length() > 0){
2908            anyAttDecl.type = XMLAttributeDecl.TYPE_ANY_LIST;
2909
2910            StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(namespace);
2911            int aStringList = fStringPool.startStringList();
2912            Vector JavaDoc tokens = new Vector JavaDoc();
2913            int tokenStr;
2914            while (tokenizer.hasMoreElements()) {
2915                String JavaDoc token = tokenizer.nextToken();
2916                if (token.equals(SchemaSymbols.ATTVAL_TWOPOUNDLOCAL)) {
2917                    tokenStr = StringPool.EMPTY_STRING;
2918                } else {
2919                    if (token.equals(SchemaSymbols.ATTVAL_TWOPOUNDTARGETNS))
2920                    token = curTargetUri;
2921                    tokenStr = fStringPool.addSymbol(token);
2922                }
2923                if (!fStringPool.addStringToList(aStringList, tokenStr)){
2924                    reportGenericSchemaError("Internal StringPool error when reading the "+
2925                                             "namespace attribute for anyattribute declaration");
2926                }
2927            }
2928            fStringPool.finishStringList(aStringList);
2929
2930            anyAttDecl.enumeration = aStringList;
2931        }
2932        else {
2933            // REVISIT: Localize
2934
reportGenericSchemaError("Empty namespace attribute for anyattribute declaration");
2935        }
2936
2937        // default processContents is "strict";
2938
if (processContents.equals(SchemaSymbols.ATTVAL_SKIP)){
2939            anyAttDecl.defaultType |= XMLAttributeDecl.PROCESSCONTENTS_SKIP;
2940        }
2941        else if (processContents.equals(SchemaSymbols.ATTVAL_LAX)) {
2942            anyAttDecl.defaultType |= XMLAttributeDecl.PROCESSCONTENTS_LAX;
2943        }
2944        else {
2945            anyAttDecl.defaultType |= XMLAttributeDecl.PROCESSCONTENTS_STRICT;
2946        }
2947
2948        return anyAttDecl;
2949    }
2950
2951    // Schema Component Constraint: Attribute Wildcard Intersection
2952
// For a wildcard's {namespace constraint} value to be the intensional intersection of two other such values (call them O1 and O2): the appropriate case among the following must be true:
2953
// 1 If O1 and O2 are the same value, then that value must be the value.
2954
// 2 If either O1 or O2 is any, then the other must be the value.
2955
// 3 If either O1 or O2 is a pair of not and a namespace name and the other is a set of (namespace names or ·absent·), then that set, minus the negated namespace name if it was in the set, must be the value.
2956
// 4 If both O1 and O2 are sets of (namespace names or ·absent·), then the intersection of those sets must be the value.
2957
// 5 If the two are negations of different namespace names, then the intersection is not expressible.
2958
// In the case where there are more than two values, the intensional intersection is determined by identifying the intensional intersection of two of the values as above, then the intensional intersection of that value with the third (providing the first intersection was expressible), and so on as required.
2959
private XMLAttributeDecl AWildCardIntersection(XMLAttributeDecl oneAny, XMLAttributeDecl anotherAny) {
2960        // if either one is not expressible, the result is still not expressible
2961
if (oneAny.type == -1) {
2962            return oneAny;
2963        }
2964        if (anotherAny.type == -1) {
2965            return anotherAny;
2966        }
2967
2968        // 1 If O1 and O2 are the same value, then that value must be the value.
2969
// this one is dealt with in different branches
2970

2971        // 2 If either O1 or O2 is any, then the other must be the value.
2972
if (oneAny.type == XMLAttributeDecl.TYPE_ANY_ANY) {
2973            return anotherAny;
2974        }
2975        if (anotherAny.type == XMLAttributeDecl.TYPE_ANY_ANY) {
2976            return oneAny;
2977        }
2978
2979        // 3 If either O1 or O2 is a pair of not and a namespace name and the other is a set of (namespace names or ·absent·), then that set, minus the negated namespace name if it was in the set, must be the value.
2980
if (oneAny.type == XMLAttributeDecl.TYPE_ANY_OTHER &&
2981            anotherAny.type == XMLAttributeDecl.TYPE_ANY_LIST ||
2982            oneAny.type == XMLAttributeDecl.TYPE_ANY_LIST &&
2983            anotherAny.type == XMLAttributeDecl.TYPE_ANY_OTHER) {
2984            XMLAttributeDecl anyList, anyOther;
2985            if (oneAny.type == XMLAttributeDecl.TYPE_ANY_LIST) {
2986                anyList = oneAny;
2987                anyOther = anotherAny;
2988            } else {
2989                anyList = anotherAny;
2990                anyOther = oneAny;
2991                }
2992
2993            int[] uriList = fStringPool.stringListAsIntArray(anyList.enumeration);
2994            if (elementInSet(anyOther.name.uri, uriList)) {
2995                    int newList = fStringPool.startStringList();
2996                for (int i=0; i< uriList.length; i++) {
2997                    if (uriList[i] != anyOther.name.uri ) {
2998                        fStringPool.addStringToList(newList, uriList[i]);
2999                        }
3000                    }
3001                    fStringPool.finishStringList(newList);
3002                anyList.enumeration = newList;
3003                }
3004
3005            return anyList;
3006        }
3007
3008        // 4 If both O1 and O2 are sets of (namespace names or ·absent·), then the intersection of those sets must be the value.
3009
if (oneAny.type == XMLAttributeDecl.TYPE_ANY_LIST &&
3010            anotherAny.type == XMLAttributeDecl.TYPE_ANY_LIST) {
3011            int[] result = intersect2sets(fStringPool.stringListAsIntArray(oneAny.enumeration),
3012                                          fStringPool.stringListAsIntArray(anotherAny.enumeration));
3013            int newList = fStringPool.startStringList();
3014            for (int i=0; i<result.length; i++) {
3015                fStringPool.addStringToList(newList, result[i]);
3016            }
3017            fStringPool.finishStringList(newList);
3018            oneAny.enumeration = newList;
3019                return oneAny;
3020            }
3021
3022        // 5 If the two are negations of different namespace names, then the intersection is not expressible.
3023
if (oneAny.type == XMLAttributeDecl.TYPE_ANY_OTHER &&
3024            anotherAny.type == XMLAttributeDecl.TYPE_ANY_OTHER) {
3025            if (oneAny.name.uri == anotherAny.name.uri) {
3026                return oneAny;
3027            } else {
3028                oneAny.type = -1;
3029                return oneAny;
3030            }
3031        }
3032
3033        // should never go there;
3034
return oneAny;
3035                }
3036
3037    // Schema Component Constraint: Attribute Wildcard Union
3038
// For a wildcard's {namespace constraint} value to be the intensional union of two other such values (call them O1 and O2): the appropriate case among the following must be true:
3039
// 1 If O1 and O2 are the same value, then that value must be the value.
3040
// 2 If either O1 or O2 is any, then any must be the value.
3041
// 3 If both O1 and O2 are sets of (namespace names or ·absent·), then the union of those sets must be the value.
3042
// 4 If the two are negations of different namespace names, then any must be the value.
3043
// 5 If either O1 or O2 is a pair of not and a namespace name and the other is a set of (namespace names or ·absent·), then The appropriate case among the following must be true:
3044
// 5.1 If the set includes the negated namespace name, then any must be the value.
3045
// 5.2 If the set does not include the negated namespace name, then whichever of O1 or O2 is a pair of not and a namespace name must be the value.
3046
// In the case where there are more than two values, the intensional union is determined by identifying the intensional union of two of the values as above, then the intensional union of that value with the third, and so on as required.
3047
private XMLAttributeDecl AWildCardUnion(XMLAttributeDecl oneAny, XMLAttributeDecl anotherAny) {
3048        // if either one is not expressible, the result is still not expressible
3049
if (oneAny.type == -1) {
3050                    return oneAny;
3051                }
3052        if (anotherAny.type == -1) {
3053            return anotherAny;
3054            }
3055
3056        // 1 If O1 and O2 are the same value, then that value must be the value.
3057
// this one is dealt with in different branches
3058

3059        // 2 If either O1 or O2 is any, then any must be the value.
3060
if (oneAny.type == XMLAttributeDecl.TYPE_ANY_ANY) {
3061                return oneAny;
3062            }
3063        if (anotherAny.type == XMLAttributeDecl.TYPE_ANY_ANY) {
3064            return anotherAny;
3065        }
3066
3067        // 3 If both O1 and O2 are sets of (namespace names or ·absent·), then the union of those sets must be the value.
3068
if (oneAny.type == XMLAttributeDecl.TYPE_ANY_LIST &&
3069            anotherAny.type == XMLAttributeDecl.TYPE_ANY_LIST) {
3070            int[] result = union2sets(fStringPool.stringListAsIntArray(oneAny.enumeration),
3071                                               fStringPool.stringListAsIntArray(anotherAny.enumeration));
3072                int newList = fStringPool.startStringList();
3073                for (int i=0; i<result.length; i++) {
3074                    fStringPool.addStringToList(newList, result[i]);
3075                }
3076                fStringPool.finishStringList(newList);
3077                oneAny.enumeration = newList;
3078                return oneAny;
3079            }
3080
3081        // 4 If the two are negations of different namespace names, then any must be the value.
3082
if (oneAny.type == XMLAttributeDecl.TYPE_ANY_OTHER &&
3083            anotherAny.type == XMLAttributeDecl.TYPE_ANY_OTHER) {
3084            if (oneAny.name.uri == anotherAny.name.uri) {
3085                return oneAny;
3086            } else {
3087                oneAny.type = XMLAttributeDecl.TYPE_ANY_ANY;
3088                return oneAny;
3089            }
3090        }
3091
3092        // 5 If either O1 or O2 is a pair of not and a namespace name and the other is a set of (namespace names or ·absent·), then The appropriate case among the following must be true:
3093
if (oneAny.type == XMLAttributeDecl.TYPE_ANY_OTHER &&
3094            anotherAny.type == XMLAttributeDecl.TYPE_ANY_LIST ||
3095            oneAny.type == XMLAttributeDecl.TYPE_ANY_LIST &&
3096            anotherAny.type == XMLAttributeDecl.TYPE_ANY_OTHER) {
3097            XMLAttributeDecl anyList, anyOther;
3098            if (oneAny.type == XMLAttributeDecl.TYPE_ANY_LIST) {
3099                anyList = oneAny;
3100                anyOther = anotherAny;
3101            } else {
3102                anyList = anotherAny;
3103                anyOther = oneAny;
3104        }
3105            // 5.1 If the set includes the negated namespace name, then any must be the value.
3106
if (elementInSet(anyOther.name.uri,
3107                             fStringPool.stringListAsIntArray(anyList.enumeration))) {
3108                anyOther.type = XMLAttributeDecl.TYPE_ANY_ANY;
3109            }
3110            // 5.2 If the set does not include the negated namespace name, then whichever of O1 or O2 is a pair of not and a namespace name must be the value.
3111

3112            return anyOther;
3113        }
3114
3115        // should never go there;
3116
return oneAny;
3117    }
3118
3119    // Schema Component Constraint: Wildcard Subset
3120
// For a namespace constraint (call it sub) to be an intensional subset of another namespace constraint (call it super) one of the following must be true:
3121
// 1 super must be any.
3122
// 2 All of the following must be true:
3123
// 2.1 sub must be a pair of not and a namespace name or ·absent·.
3124
// 2.2 super must be a pair of not and the same value.
3125
// 3 All of the following must be true:
3126
// 3.1 sub must be a set whose members are either namespace names or ·absent·.
3127
// 3.2 One of the following must be true:
3128
// 3.2.1 super must be the same set or a superset thereof.
3129
// 3.2.2 super must be a pair of not and a namespace name or ·absent· and that value must not be in sub's set.
3130
private boolean AWildCardSubset(XMLAttributeDecl subAny, XMLAttributeDecl superAny) {
3131        // if either one is not expressible, it can't be a subset
3132
if (subAny.type == -1 || superAny.type == -1)
3133            return false;
3134
3135        // 1 super must be any.
3136
if (superAny.type == XMLAttributeDecl.TYPE_ANY_ANY)
3137            return true;
3138
3139        // 2 All of the following must be true:
3140
// 2.1 sub must be a pair of not and a namespace name or ·absent·.
3141
if (subAny.type == XMLAttributeDecl.TYPE_ANY_OTHER) {
3142            // 2.2 super must be a pair of not and the same value.
3143
if (superAny.type == XMLAttributeDecl.TYPE_ANY_OTHER &&
3144                subAny.name.uri == superAny.name.uri) {
3145                return true;
3146            }
3147        }
3148
3149        // 3 All of the following must be true:
3150
// 3.1 sub must be a set whose members are either namespace names or ·absent·.
3151
if (subAny.type == XMLAttributeDecl.TYPE_ANY_LIST) {
3152        // 3.2 One of the following must be true:
3153
// 3.2.1 super must be the same set or a superset thereof.
3154
if (superAny.type == XMLAttributeDecl.TYPE_ANY_LIST &&
3155                subset2sets(fStringPool.stringListAsIntArray(subAny.enumeration),
3156                            fStringPool.stringListAsIntArray(superAny.enumeration))) {
3157                return true;
3158            }
3159
3160            // 3.2.2 super must be a pair of not and a namespace name or ·absent· and that value must not be in sub's set.
3161
if (superAny.type == XMLAttributeDecl.TYPE_ANY_OTHER &&
3162                !elementInSet(superAny.name.uri, fStringPool.stringListAsIntArray(superAny.enumeration))) {
3163                return true;
3164            }
3165        }
3166
3167        return false;
3168    }
3169
3170    // Validation Rule: Wildcard allows Namespace Name
3171
// For a value which is either a namespace name or ·absent· to be ·valid· with respect to a wildcard constraint (the value of a {namespace constraint}) one of the following must be true:
3172
// 1 The constraint must be any.
3173
// 2 All of the following must be true:
3174
// 2.1 The constraint is a pair of not and a namespace name or ·absent· ([Definition:] call this the namespace test).
3175
// 2.2 The value must not be identical to the ·namespace test·.
3176
// 2.3 The value must not be ·absent·.
3177
// 3 The constraint is a set, and the value is identical to one of the members of the set.
3178
private boolean AWildCardAllowsNameSpace(XMLAttributeDecl wildcard, String JavaDoc uri) {
3179        // if the constrain is not expressible, then nothing is allowed
3180
if (wildcard.type == -1)
3181            return false;
3182
3183        // 1 The constraint must be any.
3184
if (wildcard.type == XMLAttributeDecl.TYPE_ANY_ANY)
3185            return true;
3186
3187        int uriStr = fStringPool.addString(uri);
3188
3189        // 2 All of the following must be true:
3190
// 2.1 The constraint is a pair of not and a namespace name or ·absent· ([Definition:] call this the namespace test).
3191
if (wildcard.type == XMLAttributeDecl.TYPE_ANY_OTHER) {
3192            // 2.2 The value must not be identical to the ·namespace test·.
3193
// 2.3 The value must not be ·absent·.
3194
if (uriStr != wildcard.name.uri && uriStr != StringPool.EMPTY_STRING)
3195                return true;
3196        }
3197
3198        // 3 The constraint is a set, and the value is identical to one of the members of the set.
3199
if (wildcard.type == XMLAttributeDecl.TYPE_ANY_LIST) {
3200            if (elementInSet(uriStr, fStringPool.stringListAsIntArray(wildcard.enumeration)))
3201                return true;
3202        }
3203
3204        return false;
3205    }
3206
3207    private boolean isAWildCard(XMLAttributeDecl a) {
3208        if (a.type == XMLAttributeDecl.TYPE_ANY_ANY
3209            ||a.type == XMLAttributeDecl.TYPE_ANY_LIST
3210            ||a.type == XMLAttributeDecl.TYPE_ANY_OTHER )
3211            return true;
3212        else
3213            return false;
3214    }
3215
3216    int[] intersect2sets(int[] one, int[] theOther){
3217        int[] result = new int[(one.length>theOther.length?one.length:theOther.length)];
3218
3219        // simple implemention,
3220
int count = 0;
3221        for (int i=0; i<one.length; i++) {
3222            if (elementInSet(one[i], theOther))
3223                    result[count++] = one[i];
3224                }
3225
3226        int[] result2 = new int[count];
3227        System.arraycopy(result, 0, result2, 0, count);
3228
3229        return result2;
3230    }
3231
3232    int[] union2sets(int[] one, int[] theOther){
3233        int[] result1 = new int[one.length];
3234
3235        // simple implemention,
3236
int count = 0;
3237        for (int i=0; i<one.length; i++) {
3238            if (!elementInSet(one[i], theOther))
3239                result1[count++] = one[i];
3240        }
3241
3242        int[] result2 = new int[count+theOther.length];
3243        System.arraycopy(result1, 0, result2, 0, count);
3244        System.arraycopy(theOther, 0, result2, count, theOther.length);
3245
3246        return result2;
3247    }
3248
3249    boolean subset2sets(int[] subSet, int[] superSet){
3250        for (int i=0; i<subSet.length; i++) {
3251            if (!elementInSet(subSet[i], superSet))
3252                return false;
3253        }
3254
3255        return true;
3256    }
3257
3258    boolean elementInSet(int ele, int[] set){
3259        boolean found = false;
3260        for (int i=0; i<set.length && !found; i++) {
3261            if (ele==set[i])
3262                found = true;
3263        }
3264
3265        return found;
3266    }
3267
3268    // wrapper traverseComplexTypeDecl method
3269
private int traverseComplexTypeDecl( Element JavaDoc complexTypeDecl ) throws Exception JavaDoc {
3270        return traverseComplexTypeDecl (complexTypeDecl, false);
3271    }
3272
3273    /**
3274     * Traverse ComplexType Declaration - Rec Implementation.
3275     *
3276     * <complexType
3277     * abstract = boolean
3278     * block = #all or (possibly empty) subset of {extension, restriction}
3279     * final = #all or (possibly empty) subset of {extension, restriction}
3280     * id = ID
3281     * mixed = boolean : false
3282     * name = NCName>
3283     * Content: (annotation? , (simpleContent | complexContent |
3284     * ( (group | all | choice | sequence)? ,
3285     * ( (attribute | attributeGroup)* , anyAttribute?))))
3286     * </complexType>
3287     * @param complexTypeDecl
3288     * @param forwardRef
3289     * @return
3290     */

3291
3292    private int traverseComplexTypeDecl( Element JavaDoc complexTypeDecl, boolean forwardRef)
3293            throws Exception JavaDoc {
3294
3295        // General Attribute Checking
3296
int scope = isTopLevel(complexTypeDecl)?
3297                    GeneralAttrCheck.ELE_CONTEXT_GLOBAL:
3298                    GeneralAttrCheck.ELE_CONTEXT_LOCAL;
3299        Hashtable JavaDoc attrValues = generalCheck(complexTypeDecl, scope);
3300
3301        // ------------------------------------------------------------------
3302
// Get the attributes of the type
3303
// ------------------------------------------------------------------
3304
String JavaDoc isAbstract = complexTypeDecl.getAttribute( SchemaSymbols.ATT_ABSTRACT );
3305        String JavaDoc blockSet = null;
3306        Attr JavaDoc blockAttr = complexTypeDecl.getAttributeNode( SchemaSymbols.ATT_BLOCK );
3307        if (blockAttr != null)
3308            blockSet = blockAttr.getValue();
3309        String JavaDoc finalSet = null;
3310        Attr JavaDoc finalAttr = complexTypeDecl.getAttributeNode( SchemaSymbols.ATT_FINAL );
3311        if (finalAttr != null)
3312            finalSet = finalAttr.getValue();
3313        String JavaDoc typeId = complexTypeDecl.getAttribute( SchemaSymbols.ATTVAL_ID );
3314        String JavaDoc typeName = complexTypeDecl.getAttribute(SchemaSymbols.ATT_NAME);
3315        String JavaDoc mixed = complexTypeDecl.getAttribute(SchemaSymbols.ATT_MIXED);
3316        boolean isMixed = mixed.equals(SchemaSymbols.ATTVAL_TRUE) || mixed.equals(SchemaSymbols.ATTVAL_TRUE_1);
3317        boolean isNamedType = false;
3318        Stack JavaDoc savedGroupNameStack = null;
3319
3320        // ------------------------------------------------------------------
3321
// Generate a type name, if one wasn't specified
3322
// ------------------------------------------------------------------
3323
if (typeName.length() == 0) { // gensym a unique name
3324
typeName = genAnonTypeName(complexTypeDecl);
3325        }
3326
3327        if ( DEBUGGING )
3328            System.out.println("traversing complex Type : " + typeName);
3329
3330        int typeNameIndex = fStringPool.addSymbol(typeName);
3331
3332
3333        // ------------------------------------------------------------------
3334
// Check if the type has already been registered
3335
// ------------------------------------------------------------------
3336
if (isTopLevel(complexTypeDecl)) {
3337
3338            String JavaDoc fullName = fTargetNSURIString+","+typeName;
3339            ComplexTypeInfo temp = (ComplexTypeInfo) fComplexTypeRegistry.get(fullName);
3340            if (temp != null ) {
3341                // check for duplicate declarations
3342
if (!forwardRef) {
3343                   if (temp.declSeen())
3344                      reportGenericSchemaError("sch-props-correct: Duplicate declaration for complexType " +
3345                                                typeName);
3346                   else
3347                      temp.setDeclSeen();
3348
3349                }
3350                return fStringPool.addSymbol(fullName);
3351            }
3352            else {
3353              // check if the type is the name of a simple type
3354
if (getDatatypeValidator(fTargetNSURIString,typeName)!=null)
3355                reportGenericSchemaError("sch-props-correct: Duplicate type declaration - type is " +
3356                                                typeName);
3357
3358            }
3359        }
3360
3361        fCurrentTypeNameStack.push(typeName);
3362
3363        int scopeDefined = fScopeCount++;
3364        int previousScope = fCurrentScope;
3365        fCurrentScope = scopeDefined;
3366
3367        // Squirrel away the groupNameStack.
3368
// If we are in the middle of processing a group, and we hit the group again
3369
// because of a complexType for an element, it's not an error.
3370
if (!fCurrentGroupNameStack.isEmpty()) {
3371          savedGroupNameStack = fCurrentGroupNameStack;
3372          fCurrentGroupNameStack = new Stack JavaDoc();
3373        }
3374
3375        Element JavaDoc child = null;
3376        ComplexTypeInfo typeInfo = new ComplexTypeInfo();
3377        typeInfo.scopeDefined = scopeDefined;
3378
3379        try {
3380
3381          // ------------------------------------------------------------------
3382
// First, handle any ANNOTATION declaration and get next child
3383
// ------------------------------------------------------------------
3384
child = checkContent(complexTypeDecl,XUtil.getFirstChildElement(complexTypeDecl),
3385                               true);
3386
3387          // ------------------------------------------------------------------
3388
// Process the content of the complex type declaration
3389
// ------------------------------------------------------------------
3390
if (child==null) {
3391              //
3392
// EMPTY complexType with complexContent
3393
//
3394
processComplexContent(typeNameIndex, child, typeInfo, null, isMixed);
3395          }
3396          else {
3397              String JavaDoc childName = child.getLocalName();
3398              int index = -2;
3399
3400              if (childName.equals(SchemaSymbols.ELT_SIMPLECONTENT)) {
3401                  //
3402
// SIMPLE CONTENT element
3403
//
3404
traverseSimpleContentDecl(typeNameIndex, child, typeInfo);
3405                  if (XUtil.getNextSiblingElement(child) != null)
3406                     throw new ComplexTypeRecoverableError(
3407                      "Invalid child following the simpleContent child in the complexType");
3408              }
3409              else if (childName.equals(SchemaSymbols.ELT_COMPLEXCONTENT)) {
3410                  //
3411
// COMPLEX CONTENT element
3412
//
3413
traverseComplexContentDecl(typeNameIndex, child, typeInfo, isMixed);
3414                  if (XUtil.getNextSiblingElement(child) != null)
3415                     throw new ComplexTypeRecoverableError(
3416                      "Invalid child following the complexContent child in the complexType");
3417              }
3418              else {
3419                  //
3420
// We must have ....
3421
// GROUP, ALL, SEQUENCE or CHOICE, followed by optional attributes
3422
// Note that it's possible that only attributes are specified.
3423
//
3424
processComplexContent(typeNameIndex, child, typeInfo, null, isMixed);
3425
3426              }
3427          }
3428          typeInfo.blockSet = parseBlockSet(blockSet);
3429          // make sure block's value was absent, #all or in {extension, restriction}
3430
if( (blockSet != null ) && blockSet.length() != 0 &&
3431                (!blockSet.equals(SchemaSymbols.ATTVAL_POUNDALL) &&
3432                (((typeInfo.blockSet & SchemaSymbols.RESTRICTION) == 0) &&
3433                ((typeInfo.blockSet & SchemaSymbols.EXTENSION) == 0))))
3434            throw new ComplexTypeRecoverableError("The values of the 'block' attribute of a complexType must be either #all or a list of 'restriction' and 'extension'; " + blockSet + " was found");
3435
3436          typeInfo.finalSet = parseFinalSet(finalSet);
3437          // make sure final's value was absent, #all or in {extension, restriction}
3438
if( (finalSet != null ) && finalSet.length() != 0 &&
3439                (!finalSet.equals(SchemaSymbols.ATTVAL_POUNDALL) &&
3440                (((typeInfo.finalSet & SchemaSymbols.RESTRICTION) == 0) &&
3441                ((typeInfo.finalSet & SchemaSymbols.EXTENSION) == 0))))
3442            throw new ComplexTypeRecoverableError("The values of the 'final' attribute of a complexType must be either #all or a list of 'restriction' and 'extension'; " + finalSet + " was found");
3443
3444        }
3445        catch (ComplexTypeRecoverableError e) {
3446           String JavaDoc message = e.getMessage();
3447           handleComplexTypeError(message,typeNameIndex,typeInfo);
3448        }
3449
3450
3451        // ------------------------------------------------------------------
3452
// Finish the setup of the typeInfo and register the type
3453
// ------------------------------------------------------------------
3454
if (isAbstract.equals(SchemaSymbols.ATTVAL_TRUE) ||
3455            isAbstract.equals(SchemaSymbols.ATTVAL_TRUE_1))
3456          typeInfo.setIsAbstractType();
3457        if (!forwardRef)
3458          typeInfo.setDeclSeen();
3459        typeName = fTargetNSURIString + "," + typeName;
3460        typeInfo.typeName = new String JavaDoc(typeName);
3461
3462        if ( DEBUGGING )
3463            System.out.println(">>>add complex Type to Registry: " + typeName +
3464                               " baseDTValidator=" + typeInfo.baseDataTypeValidator +
3465                               " baseCTInfo=" + typeInfo.baseComplexTypeInfo +
3466                               " derivedBy=" + typeInfo.derivedBy +
3467                             " contentType=" + typeInfo.contentType +
3468                               " contentSpecHandle=" + typeInfo.contentSpecHandle +
3469                               " datatypeValidator=" + typeInfo.datatypeValidator +
3470                               " scopeDefined=" + typeInfo.scopeDefined);
3471
3472        fComplexTypeRegistry.put(typeName,typeInfo);
3473
3474        // ------------------------------------------------------------------
3475
// Before exiting, restore the scope, mainly for nested anonymous types
3476
// ------------------------------------------------------------------
3477
fCurrentScope = previousScope;
3478        if (savedGroupNameStack != null)
3479          fCurrentGroupNameStack = savedGroupNameStack;
3480        fCurrentTypeNameStack.pop();
3481        checkRecursingComplexType();
3482
3483        //set template element's typeInfo
3484
fSchemaGrammar.setElementComplexTypeInfo(typeInfo.templateElementIndex, typeInfo);
3485
3486        typeNameIndex = fStringPool.addSymbol(typeName);
3487        return typeNameIndex;
3488
3489    } // end traverseComplexTypeDecl
3490

3491
3492    /**
3493     * Traverse SimpleContent Declaration
3494     *
3495     * <simpleContent
3496     * id = ID
3497     * {any attributes with non-schema namespace...}>
3498     *
3499     * Content: (annotation? , (restriction | extension))
3500     * </simpleContent>
3501     *
3502     * <restriction
3503     * base = QNAME
3504     * id = ID
3505     * {any attributes with non-schema namespace...}>
3506     *
3507     * Content: (annotation?,(simpleType?, (minExclusive|minInclusive|maxExclusive
3508     * | maxInclusive | totalDigits | fractionDigits | length | minLength
3509     * | maxLength | encoding | period | duration | enumeration
3510     * | pattern | whiteSpace)*) ? ,
3511     * ((attribute | attributeGroup)* , anyAttribute?))
3512     * </restriction>
3513     *
3514     * <extension
3515     * base = QNAME
3516     * id = ID
3517     * {any attributes with non-schema namespace...}>
3518     * Content: (annotation? , ((attribute | attributeGroup)* , anyAttribute?))
3519     * </extension>
3520     *
3521     * @param typeNameIndex
3522     * @param simpleContentTypeDecl
3523     * @param typeInfo
3524     * @return
3525     */

3526
3527    private void traverseSimpleContentDecl(int typeNameIndex,
3528               Element JavaDoc simpleContentDecl, ComplexTypeInfo typeInfo)
3529               throws Exception JavaDoc {
3530
3531
3532        // General Attribute Checking
3533
int scope = GeneralAttrCheck.ELE_CONTEXT_LOCAL;
3534        Hashtable JavaDoc attrValues = generalCheck(simpleContentDecl, scope);
3535
3536        String JavaDoc typeName = fStringPool.toString(typeNameIndex);
3537
3538        // -----------------------------------------------------------------------
3539
// Get attributes.
3540
// -----------------------------------------------------------------------
3541
String JavaDoc simpleContentTypeId = simpleContentDecl.getAttribute(SchemaSymbols.ATTVAL_ID);
3542
3543        // -----------------------------------------------------------------------
3544
// Set the content type to be simple, and initialize content spec handle
3545
// -----------------------------------------------------------------------
3546
typeInfo.contentType = XMLElementDecl.TYPE_SIMPLE;
3547        typeInfo.contentSpecHandle = -1;
3548
3549        Element JavaDoc simpleContent = checkContent(simpleContentDecl,
3550                                     XUtil.getFirstChildElement(simpleContentDecl),false);
3551
3552        // If there are no children, return
3553
if (simpleContent==null) {
3554          throw new ComplexTypeRecoverableError();
3555        }
3556
3557        // General Attribute Checking
3558
attrValues = generalCheck(simpleContent, scope);
3559
3560        // -----------------------------------------------------------------------
3561
// The content should be either "restriction" or "extension"
3562
// -----------------------------------------------------------------------
3563
String JavaDoc simpleContentName = simpleContent.getLocalName();
3564        if (simpleContentName.equals(SchemaSymbols.ELT_RESTRICTION))
3565          typeInfo.derivedBy = SchemaSymbols.RESTRICTION;
3566        else if (simpleContentName.equals(SchemaSymbols.ELT_EXTENSION))
3567          typeInfo.derivedBy = SchemaSymbols.EXTENSION;
3568        else {
3569
3570          throw new ComplexTypeRecoverableError(
3571                     "The content of the simpleContent element is invalid. The " +
3572                     "content must be RESTRICTION or EXTENSION");
3573        }
3574
3575        // -----------------------------------------------------------------------
3576
// Get the attributes of the restriction/extension element
3577
// -----------------------------------------------------------------------
3578
String JavaDoc base = simpleContent.getAttribute(SchemaSymbols.ATT_BASE);
3579        String JavaDoc typeId = simpleContent.getAttribute(SchemaSymbols.ATTVAL_ID);
3580
3581
3582        // -----------------------------------------------------------------------
3583
// Skip over any annotations in the restriction or extension elements
3584
// -----------------------------------------------------------------------
3585
Element JavaDoc content = checkContent(simpleContent,
3586                              XUtil.getFirstChildElement(simpleContent),true);
3587
3588        // -----------------------------------------------------------------------
3589
// Handle the base type name
3590
// -----------------------------------------------------------------------
3591
if (base.length() == 0) {
3592          throw new ComplexTypeRecoverableError(
3593                  "The BASE attribute must be specified for the " +
3594                  "RESTRICTION or EXTENSION element");
3595        }
3596
3597        QName baseQName = parseBase(base);
3598        // check if we're extending a simpleType which has a "final" setting which precludes this
3599
Integer JavaDoc finalValue =
3600                ((Integer JavaDoc)fSimpleTypeFinalRegistry.get(fStringPool.toString(baseQName.uri) + "," +fStringPool.toString(baseQName.localpart)));
3601        if(finalValue != null &&
3602                (finalValue.intValue() == typeInfo.derivedBy))
3603            throw new ComplexTypeRecoverableError(
3604                  "The simpleType " + base + " that " + typeName + " uses has a value of \"final\" which does not permit extension");
3605
3606        String JavaDoc baseTypeURI = fStringPool.toString(baseQName.uri);
3607        String JavaDoc baseLocalName = fStringPool.toString(baseQName.localpart);
3608        if (baseTypeURI.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA) &&
3609            baseLocalName.equals("anyType")) {
3610             throw new ComplexTypeRecoverableError(
3611             "The type '"+ base +"' specified as the " +
3612             "base in the simpleContent element must be a complex type with simple content");
3613        }
3614
3615        processBaseTypeInfo(baseQName,typeInfo);
3616
3617        // check that the base isn't a complex type with simple content
3618
if (typeInfo.baseComplexTypeInfo != null) {
3619             if (typeInfo.baseComplexTypeInfo.contentType != XMLElementDecl.TYPE_SIMPLE) {
3620                 throw new ComplexTypeRecoverableError(
3621                 "The type '"+ base +"' specified as the " +
3622                 "base in the simpleContent element must not have complexContent");
3623             }
3624        }
3625
3626        // -----------------------------------------------------------------------
3627
// Process the content of the derivation
3628
// -----------------------------------------------------------------------
3629
Element JavaDoc attrNode = null;
3630        //
3631
// RESTRICTION
3632
//
3633
if (typeInfo.derivedBy==SchemaSymbols.RESTRICTION) {
3634            //
3635
//Schema Spec : Complex Type Definition Properties Correct : 2
3636
//
3637
if (typeInfo.baseDataTypeValidator != null) {
3638                throw new ComplexTypeRecoverableError(
3639                 "ct-props-correct.2: The type '" + base +"' is a simple type. It cannot be used in a "+
3640                 "derivation by RESTRICTION for a complexType");
3641            }
3642            else {
3643                typeInfo.baseDataTypeValidator = typeInfo.baseComplexTypeInfo.datatypeValidator;
3644            }
3645
3646            //
3647
// Check that the base's final set does not include RESTRICTION
3648
//
3649
if((typeInfo.baseComplexTypeInfo.finalSet & SchemaSymbols.RESTRICTION) != 0) {
3650               throw new ComplexTypeRecoverableError("Derivation by restriction is forbidden by either the base type " + base + " or the schema");
3651            }
3652
3653
3654            // -----------------------------------------------------------------------
3655
// There may be a simple type definition in the restriction element
3656
// The data type validator will be based on it, if specified
3657
// -----------------------------------------------------------------------
3658
if (content != null &&
3659                content.getLocalName().equals(SchemaSymbols.ELT_SIMPLETYPE )) {
3660                int simpleTypeNameIndex = traverseSimpleTypeDecl(content);
3661                if (simpleTypeNameIndex!=-1) {
3662                    DatatypeValidator dv=fDatatypeRegistry.getDatatypeValidator(
3663                       fStringPool.toString(simpleTypeNameIndex));
3664
3665                  //check that this datatype validator is validly derived from the base
3666
//according to derivation-ok-restriction 5.1.1
3667
if (!checkSimpleTypeDerivationOK(dv,typeInfo.baseDataTypeValidator)) {
3668                    throw new ComplexTypeRecoverableError("derivation-ok-restriction.5.1.1: The content type is not a valid restriction of the content type of the base");
3669                  }
3670                  typeInfo.baseDataTypeValidator = dv;
3671                  content = XUtil.getNextSiblingElement(content);
3672                }
3673                else {
3674                  throw new ComplexTypeRecoverableError();
3675                }
3676            }
3677
3678
3679            //
3680
// Build up facet information
3681
//
3682
int numEnumerationLiterals = 0;
3683            int numFacets = 0;
3684            Hashtable JavaDoc facetData = new Hashtable JavaDoc();
3685            Vector JavaDoc enumData = new Vector JavaDoc();
3686            Element JavaDoc child;
3687
3688             // General Attribute Checking
3689
scope = GeneralAttrCheck.ELE_CONTEXT_LOCAL;
3690            Hashtable JavaDoc contentAttrs;
3691
3692            //REVISIT: there is a better way to do this,
3693
for (child = content;
3694                 child != null && (child.getLocalName().equals(SchemaSymbols.ELT_MINEXCLUSIVE) ||
3695                           child.getLocalName().equals(SchemaSymbols.ELT_MININCLUSIVE) ||
3696                           child.getLocalName().equals(SchemaSymbols.ELT_MAXEXCLUSIVE) ||
3697                           child.getLocalName().equals(SchemaSymbols.ELT_MAXINCLUSIVE) ||
3698                           child.getLocalName().equals(SchemaSymbols.ELT_TOTALDIGITS) ||
3699                           child.getLocalName().equals(SchemaSymbols.ELT_FRACTIONDIGITS) ||
3700                           child.getLocalName().equals(SchemaSymbols.ELT_LENGTH) ||
3701                           child.getLocalName().equals(SchemaSymbols.ELT_MINLENGTH) ||
3702                           child.getLocalName().equals(SchemaSymbols.ELT_MAXLENGTH) ||
3703                           child.getLocalName().equals(SchemaSymbols.ELT_ENUMERATION) ||
3704                           child.getLocalName().equals(SchemaSymbols.ELT_PATTERN) ||
3705                           child.getLocalName().equals(SchemaSymbols.ELT_WHITESPACE) ||
3706                           child.getLocalName().equals(SchemaSymbols.ELT_ANNOTATION));
3707                 child = XUtil.getNextSiblingElement(child))
3708            {
3709                if ( child.getNodeType() == Node.ELEMENT_NODE ) {
3710                    Element JavaDoc facetElt = (Element JavaDoc) child;
3711                    // General Attribute Checking
3712
contentAttrs = generalCheck(facetElt, scope);
3713                    numFacets++;
3714                    if (facetElt.getLocalName().equals(SchemaSymbols.ELT_ENUMERATION)) {
3715                        numEnumerationLiterals++;
3716                        enumData.addElement(facetElt.getAttribute(SchemaSymbols.ATT_VALUE));
3717                        //Enumerations can have annotations ? ( 0 | 1 )
3718
Element JavaDoc enumContent = XUtil.getFirstChildElement( facetElt );
3719                        if( enumContent != null &&
3720                            enumContent.getLocalName().equals
3721                                  ( SchemaSymbols.ELT_ANNOTATION )){
3722                            traverseAnnotationDecl( child );
3723                        }
3724                        // TO DO: if Jeff check in new changes to TraverseSimpleType, copy them over
3725
}
3726                    else {
3727                        facetData.put(facetElt.getLocalName(),
3728                              facetElt.getAttribute( SchemaSymbols.ATT_VALUE ));
3729                    }
3730                }
3731            } // end of for loop thru facets
3732

3733            if (numEnumerationLiterals > 0) {
3734                facetData.put(SchemaSymbols.ELT_ENUMERATION, enumData);
3735            }
3736
3737            //
3738
// If there were facets, create a new data type validator, otherwise
3739
// the data type validator is from the base
3740
//
3741
if (numFacets > 0) {
3742              try{
3743                typeInfo.datatypeValidator = fDatatypeRegistry.createDatatypeValidator(
3744                                      typeName,
3745                                      typeInfo.baseDataTypeValidator, facetData, false);
3746              } catch (Exception JavaDoc e) {
3747                throw new ComplexTypeRecoverableError(e.getMessage());
3748              }
3749
3750            }
3751            else
3752                typeInfo.datatypeValidator =
3753                             typeInfo.baseDataTypeValidator;
3754
3755            if (child != null) {
3756               //
3757
// Check that we have attributes
3758
//
3759
if (!isAttrOrAttrGroup(child)) {
3760                  throw new ComplexTypeRecoverableError(
3761                     "Invalid child in the RESTRICTION element of simpleContent");
3762               }
3763               else
3764                  attrNode = child;
3765            }
3766
3767        } // end RESTRICTION
3768

3769        //
3770
// EXTENSION
3771
//
3772
else {
3773            if (typeInfo.baseComplexTypeInfo != null) {
3774               typeInfo.baseDataTypeValidator = typeInfo.baseComplexTypeInfo.datatypeValidator;
3775              //
3776
// Check that the base's final set does not include EXTENSION
3777
//
3778
if((typeInfo.baseComplexTypeInfo.finalSet &
3779                   SchemaSymbols.EXTENSION) != 0) {
3780                 throw new ComplexTypeRecoverableError("Derivation by extension is forbidden by either the base type " + base + " or the schema");
3781              }
3782            }
3783
3784            typeInfo.datatypeValidator = typeInfo.baseDataTypeValidator;
3785
3786            //
3787
// Look for attributes
3788
//
3789
if (content != null) {
3790               //
3791
// Check that we have attributes
3792
//
3793
if (!isAttrOrAttrGroup(content)) {
3794                   throw new ComplexTypeRecoverableError(
3795                             "Only annotations and attributes are allowed in the " +
3796                             "content of an EXTENSION element for a complexType with simpleContent");
3797               }
3798               else {
3799                   attrNode = content;
3800               }
3801            }
3802
3803        }
3804
3805        // -----------------------------------------------------------------------
3806
// add a template element to the grammar element decl pool for the type
3807
// -----------------------------------------------------------------------
3808
int templateElementNameIndex = fStringPool.addSymbol("$"+typeName);
3809
3810        typeInfo.templateElementIndex = fSchemaGrammar.addElementDecl(
3811             new QName(-1, templateElementNameIndex,typeNameIndex,fTargetNSURI),
3812             (fTargetNSURI==StringPool.EMPTY_STRING) ? StringPool.EMPTY_STRING : fCurrentScope, typeInfo.scopeDefined,
3813             typeInfo.contentType,
3814             typeInfo.contentSpecHandle, -1, typeInfo.datatypeValidator);
3815        typeInfo.attlistHead = fSchemaGrammar.getFirstAttributeDeclIndex(
3816                                typeInfo.templateElementIndex);
3817
3818        // -----------------------------------------------------------------------
3819
// Process attributes
3820
// -----------------------------------------------------------------------
3821
processAttributes(attrNode,baseQName,typeInfo);
3822
3823        if (XUtil.getNextSiblingElement(simpleContent) != null)
3824            throw new ComplexTypeRecoverableError(
3825               "Invalid child following the RESTRICTION or EXTENSION element in the " +
3826               "complex type definition");
3827
3828    } // end traverseSimpleContentDecl
3829

3830    /**
3831     * Traverse complexContent Declaration
3832     *
3833     * <complexContent
3834     * id = ID
3835     * mixed = boolean
3836     * {any attributes with non-schema namespace...}>
3837     *
3838     * Content: (annotation? , (restriction | extension))
3839     * </complexContent>
3840     *
3841     * <restriction
3842     * base = QNAME
3843     * id = ID
3844     * {any attributes with non-schema namespace...}>
3845     *
3846     * Content: (annotation? , (group | all | choice | sequence)?,
3847     * ((attribute | attributeGroup)* , anyAttribute?))
3848     * </restriction>
3849     *
3850     * <extension
3851     * base = QNAME
3852     * id = ID
3853     * {any attributes with non-schema namespace...}>
3854     * Content: (annotation? , (group | all | choice | sequence)?,
3855     * ((attribute | attributeGroup)* , anyAttribute?))
3856     * </extension>
3857     *
3858     * @param typeNameIndex
3859     * @param simpleContentTypeDecl
3860     * @param typeInfo
3861     * @param mixedOnComplexTypeDecl
3862     * @return
3863     */

3864
3865    private void traverseComplexContentDecl(int typeNameIndex,
3866               Element JavaDoc complexContentDecl, ComplexTypeInfo typeInfo,
3867               boolean mixedOnComplexTypeDecl) throws Exception JavaDoc {
3868
3869         // General Attribute Checking
3870
int scope = GeneralAttrCheck.ELE_CONTEXT_LOCAL;
3871        Hashtable JavaDoc attrValues = generalCheck(complexContentDecl, scope);
3872
3873        String JavaDoc typeName = fStringPool.toString(typeNameIndex);
3874
3875        // -----------------------------------------------------------------------
3876
// Get the attributes
3877
// -----------------------------------------------------------------------
3878
String JavaDoc typeId = complexContentDecl.getAttribute(SchemaSymbols.ATTVAL_ID);
3879        String JavaDoc mixed = complexContentDecl.getAttribute(SchemaSymbols.ATT_MIXED);
3880
3881        // -----------------------------------------------------------------------
3882
// Determine whether the content is mixed, or element-only
3883
// Setting here overrides any setting on the complex type decl
3884
// -----------------------------------------------------------------------
3885
boolean isMixed = mixedOnComplexTypeDecl;
3886        if (mixed.equals(SchemaSymbols.ATTVAL_TRUE) ||
3887            mixed.equals(SchemaSymbols.ATTVAL_TRUE_1))
3888           isMixed = true;
3889        else if (mixed.equals(SchemaSymbols.ATTVAL_FALSE) ||
3890                 mixed.equals(SchemaSymbols.ATTVAL_FALSE_0))
3891           isMixed = false;
3892
3893        // -----------------------------------------------------------------------
3894
// Since the type must have complex content, set the simple type validators
3895
// to null
3896
// -----------------------------------------------------------------------
3897
typeInfo.datatypeValidator = null;
3898        typeInfo.baseDataTypeValidator = null;
3899
3900        Element JavaDoc complexContent = checkContent(complexContentDecl,
3901                                 XUtil.getFirstChildElement(complexContentDecl),false);
3902
3903        // If there are no children, return
3904
if (complexContent==null) {
3905           throw new ComplexTypeRecoverableError();
3906        }
3907
3908        // -----------------------------------------------------------------------
3909
// The content should be either "restriction" or "extension"
3910
// -----------------------------------------------------------------------
3911
String JavaDoc complexContentName = complexContent.getLocalName();
3912        if (complexContentName.equals(SchemaSymbols.ELT_RESTRICTION))
3913          typeInfo.derivedBy = SchemaSymbols.RESTRICTION;
3914        else if (complexContentName.equals(SchemaSymbols.ELT_EXTENSION))
3915          typeInfo.derivedBy = SchemaSymbols.EXTENSION;
3916        else {
3917           throw new ComplexTypeRecoverableError(
3918                     "The content of the complexContent element is invalid. " +
3919                     "The content must be RESTRICTION or EXTENSION");
3920        }
3921
3922        // Get the attributes of the restriction/extension element
3923
String JavaDoc base = complexContent.getAttribute(SchemaSymbols.ATT_BASE);
3924        String JavaDoc complexContentTypeId=complexContent.getAttribute(SchemaSymbols.ATTVAL_ID);
3925
3926
3927        // Skip over any annotations in the restriction or extension elements
3928
Element JavaDoc content = checkContent(complexContent,
3929                              XUtil.getFirstChildElement(complexContent),true);
3930
3931        // -----------------------------------------------------------------------
3932
// Handle the base type name
3933
// -----------------------------------------------------------------------
3934
if (base.length() == 0) {
3935           throw new ComplexTypeRecoverableError(
3936                  "The BASE attribute must be specified for the " +
3937                  "RESTRICTION or EXTENSION element");
3938        }
3939
3940        QName baseQName = parseBase(base);
3941
3942        // -------------------------------------------------------------
3943
// check if the base is "anyType"
3944
// -------------------------------------------------------------
3945
String JavaDoc baseTypeURI = fStringPool.toString(baseQName.uri);
3946        String JavaDoc baseLocalName = fStringPool.toString(baseQName.localpart);
3947        if (!(baseTypeURI.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA) &&
3948            baseLocalName.equals("anyType"))) {
3949
3950            processBaseTypeInfo(baseQName,typeInfo);
3951
3952            //Check that the base is a complex type
3953
if (typeInfo.baseComplexTypeInfo == null) {
3954                 throw new ComplexTypeRecoverableError(
3955                   "The base type specified in the complexContent element must be a complexType");
3956            }
3957        }
3958
3959        // -----------------------------------------------------------------------
3960
// Process the elements that make up the content
3961
// -----------------------------------------------------------------------
3962
processComplexContent(typeNameIndex,content,typeInfo,baseQName,isMixed);
3963
3964        if (XUtil.getNextSiblingElement(complexContent) != null)
3965            throw new ComplexTypeRecoverableError(
3966               "Invalid child following the RESTRICTION or EXTENSION element in the " +
3967               "complex type definition");
3968
3969    } // end traverseComplexContentDecl
3970

3971
3972    /**
3973     * Handle complexType error
3974     *
3975     * @param message
3976     * @param typeNameIndex
3977     * @param typeInfo
3978     * @return
3979     */

3980    private void handleComplexTypeError(String JavaDoc message, int typeNameIndex,
3981                                        ComplexTypeInfo typeInfo) throws Exception JavaDoc {
3982
3983        String JavaDoc typeName = fStringPool.toString(typeNameIndex);
3984        if (message != null) {
3985          if (typeName.startsWith("#"))
3986            reportGenericSchemaError("Anonymous complexType: " + message);
3987          else
3988            reportGenericSchemaError("ComplexType '" + typeName + "': " + message);
3989        }
3990
3991        //
3992
// Mock up the typeInfo structure so that there won't be problems during
3993
// validation
3994
//
3995
typeInfo.contentType = XMLElementDecl.TYPE_ANY; // this should match anything
3996
typeInfo.contentSpecHandle = -1;
3997        typeInfo.derivedBy = 0;
3998        typeInfo.datatypeValidator = null;
3999        typeInfo.attlistHead = -1;
4000
4001        int templateElementNameIndex = fStringPool.addSymbol("$"+typeName);
4002        typeInfo.templateElementIndex = fSchemaGrammar.addElementDecl(
4003            new QName(-1, templateElementNameIndex,typeNameIndex,fTargetNSURI),
4004            (fTargetNSURI==StringPool.EMPTY_STRING) ? StringPool.EMPTY_STRING : fCurrentScope, typeInfo.scopeDefined,
4005            typeInfo.contentType,
4006            typeInfo.contentSpecHandle, -1, typeInfo.datatypeValidator);
4007        return;
4008    }
4009
4010    /**
4011     * Generate a name for an anonymous type
4012     *
4013     * @param Element
4014     * @return String
4015     */

4016    private String JavaDoc genAnonTypeName(Element JavaDoc complexTypeDecl) throws Exception JavaDoc {
4017
4018        // Generate a unique name for the anonymous type by concatenating together the
4019
// names of parent nodes
4020
String JavaDoc typeName;
4021        Element JavaDoc node=complexTypeDecl;
4022        typeName="#AnonType_";
4023        while (!isTopLevel(node)) {
4024          node = (Element JavaDoc)node.getParentNode();
4025          typeName = typeName+node.getAttribute(SchemaSymbols.ATT_NAME);
4026        }
4027
4028        return typeName;
4029    }
4030    /**
4031     * Parse base string
4032     *
4033     * @param base
4034     * @return QName
4035     */

4036    private QName parseBase(String JavaDoc base) throws Exception JavaDoc {
4037
4038        String JavaDoc prefix = "";
4039        String JavaDoc localpart = base;
4040        int colonptr = base.indexOf(":");
4041        if ( colonptr > 0) {
4042            prefix = base.substring(0,colonptr);
4043            localpart = base.substring(colonptr+1);
4044        }
4045
4046        int nameIndex = fStringPool.addSymbol(base);
4047        int prefixIndex = fStringPool.addSymbol(prefix);
4048        int localpartIndex = fStringPool.addSymbol(localpart);
4049        int URIindex = fStringPool.addSymbol(resolvePrefixToURI(prefix));
4050        return new QName(prefixIndex,localpartIndex,nameIndex,URIindex);
4051    }
4052
4053    /**
4054     * Check if base is from another schema
4055     *
4056     * @param baseName
4057     * @return boolean
4058     */

4059    private boolean baseFromAnotherSchema(QName baseName) throws Exception JavaDoc {
4060
4061        String JavaDoc typeURI = fStringPool.toString(baseName.uri);
4062        if ( ! typeURI.equals(fTargetNSURIString)
4063             && ! typeURI.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)
4064             && typeURI.length() != 0 )
4065             //REVISIT, !!!! a hack: for schema that has no
4066
//target namespace, e.g. personal-schema.xml
4067
return true;
4068        else
4069          return false;
4070
4071    }
4072
4073    /**
4074     * Process "base" information for a complexType
4075     *
4076     * @param baseTypeInfo
4077     * @param baseName
4078     * @param typeInfo
4079     * @return
4080     */

4081
4082    private void processBaseTypeInfo(QName baseName, ComplexTypeInfo typeInfo) throws Exception JavaDoc {
4083
4084        ComplexTypeInfo baseComplexTypeInfo = null;
4085        DatatypeValidator baseDTValidator = null;
4086
4087        String JavaDoc typeURI = fStringPool.toString(baseName.uri);
4088        String JavaDoc localpart = fStringPool.toString(baseName.localpart);
4089        String JavaDoc base = fStringPool.toString(baseName.rawname);
4090
4091
4092        // -------------------------------------------------------------
4093
// check if the base type is from another schema
4094
// -------------------------------------------------------------
4095
if (baseFromAnotherSchema(baseName)) {
4096            baseComplexTypeInfo = getTypeInfoFromNS(typeURI, localpart);
4097            if (baseComplexTypeInfo == null) {
4098                baseDTValidator = getTypeValidatorFromNS(typeURI, localpart);
4099            }
4100        }
4101
4102        // -------------------------------------------------------------
4103
// type must be from same schema
4104
// -------------------------------------------------------------
4105
else {
4106            String JavaDoc fullBaseName = typeURI+","+localpart;
4107
4108            // assume the base is a complexType and try to locate the base type first
4109
baseComplexTypeInfo= (ComplexTypeInfo) fComplexTypeRegistry.get(fullBaseName);
4110
4111            // if not found, 2 possibilities:
4112
// 1: ComplexType in question has not been compiled yet;
4113
// 2: base is SimpleTYpe;
4114
if (baseComplexTypeInfo == null) {
4115                baseDTValidator = getDatatypeValidator(typeURI, localpart);
4116
4117                if (baseDTValidator == null) {
4118                    int baseTypeSymbol;
4119                    Element JavaDoc baseTypeNode = getTopLevelComponentByName(
4120                                   SchemaSymbols.ELT_COMPLEXTYPE,localpart);
4121                    if (baseTypeNode != null) {
4122                        // Before traversing the base, make sure we're not already
4123
// doing so..
4124
// ct-props-correct 3
4125
if (fBaseTypeNameStack.search((Object JavaDoc)fullBaseName) > - 1) {
4126                            throw new ComplexTypeRecoverableError(
4127                                 "ct-props-correct.3: Recursive type definition");
4128                        }
4129                        fBaseTypeNameStack.push(fullBaseName);
4130                        baseTypeSymbol = traverseComplexTypeDecl( baseTypeNode, true );
4131                    fBaseTypeNameStack.pop();
4132                        baseComplexTypeInfo = (ComplexTypeInfo)
4133                          fComplexTypeRegistry.get(fStringPool.toString(baseTypeSymbol));
4134                        //REVISIT: should it be fullBaseName;
4135
}
4136                    else {
4137                        baseTypeNode = getTopLevelComponentByName(
4138                                   SchemaSymbols.ELT_SIMPLETYPE, localpart);
4139                        if (baseTypeNode != null) {
4140                            baseTypeSymbol = traverseSimpleTypeDecl( baseTypeNode );
4141                            baseDTValidator = getDatatypeValidator(typeURI, localpart);
4142                        }
4143                    }
4144                }
4145            }
4146        } // end else (type must be from same schema)
4147

4148        //
4149
//Schema Spec: Complex Type Definition Representation OK : 2
4150
//
4151
if (baseComplexTypeInfo == null && baseDTValidator == null) {
4152            throw new ComplexTypeRecoverableError(
4153             "src-ct.2: Cannot find type definition for '" + base +"'");
4154        }
4155
4156        typeInfo.baseComplexTypeInfo = baseComplexTypeInfo;
4157        typeInfo.baseDataTypeValidator = baseDTValidator;
4158    } // end processBaseTypeInfo
4159

4160    /**
4161     * Process content which is complex
4162     *
4163     * (group | all | choice | sequence) ? ,
4164     * ((attribute | attributeGroup)* , anyAttribute?))
4165     *
4166     * @param typeNameIndex
4167     * @param complexContentChild
4168     * @param typeInfo
4169     * @return
4170     */

4171
4172    private void processComplexContent(int typeNameIndex,
4173               Element JavaDoc complexContentChild, ComplexTypeInfo typeInfo, QName baseName,
4174               boolean isMixed) throws Exception JavaDoc {
4175
4176       Element JavaDoc attrNode = null;
4177       int index=-2;
4178       String JavaDoc typeName = fStringPool.toString(typeNameIndex);
4179
4180       if (complexContentChild != null) {
4181           // -------------------------------------------------------------
4182
// GROUP, ALL, SEQUENCE or CHOICE, followed by attributes, if specified.
4183
// Note that it's possible that only attributes are specified.
4184
// -------------------------------------------------------------
4185

4186
4187          String JavaDoc childName = complexContentChild.getLocalName();
4188
4189          if (childName.equals(SchemaSymbols.ELT_GROUP)) {
4190               GroupInfo grpInfo = traverseGroupDecl(complexContentChild);
4191               int groupIndex = (grpInfo != null) ? grpInfo.contentSpecIndex:-2;
4192
4193               index = handleOccurrences(groupIndex,
4194                                complexContentChild,
4195                                hasAllContent(groupIndex) ? GROUP_REF_WITH_ALL :
4196                                                            NOT_ALL_CONTEXT);
4197               attrNode = XUtil.getNextSiblingElement(complexContentChild);
4198           }
4199           else if (childName.equals(SchemaSymbols.ELT_SEQUENCE)) {
4200               index = handleOccurrences(traverseSequence(complexContentChild),
4201                                         complexContentChild);
4202               attrNode = XUtil.getNextSiblingElement(complexContentChild);
4203           }
4204           else if (childName.equals(SchemaSymbols.ELT_CHOICE)) {
4205               index = handleOccurrences(traverseChoice(complexContentChild),
4206                                          complexContentChild);
4207               attrNode = XUtil.getNextSiblingElement(complexContentChild);
4208           }
4209           else if (childName.equals(SchemaSymbols.ELT_ALL)) {
4210               index = handleOccurrences(traverseAll(complexContentChild),
4211                                         complexContentChild,
4212                                         PROCESSING_ALL_GP);
4213               attrNode = XUtil.getNextSiblingElement(complexContentChild);
4214           }
4215           else if (isAttrOrAttrGroup(complexContentChild)) {
4216               // reset the contentType
4217
typeInfo.contentType = XMLElementDecl.TYPE_ANY;
4218               attrNode = complexContentChild;
4219           }
4220           else {
4221               throw new ComplexTypeRecoverableError(
4222                "Invalid child '"+ childName +"' in the complex type");
4223           }
4224       }
4225
4226       typeInfo.contentSpecHandle = index;
4227
4228       // -----------------------------------------------------------------------
4229
// Merge in information from base, if it exists
4230
// -----------------------------------------------------------------------
4231
if (typeInfo.baseComplexTypeInfo != null) {
4232           int baseContentSpecHandle = typeInfo.baseComplexTypeInfo.contentSpecHandle;
4233
4234           //-------------------------------------------------------------
4235
// RESTRICTION
4236
//-------------------------------------------------------------
4237
if (typeInfo.derivedBy == SchemaSymbols.RESTRICTION) {
4238              // check to see if the baseType permits derivation by restriction
4239
if((typeInfo.baseComplexTypeInfo.finalSet & SchemaSymbols.RESTRICTION) != 0)
4240                    throw new ComplexTypeRecoverableError("Derivation by restriction is forbidden by either the base type " + fStringPool.toString(baseName.localpart) + " or the schema");
4241
4242              // if the content is EMPTY, check that the base is correct
4243
// according to derivation-ok-restriction 5.2
4244
if (typeInfo.contentSpecHandle==-2) {
4245                 if (!(typeInfo.baseComplexTypeInfo.contentType==XMLElementDecl.TYPE_EMPTY ||
4246                     particleEmptiable(baseContentSpecHandle))) {
4247                    throw new ComplexTypeRecoverableError("derivation-ok-restrictoin.5.2 Content type of complexType is EMPTY but base is not EMPTY or does not have a particle which is emptiable");
4248                 }
4249              }
4250
4251              //
4252
// Delay derivation by restriction particle constraint checking until
4253
// the whole schema has been processed. We need to do this because:
4254
// - top-level element declarations are not processed until traversed
4255
// thru the main traverseSchema walk.
4256
//
4257
//
4258

4259           }
4260           //-------------------------------------------------------------
4261
// EXTENSION
4262
//-------------------------------------------------------------
4263
else {
4264               // check to see if the baseType permits derivation by extension
4265
if((typeInfo.baseComplexTypeInfo.finalSet & SchemaSymbols.EXTENSION) != 0)
4266                    throw new ComplexTypeRecoverableError("cos-ct-extends.1.1: Derivation by extension is forbidden by either the base type " + fStringPool.toString(baseName.localpart) + " or the schema");
4267
4268               //
4269
// Check if the contentType of the base is consistent with the new type
4270
// cos-ct-extends.1.4.2.2
4271
if (typeInfo.baseComplexTypeInfo.contentType != XMLElementDecl.TYPE_EMPTY) {
4272                  if (((typeInfo.baseComplexTypeInfo.contentType == XMLElementDecl.TYPE_CHILDREN) &&
4273                       isMixed) ||
4274                      ((typeInfo.baseComplexTypeInfo.contentType == XMLElementDecl.TYPE_MIXED_COMPLEX) &&
4275                      !isMixed)) {
4276                    throw new ComplexTypeRecoverableError("cos-ct-extends.1.4.2.2.2.1: The content type of the base type " +
4277                    fStringPool.toString(baseName.localpart) + " and derived type " +
4278                    typeName + " must both be mixed or element-only");
4279                  }
4280
4281               }
4282
4283               //
4284
// Compose the final content model by concatenating the base and the
4285
// current in sequence
4286
//
4287
if (baseFromAnotherSchema(baseName)) {
4288                   String JavaDoc baseSchemaURI = fStringPool.toString(baseName.uri);
4289                   SchemaGrammar aGrammar= (SchemaGrammar) fGrammarResolver.getGrammar(
4290                                    baseSchemaURI);
4291                   baseContentSpecHandle = importContentSpec(aGrammar, baseContentSpecHandle);
4292               }
4293               if (typeInfo.contentSpecHandle == -2) {
4294                   typeInfo.contentSpecHandle = baseContentSpecHandle;
4295               }
4296               else if (baseContentSpecHandle > -1) {
4297                   if (typeInfo.contentSpecHandle > -1 &&
4298                       (hasAllContent(typeInfo.contentSpecHandle) ||
4299                        hasAllContent(baseContentSpecHandle))) {
4300                       throw new ComplexTypeRecoverableError("cos-all-limited.1.2: An \"all\" model group that is part of a complex type definition must constitute the entire {content type} of the definition.");
4301                   }
4302
4303                   typeInfo.contentSpecHandle =
4304                   fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_SEQ,
4305                                                     baseContentSpecHandle,
4306                                                     typeInfo.contentSpecHandle,
4307                                                     false);
4308               }
4309
4310               //
4311
// Check that there is a particle in the final content
4312
// cos-ct-extends.1.4.2.1
4313
// LM - commented out until I get a clarification from HT
4314
//
4315
//if (typeInfo.contentSpecHandle <0) {
4316
// throw new ComplexTypeRecoverableError("cos-ct-extends.1.4.2.1: The content of a type derived by EXTENSION must contain a particle");
4317
//}
4318
}
4319       }
4320       else {
4321           typeInfo.derivedBy = SchemaSymbols.RESTRICTION;
4322       }
4323
4324       // -------------------------------------------------------------
4325
// Set the content type
4326
// -------------------------------------------------------------
4327
if (isMixed) {
4328
4329           // if there are no children, detect an error
4330
// See the definition of content type in Structures 3.4.1
4331
// This is commented out for now, until I get a clarification from schema WG
4332
// LM.
4333

4334           if (typeInfo.contentSpecHandle == -2) {
4335             //throw new ComplexTypeRecoverableError("Type '" + typeName + "': The content of a mixed complexType must not be empty");
4336

4337             // for "mixed" complex type with empty content
4338
// we add an optional leaf node to the content model
4339
// with empty namespace and -1 name (which won't match any element)
4340
// so that the result content model is emptible and only match
4341
// with cdata
4342
int emptyIndex = fSchemaGrammar.addContentSpecNode(XMLContentSpec.CONTENTSPECNODE_LEAF,
4343                                                                -1,
4344                                                                StringPool.EMPTY_STRING,
4345                                                                false);
4346             if (fSchemaGrammar.getDeferContentSpecExpansion()) {
4347                 fSchemaGrammar.setContentSpecMinOccurs(emptyIndex, 0);
4348                 fSchemaGrammar.setContentSpecMaxOccurs(emptyIndex, 1);
4349                 typeInfo.contentSpecHandle = emptyIndex;
4350             } else {
4351                 typeInfo.contentSpecHandle = fSchemaGrammar.expandContentModel(emptyIndex,0,1);
4352             }
4353
4354             typeInfo.contentType = XMLElementDecl.TYPE_MIXED_SIMPLE;
4355           }
4356
4357           else
4358             typeInfo.contentType = XMLElementDecl.TYPE_MIXED_COMPLEX;
4359       }
4360       else if (typeInfo.contentSpecHandle == -2)
4361           typeInfo.contentType = XMLElementDecl.TYPE_EMPTY;
4362       else
4363           typeInfo.contentType = XMLElementDecl.TYPE_CHILDREN;
4364
4365
4366       // -------------------------------------------------------------
4367
// add a template element to the grammar element decl pool.
4368
// -------------------------------------------------------------
4369
int templateElementNameIndex = fStringPool.addSymbol("$"+typeName);
4370
4371       typeInfo.templateElementIndex = fSchemaGrammar.addElementDecl(
4372            new QName(-1, templateElementNameIndex,typeNameIndex,fTargetNSURI),
4373            (fTargetNSURI==StringPool.EMPTY_STRING) ? StringPool.EMPTY_STRING : fCurrentScope, typeInfo.scopeDefined,
4374            typeInfo.contentType,
4375            typeInfo.contentSpecHandle, -1, typeInfo.datatypeValidator);
4376       typeInfo.attlistHead = fSchemaGrammar.getFirstAttributeDeclIndex(
4377                               typeInfo.templateElementIndex);
4378
4379       // -------------------------------------------------------------
4380
// Now, check attributes and handle
4381
// -------------------------------------------------------------
4382
if (attrNode !=null) {
4383           if (!isAttrOrAttrGroup(attrNode)) {
4384              throw new ComplexTypeRecoverableError(
4385                  "Invalid child "+ attrNode.getLocalName() + " in the complexType or complexContent");
4386           }
4387           else
4388              processAttributes(attrNode,baseName,typeInfo);
4389       }
4390       else if (typeInfo.baseComplexTypeInfo != null)
4391           processAttributes(null,baseName,typeInfo);
4392
4393
4394    } // end processComplexContent
4395

4396    /**
4397     * Process attributes of a complex type
4398     *
4399     * @param attrNode
4400     * @param typeInfo
4401     * @return
4402     */

4403
4404    private void processAttributes(Element JavaDoc attrNode, QName baseName,
4405               ComplexTypeInfo typeInfo) throws Exception JavaDoc {
4406
4407
4408        XMLAttributeDecl attWildcard = null;
4409        Vector JavaDoc anyAttDecls = new Vector JavaDoc();
4410
4411        Element JavaDoc child;
4412        for (child = attrNode;
4413             child != null;
4414             child = XUtil.getNextSiblingElement(child)) {
4415
4416            String JavaDoc childName = child.getLocalName();
4417
4418            if (childName.equals(SchemaSymbols.ELT_ATTRIBUTE)) {
4419                traverseAttributeDecl(child, typeInfo, false);
4420            }
4421            else if ( childName.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP) ) {
4422                traverseAttributeGroupDecl(child,typeInfo,anyAttDecls);
4423
4424            }
4425            else if ( childName.equals(SchemaSymbols.ELT_ANYATTRIBUTE) ) {
4426                attWildcard = traverseAnyAttribute(child);
4427            }
4428            else {
4429                throw new ComplexTypeRecoverableError( "Invalid child among the children of the complexType definition");
4430            }
4431        }
4432
4433        if (attWildcard != null) {
4434            XMLAttributeDecl fromGroup = null;
4435            final int count = anyAttDecls.size();
4436            if ( count > 0) {
4437                fromGroup = (XMLAttributeDecl) anyAttDecls.elementAt(0);
4438                for (int i=1; i<count; i++) {
4439                    fromGroup = AWildCardIntersection(
4440                                fromGroup,(XMLAttributeDecl)anyAttDecls.elementAt(i));
4441                }
4442            }
4443            if (fromGroup != null) {
4444                int saveProcessContents = attWildcard.defaultType;
4445                attWildcard = AWildCardIntersection(attWildcard, fromGroup);
4446                attWildcard.defaultType = saveProcessContents;
4447            }
4448        }
4449        else {
4450            //REVISIT: unclear in the Scheme Structures 4.3.3 what to do in this case
4451
if (anyAttDecls.size()>0) {
4452                attWildcard = (XMLAttributeDecl)anyAttDecls.elementAt(0);
4453            }
4454        }
4455        //
4456
// merge in base type's attribute decls
4457
//
4458
XMLAttributeDecl baseAttWildcard = null;
4459        ComplexTypeInfo baseTypeInfo = typeInfo.baseComplexTypeInfo;
4460
4461        SchemaGrammar aGrammar=null;
4462        if (baseTypeInfo != null && baseTypeInfo.attlistHead > -1 ) {
4463            int attDefIndex = baseTypeInfo.attlistHead;
4464            aGrammar = fSchemaGrammar;
4465            String JavaDoc baseTypeSchemaURI = baseFromAnotherSchema(baseName)?
4466                           fStringPool.toString(baseName.uri):null;
4467            if (baseTypeSchemaURI != null) {
4468                aGrammar = (SchemaGrammar) fGrammarResolver.getGrammar(baseTypeSchemaURI);
4469            }
4470            if (aGrammar == null) {
4471                //reportGenericSchemaError("In complexType "+typeName+", can NOT find the grammar "+
4472
// "with targetNamespace" + baseTypeSchemaURI+
4473
// "for the base type");
4474
}
4475            else
4476            while ( attDefIndex > -1 ) {
4477                fTempAttributeDecl.clear();
4478                aGrammar.getAttributeDecl(attDefIndex, fTempAttributeDecl);
4479                if (fTempAttributeDecl.type == XMLAttributeDecl.TYPE_ANY_ANY
4480                    ||fTempAttributeDecl.type == XMLAttributeDecl.TYPE_ANY_LIST
4481                    ||fTempAttributeDecl.type == XMLAttributeDecl.TYPE_ANY_OTHER ) {
4482                    if (attWildcard == null) {
4483                        baseAttWildcard = fTempAttributeDecl;
4484                    }
4485                    attDefIndex = aGrammar.getNextAttributeDeclIndex(attDefIndex);
4486                    continue;
4487                }
4488                // if found a duplicate, if it is derived by restriction,
4489
// then skip the one from the base type
4490

4491                int temp = fSchemaGrammar.getAttributeDeclIndex(typeInfo.templateElementIndex, fTempAttributeDecl.name);
4492                if ( temp > -1) {
4493                  if (typeInfo.derivedBy==SchemaSymbols.EXTENSION) {
4494                    throw new ComplexTypeRecoverableError("Attribute " + fStringPool.toString(fTempAttributeDecl.name.localpart) + " that appeared in the base should not appear in a derivation by extension");
4495
4496
4497                  }
4498                  else {
4499                    attDefIndex = fSchemaGrammar.getNextAttributeDeclIndex(attDefIndex);
4500                    continue;
4501                  }
4502                }
4503
4504                fSchemaGrammar.addAttDef( typeInfo.templateElementIndex,
4505                                          fTempAttributeDecl.name, fTempAttributeDecl.type,
4506                                          fTempAttributeDecl.enumeration, fTempAttributeDecl.defaultType,
4507                                          fTempAttributeDecl.defaultValue,
4508                                          fTempAttributeDecl.datatypeValidator,
4509                                          fTempAttributeDecl.list);
4510                attDefIndex = aGrammar.getNextAttributeDeclIndex(attDefIndex);
4511            }
4512        }
4513
4514        // att wildcard will inserted after all attributes were processed
4515
if (attWildcard != null) {
4516            if (attWildcard.type != -1) {
4517                fSchemaGrammar.addAttDef( typeInfo.templateElementIndex,
4518                                          attWildcard.name, attWildcard.type,
4519                                          attWildcard.enumeration, attWildcard.defaultType,
4520                                          attWildcard.defaultValue,
4521                                          attWildcard.datatypeValidator,
4522                                          attWildcard.list);
4523            }
4524            else {
4525                //REVISIT: unclear in Schema spec if should report error here.
4526
reportGenericSchemaError("The intensional intersection for {attribute wildcard}s must be expressible");
4527            }
4528        }
4529        else if (baseAttWildcard != null) {
4530            fSchemaGrammar.addAttDef( typeInfo.templateElementIndex,
4531                                      baseAttWildcard.name, baseAttWildcard.type,
4532                                      baseAttWildcard.enumeration, baseAttWildcard.defaultType,
4533                                      baseAttWildcard.defaultValue,
4534                                      baseAttWildcard.datatypeValidator,
4535                                      baseAttWildcard.list);
4536        }
4537
4538        typeInfo.attlistHead = fSchemaGrammar.getFirstAttributeDeclIndex
4539                                              (typeInfo.templateElementIndex);
4540
4541        // For derivation by restriction, ensure that the resulting attribute list
4542
// satisfies the constraints in derivation-ok-restriction 2,3,4
4543
if ((typeInfo.derivedBy==SchemaSymbols.RESTRICTION) &&
4544            (typeInfo.attlistHead>-1 && baseTypeInfo != null)) {
4545           checkAttributesDerivationOKRestriction(typeInfo.attlistHead,fSchemaGrammar,
4546               attWildcard,baseTypeInfo.attlistHead,aGrammar,baseAttWildcard);
4547        }
4548
4549    } // end processAttributes
4550

4551    // Check that the attributes of a type derived by restriction satisfy the
4552
// constraints of derivation-ok-restriction
4553

4554    private void checkAttributesDerivationOKRestriction(int dAttListHead, SchemaGrammar dGrammar, XMLAttributeDecl dAttWildCard, int bAttListHead, SchemaGrammar bGrammar, XMLAttributeDecl bAttWildCard) throws ComplexTypeRecoverableError {
4555
4556       int attDefIndex = dAttListHead;
4557
4558       if (bAttListHead < 0) {
4559          throw new ComplexTypeRecoverableError("derivation-ok-restriction.2: Base type definition does not have any attributes");
4560       }
4561
4562       // Loop thru the attributes
4563
while ( attDefIndex > -1 ) {
4564          fTempAttributeDecl.clear();
4565          dGrammar.getAttributeDecl(attDefIndex, fTempAttributeDecl);
4566          if (isAWildCard(fTempAttributeDecl)) {
4567             attDefIndex = dGrammar.getNextAttributeDeclIndex(attDefIndex);
4568             continue;
4569          }
4570          int bAttDefIndex = bGrammar.findAttributeDecl(bAttListHead, fTempAttributeDecl.name);
4571          if (bAttDefIndex > -1) {
4572             fTemp2AttributeDecl.clear();
4573             bGrammar.getAttributeDecl(bAttDefIndex, fTemp2AttributeDecl);
4574
4575             // derivation-ok-restriction. Constraint 2.1.1
4576
if ((fTemp2AttributeDecl.defaultType &
4577                   XMLAttributeDecl.DEFAULT_TYPE_REQUIRED) > 0 &&
4578                (fTempAttributeDecl.defaultType &
4579                   XMLAttributeDecl.DEFAULT_TYPE_REQUIRED) <= 0) {
4580               throw new ComplexTypeRecoverableError("derivation-ok-restriction.2.1.1: Attribute '" + fStringPool.toString(fTempAttributeDecl.name.localpart) + "' in derivation has an inconsistent REQUIRED setting to that of attribute in base");
4581             }
4582
4583             //
4584
// derivation-ok-restriction. Constraint 2.1.2
4585
//
4586
if (!(checkSimpleTypeDerivationOK(
4587                  fTempAttributeDecl.datatypeValidator,
4588                  fTemp2AttributeDecl.datatypeValidator))) {
4589               throw new ComplexTypeRecoverableError("derivation-ok-restriction.2.1.2: Type of attribute '" + fStringPool.toString(fTempAttributeDecl.name.localpart) + "' in derivation must be a restriction of type of attribute in base");
4590             }
4591
4592             //
4593
// derivation-ok-restriction. Constraint 2.1.3
4594
//
4595
if ((fTemp2AttributeDecl.defaultType &
4596                   XMLAttributeDecl.DEFAULT_TYPE_FIXED) > 0) {
4597
4598               if (!((fTempAttributeDecl.defaultType &
4599                   XMLAttributeDecl.DEFAULT_TYPE_FIXED) > 0) ||
4600                   !fTempAttributeDecl.defaultValue.equals(fTemp2AttributeDecl.defaultValue)) {
4601
4602                  throw new ComplexTypeRecoverableError("derivation-ok-restriction.2.1.3: Attribute '" + fStringPool.toString(fTempAttributeDecl.name.localpart) + "' is either not fixed, or is not fixed with the same value as the attribute in the base");
4603               }
4604             }
4605
4606          }
4607         else {
4608             //
4609
// derivation-ok-restriction. Constraint 2.2
4610
//
4611
if ((bAttWildCard==null) ||
4612              !AWildCardAllowsNameSpace(bAttWildCard, dGrammar.getTargetNamespaceURI())) {
4613                throw new ComplexTypeRecoverableError("derivation-ok-restriction.2.2: Attribute '" + fStringPool.toString(fTempAttributeDecl.name.localpart) + "' has a target namespace which is not valid with respect to a base type definition's wildcard or, the base does not contain a wildcard");
4614
4615             }
4616         }
4617         attDefIndex = dGrammar.getNextAttributeDeclIndex(attDefIndex);
4618
4619       }
4620
4621       // derivation-ok-restriction. Constraint 4
4622
if (dAttWildCard!=null) {
4623          if (bAttWildCard==null) {
4624            throw new ComplexTypeRecoverableError("derivation-ok-restriction.4.1: An attribute wildcard is present in the derived type, but not the base");
4625          }
4626
4627          if (!AWildCardSubset(dAttWildCard,bAttWildCard)) {
4628            throw new ComplexTypeRecoverableError("derivation-ok-restriction.4.2: The attribute wildcard in the derived type is not a valid subset of that in the base");
4629
4630          }
4631       }
4632    }
4633
4634    private boolean isAttrOrAttrGroup(Element JavaDoc e)
4635    {
4636        String JavaDoc elementName = e.getLocalName();
4637
4638        if (elementName.equals(SchemaSymbols.ELT_ATTRIBUTE) ||
4639            elementName.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP) ||
4640            elementName.equals(SchemaSymbols.ELT_ANYATTRIBUTE))
4641          return true;
4642        else
4643          return false;
4644    }
4645
4646    private void checkRecursingComplexType() throws Exception JavaDoc {
4647        if ( fCurrentTypeNameStack.empty() ) {
4648            if (! fElementRecurseComplex.isEmpty() ) {
4649
4650               int count= fElementRecurseComplex.size();
4651
4652               for (int i = 0; i<count; i++) {
4653
4654                 ElementInfo eobj = (ElementInfo)fElementRecurseComplex.elementAt(i);
4655                 int elementIndex = eobj.elementIndex;
4656                 String JavaDoc typeName = eobj.typeName;
4657
4658
4659                 ComplexTypeInfo typeInfo =
4660                     (ComplexTypeInfo) fComplexTypeRegistry.get(fTargetNSURIString+","+typeName);
4661                 if (typeInfo==null) {
4662                    throw new Exception JavaDoc ( "Internal Error in void checkRecursingComplexType(). " );
4663                 }
4664                 else {
4665                   // update the element decl with info from the type
4666

4667                   fSchemaGrammar.getElementDecl(elementIndex, fTempElementDecl);
4668                   fTempElementDecl.type = typeInfo.contentType;
4669                   fTempElementDecl.contentSpecIndex = typeInfo.contentSpecHandle;
4670                   fTempElementDecl.datatypeValidator = typeInfo.datatypeValidator;
4671                   fSchemaGrammar.setElementDecl(elementIndex, fTempElementDecl);
4672
4673                   fSchemaGrammar.setFirstAttributeDeclIndex(elementIndex,
4674                        typeInfo.attlistHead);
4675                   fSchemaGrammar.setElementComplexTypeInfo(elementIndex,typeInfo);
4676                   fSchemaGrammar.setElementDefinedScope(elementIndex,typeInfo.scopeDefined);
4677                 }
4678               }
4679               fElementRecurseComplex.removeAllElements();
4680            }
4681        }
4682    }
4683
4684    // Check that the particle defined by the derived ct tree is a valid restriction of
4685
// that specified by baseContentSpecIndex. derivedScope and baseScope are the
4686
// scopes of the particles, respectively. bInfo is supplied when the base particle
4687
// is from a base type definition, and may be null - it helps determine other scopes
4688
// that elements should be looked up in.
4689

4690    private void checkParticleDerivationOK(int derivedContentSpecIndex, int derivedScope, int baseContentSpecIndex, int baseScope, ComplexTypeInfo bInfo) throws Exception JavaDoc {
4691
4692
4693       // Only do this if full checking is enabled
4694
if (!fFullConstraintChecking)
4695           return;
4696
4697       // Check for pointless occurrences of all, choice, sequence. The result is the
4698
// contentspec which is not pointless. If the result is a non-pointless
4699
// group, Vector is filled in with the children of interest
4700
int csIndex1 = derivedContentSpecIndex;
4701       fSchemaGrammar.getContentSpec(csIndex1, tempContentSpec1);
4702       int csIndex2 = baseContentSpecIndex;
4703       fSchemaGrammar.getContentSpec(csIndex2, tempContentSpec2);
4704
4705       Vector JavaDoc tempVector1 = new Vector JavaDoc();
4706       Vector JavaDoc tempVector2 = new Vector JavaDoc();
4707
4708       if (tempContentSpec1.type == XMLContentSpec.CONTENTSPECNODE_SEQ ||
4709           tempContentSpec1.type == XMLContentSpec.CONTENTSPECNODE_CHOICE ||
4710           tempContentSpec1.type == XMLContentSpec.CONTENTSPECNODE_ALL) {
4711         csIndex1 = checkForPointlessOccurrences(csIndex1,tempVector1);
4712       }
4713       if (tempContentSpec2.type == XMLContentSpec.CONTENTSPECNODE_SEQ ||
4714           tempContentSpec2.type == XMLContentSpec.CONTENTSPECNODE_CHOICE ||
4715           tempContentSpec2.type == XMLContentSpec.CONTENTSPECNODE_ALL) {
4716         csIndex2 = checkForPointlessOccurrences(csIndex2,tempVector2);
4717       }
4718
4719       fSchemaGrammar.getContentSpec(csIndex1, tempContentSpec1);
4720       fSchemaGrammar.getContentSpec(csIndex2, tempContentSpec2);
4721
4722       switch (tempContentSpec1.type & 0x0f) {
4723         case XMLContentSpec.CONTENTSPECNODE_LEAF:
4724         {
4725            switch (tempContentSpec2.type & 0x0f) {
4726
4727              // Elt:Elt NameAndTypeOK
4728
case XMLContentSpec.CONTENTSPECNODE_LEAF:
4729              {
4730                 checkNameAndTypeOK(csIndex1, derivedScope, csIndex2, baseScope, bInfo);
4731                 return;
4732              }
4733
4734              // Elt:Any NSCompat
4735
case XMLContentSpec.CONTENTSPECNODE_ANY:
4736              case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER:
4737              case XMLContentSpec.CONTENTSPECNODE_ANY_NS:
4738              {
4739                 checkNSCompat(csIndex1, derivedScope, csIndex2);
4740                 return;
4741              }
4742
4743              // Elt:All RecurseAsIfGroup
4744
case XMLContentSpec.CONTENTSPECNODE_CHOICE:
4745              case XMLContentSpec.CONTENTSPECNODE_SEQ:
4746              case XMLContentSpec.CONTENTSPECNODE_ALL:
4747              {
4748                 checkRecurseAsIfGroup(csIndex1, derivedScope, csIndex2, tempVector2, baseScope, bInfo);
4749                 return;
4750              }
4751
4752              default:
4753              {
4754            throw new ParticleRecoverableError("internal Xerces error");
4755              }
4756            }
4757         }
4758
4759         case XMLContentSpec.CONTENTSPECNODE_ANY:
4760         case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER:
4761         case XMLContentSpec.CONTENTSPECNODE_ANY_NS:
4762         {
4763            switch (tempContentSpec2.type & 0x0f) {
4764
4765              // Any:Any NSSubset
4766
case XMLContentSpec.CONTENTSPECNODE_ANY:
4767              case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER:
4768              case XMLContentSpec.CONTENTSPECNODE_ANY_NS:
4769              {
4770                 checkNSSubset(csIndex1, csIndex2);
4771                 return;
4772              }
4773
4774              case XMLContentSpec.CONTENTSPECNODE_CHOICE:
4775              case XMLContentSpec.CONTENTSPECNODE_SEQ:
4776              case XMLContentSpec.CONTENTSPECNODE_ALL:
4777              case XMLContentSpec.CONTENTSPECNODE_LEAF:
4778              {
4779                 throw new ParticleRecoverableError("cos-particle-restrict: Forbidden restriction: Any: Choice,Seq,All,Elt");
4780              }
4781
4782              default:
4783              {
4784            throw new ParticleRecoverableError("internal Xerces error");
4785              }
4786            }
4787         }
4788
4789         case XMLContentSpec.CONTENTSPECNODE_ALL:
4790         {
4791            switch (tempContentSpec2.type & 0x0f) {
4792
4793              // All:Any NSRecurseCheckCardinality
4794
case XMLContentSpec.CONTENTSPECNODE_ANY:
4795              case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER:
4796              case XMLContentSpec.CONTENTSPECNODE_ANY_NS:
4797              {
4798                 checkNSRecurseCheckCardinality(csIndex1, tempVector1, derivedScope, csIndex2);
4799                 return;
4800              }
4801
4802              case XMLContentSpec.CONTENTSPECNODE_ALL:
4803              {
4804                 checkRecurse(csIndex1, tempVector1, derivedScope, csIndex2, tempVector2, baseScope, bInfo);
4805                 return;
4806              }
4807
4808              case XMLContentSpec.CONTENTSPECNODE_CHOICE:
4809              case XMLContentSpec.CONTENTSPECNODE_SEQ:
4810              case XMLContentSpec.CONTENTSPECNODE_LEAF:
4811              {
4812                 throw new ParticleRecoverableError("cos-particle-restrict: Forbidden restriction: All:Choice,Seq,Elt");
4813              }
4814
4815              default:
4816              {
4817            throw new ParticleRecoverableError("internal Xerces error");
4818              }
4819            }
4820         }
4821
4822         case XMLContentSpec.CONTENTSPECNODE_CHOICE:
4823         {
4824            switch (tempContentSpec2.type & 0x0f) {
4825
4826              // Choice:Any NSRecurseCheckCardinality
4827
case XMLContentSpec.CONTENTSPECNODE_ANY:
4828              case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER:
4829              case XMLContentSpec.CONTENTSPECNODE_ANY_NS:
4830              {
4831                 checkNSRecurseCheckCardinality(csIndex1, tempVector1, derivedScope, csIndex2);
4832                 return;
4833              }
4834
4835              case XMLContentSpec.CONTENTSPECNODE_CHOICE:
4836              {
4837                 checkRecurseLax(csIndex1, tempVector1, derivedScope, csIndex2, tempVector2, baseScope, bInfo);
4838                 return;
4839              }
4840
4841              case XMLContentSpec.CONTENTSPECNODE_ALL:
4842              case XMLContentSpec.CONTENTSPECNODE_SEQ:
4843              case XMLContentSpec.CONTENTSPECNODE_LEAF:
4844              {
4845                 throw new ParticleRecoverableError("cos-particle-restrict: Forbidden restriction: Choice:All,Seq,Leaf");
4846              }
4847
4848              default:
4849              {
4850            throw new ParticleRecoverableError("internal Xerces error");
4851              }
4852            }
4853         }
4854
4855
4856         case XMLContentSpec.CONTENTSPECNODE_SEQ:
4857         {
4858            switch (tempContentSpec2.type & 0x0f) {
4859
4860              // Choice:Any NSRecurseCheckCardinality
4861
case XMLContentSpec.CONTENTSPECNODE_ANY:
4862              case XMLContentSpec.CONTENTSPECNODE_ANY_OTHER:
4863              case XMLContentSpec.CONTENTSPECNODE_ANY_NS:
4864              {
4865                 checkNSRecurseCheckCardinality(csIndex1, tempVector1, derivedScope, csIndex2);
4866                 return;
4867              }
4868
4869              case XMLContentSpec.CONTENTSPECNODE_ALL:
4870              {
4871                 checkRecurseUnordered(csIndex1, tempVector1, derivedScope, csIndex2, tempVector2, baseScope, bInfo);
4872                 return;
4873              }
4874
4875              case XMLContentSpec.CONTENTSPECNODE_SEQ:
4876              {
4877                 checkRecurse(csIndex1, tempVector1, derivedScope, csIndex2, tempVector2, baseScope, bInfo);
4878                 return;
4879              }
4880
4881              case XMLContentSpec.CONTENTSPECNODE_CHOICE:
4882              {
4883                 checkMapAndSum(csIndex1, tempVector1, derivedScope, csIndex2, tempVector2, baseScope, bInfo);
4884                 return;
4885              }
4886
4887              case XMLContentSpec.CONTENTSPECNODE_LEAF:
4888              {
4889                throw new ParticleRecoverableError("cos-particle-restrict: Forbidden restriction: Seq:Elt");
4890              }
4891
4892              default:
4893              {
4894            throw new ParticleRecoverableError("internal Xerces error");
4895              }
4896            }
4897         }
4898
4899       }
4900
4901    }
4902
4903    private int checkForPointlessOccurrences(int csIndex, Vector JavaDoc tempVector) {
4904
4905       // Note: instead of using a Vector, we should use a growable array of int.
4906
// To be cleaned up in release 1.4.1. (LM)
4907

4908       fSchemaGrammar.getContentSpec(csIndex, tempContentSpec1);
4909
4910       if (tempContentSpec1.otherValue == -2) {
4911         gatherChildren(tempContentSpec1.type,tempContentSpec1.value,tempVector);
4912         if (tempVector.size() == 1) {
4913           Integer JavaDoc returnVal = (Integer JavaDoc)(tempVector.elementAt(0));
4914           return returnVal.intValue();
4915         }
4916         return csIndex;
4917       }
4918
4919       int type = tempContentSpec1.type;
4920       int value = tempContentSpec1.value;
4921       int otherValue = tempContentSpec1.otherValue;
4922
4923       gatherChildren(type,value, tempVector);
4924       gatherChildren(type,otherValue, tempVector);
4925
4926
4927       return csIndex;
4928    }
4929
4930
4931    private void gatherChildren(int parentType, int csIndex, Vector JavaDoc tempVector) {
4932
4933       fSchemaGrammar.getContentSpec(csIndex, tempContentSpec1);
4934       int min = fSchemaGrammar.getContentSpecMinOccurs(csIndex);
4935       int max = fSchemaGrammar.getContentSpecMaxOccurs(csIndex);
4936       int left = tempContentSpec1.value;
4937       int right = tempContentSpec1.otherValue;
4938       int type = tempContentSpec1.type;
4939
4940       if (type == XMLContentSpec.CONTENTSPECNODE_LEAF ||
4941           (type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY ||
4942           (type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_NS ||
4943           (type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER ) {
4944          tempVector.addElement(new Integer JavaDoc(csIndex));
4945       }
4946       else if (! (min==1 && max==1)) {
4947          tempVector.addElement(new Integer JavaDoc(csIndex));
4948       }
4949       else if (right == -2) {
4950          gatherChildren(type,left,tempVector);
4951       }
4952       else if (parentType == type) {
4953          gatherChildren(type,left,tempVector);
4954          gatherChildren(type,right,tempVector);
4955       }
4956       else {
4957          tempVector.addElement(new Integer JavaDoc(csIndex));
4958       }
4959
4960    }
4961
4962
4963    private void checkNameAndTypeOK(int csIndex1, int derivedScope, int csIndex2, int baseScope, ComplexTypeInfo bInfo) throws Exception JavaDoc {
4964
4965      fSchemaGrammar.getContentSpec(csIndex1, tempContentSpec1);
4966      fSchemaGrammar.getContentSpec(csIndex2, tempContentSpec2);
4967
4968
4969      int localpart1 = tempContentSpec1.value;
4970      int uri1 = tempContentSpec1.otherValue;
4971      int localpart2 = tempContentSpec2.value;
4972      int uri2 = tempContentSpec2.otherValue;
4973
4974      int min1 = fSchemaGrammar.getContentSpecMinOccurs(csIndex1);
4975      int max1 = fSchemaGrammar.getContentSpecMaxOccurs(csIndex1);
4976      int min2 = fSchemaGrammar.getContentSpecMinOccurs(csIndex2);
4977      int max2 = fSchemaGrammar.getContentSpecMaxOccurs(csIndex2);
4978
4979      //start the checking...
4980
if (!(localpart1==localpart2 && uri1==uri2)) {
4981
4982        // we have non-matching names. Check substitution groups.
4983
if (fSComp == null)
4984           fSComp = new SubstitutionGroupComparator(fGrammarResolver,fStringPool,fErrorReporter);
4985        if (!checkSubstitutionGroups(localpart1,uri1,localpart2,uri2))
4986          throw new ParticleRecoverableError("rcase-nameAndTypeOK.1: Element name/uri in restriction does not match that of corresponding base element");
4987      }
4988
4989      if (!checkOccurrenceRange(min1,max1,min2,max2)) {
4990        throw new ParticleRecoverableError("rcase-nameAndTypeOK.3: Element occurrence range not a restriction of base element's range: element is " + fStringPool.toString(localpart1));
4991      }
4992
4993      SchemaGrammar aGrammar = fSchemaGrammar;
4994
4995      // get the element decl indices for the remainder...
4996
String JavaDoc schemaURI = fStringPool.toString(uri1);
4997      if ( !schemaURI.equals(fTargetNSURIString)
4998            && schemaURI.length() != 0 )
4999         aGrammar= (SchemaGrammar) fGrammarResolver.getGrammar(schemaURI);
5000
5001      int eltndx1 = findElement(derivedScope, uri1, localpart1, aGrammar, null);
5002      if (eltndx1 < 0)
5003         return;
5004
5005      int eltndx2 = findElement(baseScope, uri2, localpart2, aGrammar, bInfo);
5006      if (eltndx2 < 0)
5007         return;
5008
5009      int miscFlags1 = ((SchemaGrammar) aGrammar).getElementDeclMiscFlags(eltndx1);
5010      int miscFlags2 = ((SchemaGrammar) aGrammar).getElementDeclMiscFlags(eltndx2);
5011      boolean element1IsNillable = (miscFlags1 & SchemaSymbols.NILLABLE) !=0;
5012      boolean element2IsNillable = (miscFlags2 & SchemaSymbols.NILLABLE) !=0;
5013      boolean element2IsFixed = (miscFlags2 & SchemaSymbols.FIXED) !=0;
5014      boolean element1IsFixed = (miscFlags1 & SchemaSymbols.FIXED) !=0;
5015      String JavaDoc element1Value = aGrammar.getElementDefaultValue(eltndx1);
5016      String JavaDoc element2Value = aGrammar.getElementDefaultValue(eltndx2);
5017
5018      if (! (element2IsNillable || !element1IsNillable)) {
5019        throw new ParticleRecoverableError("rcase-nameAndTypeOK.2: Element " +fStringPool.toString(localpart1) + " is nillable in the restriction but not the base");
5020      }
5021
5022      if (! (element2Value == null || !element2IsFixed ||
5023             (element1IsFixed && element1Value.equals(element2Value)))) {
5024        throw new ParticleRecoverableError("rcase-nameAndTypeOK.4: Element " +fStringPool.toString(localpart1) + " is either not fixed, or is not fixed with the same value as in the base");
5025      }
5026
5027      // check disallowed substitutions
5028
int blockSet1 = ((SchemaGrammar) aGrammar).getElementDeclBlockSet(eltndx1);
5029      int blockSet2 = ((SchemaGrammar) aGrammar).getElementDeclBlockSet(eltndx2);
5030      if (((blockSet1 & blockSet2)!=blockSet2) ||
5031            (blockSet1==0 && blockSet2!=0))
5032        throw new ParticleRecoverableError("rcase-nameAndTypeOK.6: Element " +fStringPool.toString(localpart1) + "'s disallowed subsitutions are not a superset of those of the base element's");
5033
5034
5035      // Need element decls for the remainder of the checks
5036
aGrammar.getElementDecl(eltndx1, fTempElementDecl);
5037      aGrammar.getElementDecl(eltndx2, fTempElementDecl2);
5038
5039      // check identity constraints
5040
checkIDConstraintRestriction(fTempElementDecl, fTempElementDecl2, aGrammar, localpart1, localpart2);
5041
5042      // check that the derived element's type is derived from the base's. - TO BE DONE
5043
checkTypesOK(fTempElementDecl,fTempElementDecl2,eltndx1,eltndx2,aGrammar,fStringPool.toString(localpart1));
5044
5045    }
5046
5047    private void checkTypesOK(XMLElementDecl derived, XMLElementDecl base, int dndx, int bndx, SchemaGrammar aGrammar, String JavaDoc elementName) throws Exception JavaDoc {
5048
5049      ComplexTypeInfo tempType=((SchemaGrammar)aGrammar).getElementComplexTypeInfo(dndx);
5050      ComplexTypeInfo bType=((SchemaGrammar)aGrammar).getElementComplexTypeInfo(bndx);
5051      if (derived.type == XMLElementDecl.TYPE_SIMPLE ) {
5052
5053        if (base.type != XMLElementDecl.TYPE_SIMPLE &&
5054            base.type != XMLElementDecl.TYPE_ANY)
5055            throw new ParticleRecoverableError("rcase-nameAndTypeOK.6: Derived element " + elementName + " has a type that does not derive from that of the base");
5056
5057        if (tempType == null) {
5058         if (!(checkSimpleTypeDerivationOK(derived.datatypeValidator,
5059               base.datatypeValidator)) &&
5060             !(bType == null && base.datatypeValidator == null))
5061              throw new ParticleRecoverableError("rcase-nameAndTypeOK.6: Derived element " + elementName + " has a type that does not derive from that of the base");
5062         return;
5063        }
5064      }
5065
5066      for(; tempType != null; tempType = tempType.baseComplexTypeInfo) {
5067        if (bType != null && tempType.typeName.equals(bType.typeName))
5068          break;
5069        if (tempType.derivedBy != SchemaSymbols.RESTRICTION) {
5070          throw new ParticleRecoverableError("rcase-nameAndTypeOK.6: Derived element " + elementName + " has a type that does not derive from that of the base");
5071        }
5072      }
5073
5074      if(tempType == null && !(bType == null && base.datatypeValidator == null)) {
5075        throw new ParticleRecoverableError("rcase-nameAndTypeOK.6: Derived element " + elementName + " has a type that does not derive from that of the base");
5076      }
5077    }
5078
5079    private void checkIDConstraintRestriction(XMLElementDecl derivedElemDecl, XMLElementDecl baseElemDecl,
5080                SchemaGrammar grammar, int derivedElemName, int baseElemName) throws Exception JavaDoc {
5081        // this method throws no errors if the ID constraints on
5082
// the derived element are a logical subset of those on the
5083
// base element--that is, those that are present are
5084
// identical to ones in the base element.
5085
Vector JavaDoc derivedUnique = derivedElemDecl.unique;
5086        Vector JavaDoc baseUnique = baseElemDecl.unique;
5087        if(derivedUnique.size() > baseUnique.size()) {
5088            throw new ParticleRecoverableError("rcase-nameAndTypeOK.5: derived element " +
5089                    fStringPool.toString(derivedElemName) +
5090                    " has fewer <unique> Identity Constraints than the base element"+
5091                    fStringPool.toString(baseElemName));
5092        } else {
5093            boolean found = true;
5094            for(int i=0; i<derivedUnique.size() && found; i++) {
5095                Unique id = (Unique)derivedUnique.elementAt(i);
5096                found = false;
5097                for(int j=0; j<baseUnique.size(); j++) {
5098                    if(id.equals((Unique)baseUnique.elementAt(j))) {
5099                        found = true;
5100                        break;
5101                    }
5102                }
5103            }
5104            if(!found) {
5105                throw new ParticleRecoverableError("rcase-nameAndTypeOK.5: derived element " +
5106                    fStringPool.toString(derivedElemName) +
5107                    " has a <unique> Identity Constraint that does not appear on the base element"+
5108                    fStringPool.toString(baseElemName));
5109            }
5110        }
5111
5112        Vector JavaDoc derivedKey = derivedElemDecl.key;
5113        Vector JavaDoc baseKey = baseElemDecl.key;
5114        if(derivedKey.size() > baseKey.size()) {
5115            throw new ParticleRecoverableError("rcase-nameAndTypeOK.5: derived element " +
5116                    fStringPool.toString(derivedElemName) +
5117                    " has fewer <key> Identity Constraints than the base element"+
5118                    fStringPool.toString(baseElemName));
5119        } else {
5120            boolean found = true;
5121            for(int i=0; i<derivedKey.size() && found; i++) {
5122                Key id = (Key)derivedKey.elementAt(i);
5123                found = false;
5124                for(int j=0; j<baseKey.size(); j++) {
5125                    if(id.equals((Key)baseKey.elementAt(j))) {
5126                        found = true;
5127                        break;
5128                    }
5129                }
5130            }
5131            if(!found) {
5132                throw new ParticleRecoverableError("rcase-nameAndTypeOK.5: derived element " +
5133                    fStringPool.toString(derivedElemName) +
5134                    " has a <key> Identity Constraint that does not appear on the base element"+
5135                    fStringPool.toString(baseElemName));
5136            }
5137        }
5138
5139        Vector JavaDoc derivedKeyRef = derivedElemDecl.keyRef;
5140        Vector JavaDoc baseKeyRef = baseElemDecl.keyRef;
5141        if(derivedKeyRef.size() > baseKeyRef.size()) {
5142            throw new ParticleRecoverableError("rcase-nameAndTypeOK.5: derived element " +
5143                    fStringPool.toString(derivedElemName) +
5144                    " has fewer <keyref> Identity Constraints than the base element"+
5145                    fStringPool.toString(baseElemName));
5146        } else {
5147            boolean found = true;
5148            for(int i=0; i<derivedKeyRef.size() && found; i++) {
5149                KeyRef id = (KeyRef)derivedKeyRef.elementAt(i);
5150                found = false;
5151                for(int j=0; j<baseKeyRef.size(); j++) {
5152                    if(id.equals((KeyRef)baseKeyRef.elementAt(j))) {
5153                        found = true;
5154                        break;
5155                    }
5156                }
5157            }
5158            if(!found) {
5159                throw new ParticleRecoverableError("rcase-nameAndTypeOK.5: derived element " +
5160                    fStringPool.toString(derivedElemName) +
5161                    " has a <keyref> Identity Constraint that does not appear on the base element"+
5162                    fStringPool.toString(baseElemName));
5163            }
5164        }
5165    } // checkIDConstraintRestriction
5166

5167    private boolean checkSubstitutionGroups(int local1, int uri1, int local2, int uri2)
5168throws Exception JavaDoc {
5169
5170       // check if either name is in the other's substitution group
5171
QName name1 = new QName(-1,local1,local1,uri1);
5172       QName name2 = new QName(-1,local2,local2,uri2);
5173
5174       if (fSComp.isEquivalentTo(name1,name2) ||
5175           fSComp.isEquivalentTo(name2,name1))
5176         return true;
5177       else
5178         return false;
5179
5180    }
5181    private boolean checkOccurrenceRange(int min1, int max1, int min2, int max2) {
5182
5183      if ((min1 >= min2) &&
5184          ((max2==SchemaSymbols.OCCURRENCE_UNBOUNDED) || (max1!=SchemaSymbols.OCCURRENCE_UNBOUNDED && max1<=max2)))
5185        return true;
5186      else
5187        return false;
5188    }
5189
5190    private int findElement(int scope, int uriIndex, int nameIndex, SchemaGrammar gr, ComplexTypeInfo bInfo) {
5191
5192      // check for element at given scope first
5193
int elementDeclIndex = gr.getElementDeclIndex(uriIndex,nameIndex,scope);
5194
5195      // if not found, check at global scope
5196
if (elementDeclIndex == -1) {
5197         elementDeclIndex = gr.getElementDeclIndex(nameIndex, -1);
5198
5199         // if still not found, and base is specified, look it up there
5200
if (elementDeclIndex == -1 && bInfo != null) {
5201            ComplexTypeInfo baseInfo = bInfo;
5202            while (baseInfo != null) {
5203                elementDeclIndex = gr.getElementDeclIndex(nameIndex,baseInfo.scopeDefined);
5204                if (elementDeclIndex > -1)
5205                   break;
5206                baseInfo = baseInfo.baseComplexTypeInfo;
5207            }
5208         }
5209
5210      }
5211      return elementDeclIndex;
5212    }
5213
5214    private void checkNSCompat(int csIndex1, int derivedScope, int csIndex2) throws Exception JavaDoc {
5215
5216      int min1 = fSchemaGrammar.getContentSpecMinOccurs(csIndex1);
5217      int max1 = fSchemaGrammar.getContentSpecMaxOccurs(csIndex1);
5218      int min2 = fSchemaGrammar.getContentSpecMinOccurs(csIndex2);
5219      int max2 = fSchemaGrammar.getContentSpecMaxOccurs(csIndex2);
5220
5221      // check Occurrence ranges
5222
if (!checkOccurrenceRange(min1,max1,min2,max2)) {
5223        throw new ParticleRecoverableError("rcase-NSCompat.2: Element occurrence range not a restriction of base any element's range");
5224      }
5225
5226
5227      fSchemaGrammar.getContentSpec(csIndex1, tempContentSpec1);
5228      int uri = tempContentSpec1.otherValue;
5229
5230      // check wildcard subset
5231
if (!wildcardEltAllowsNamespace(csIndex2, uri))
5232        throw new ParticleRecoverableError("rcase-NSCompat.1: Element's namespace not allowed by wildcard in base");
5233
5234    }
5235
5236    private boolean wildcardEltAllowsNamespace(int wildcardNode, int uriIndex) {
5237
5238      fSchemaGrammar.getContentSpec(wildcardNode, tempContentSpec1);
5239      if ((tempContentSpec1.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY)
5240        return true;
5241
5242      if ((tempContentSpec1.type & 0x0f)==XMLContentSpec.CONTENTSPECNODE_ANY_NS) {
5243        if (uriIndex == tempContentSpec1.otherValue)
5244           return true;
5245      }
5246      else { // must be ANY_OTHER
5247
if (uriIndex != tempContentSpec1.otherValue && uriIndex != StringPool.EMPTY_STRING)
5248            return true;
5249      }
5250
5251      return false;
5252    }
5253
5254
5255    private void checkNSSubset(int csIndex1, int csIndex2) throws Exception JavaDoc {
5256      int min1 = fSchemaGrammar.getContentSpecMinOccurs(csIndex1);
5257      int max1 = fSchemaGrammar.getContentSpecMaxOccurs(csIndex1);
5258      int min2 = fSchemaGrammar.getContentSpecMinOccurs(csIndex2);
5259      int max2 = fSchemaGrammar.getContentSpecMaxOccurs(csIndex2);
5260
5261      // check Occurrence ranges
5262
if (!checkOccurrenceRange(min1,max1,min2,max2)) {
5263        throw new ParticleRecoverableError("rcase-NSSubset.2: Wildcard's occurrence range not a restriction of base wildcard's range");
5264      }
5265
5266      if (!wildcardEltSubset(csIndex1, csIndex2))
5267         throw new ParticleRecoverableError("rcase-NSSubset.1: Wildcard is not a subset of corresponding wildcard in base");
5268
5269
5270    }
5271
5272    private boolean wildcardEltSubset(int wildcardNode, int wildcardBaseNode) {
5273
5274      fSchemaGrammar.getContentSpec(wildcardNode, tempContentSpec1);
5275      fSchemaGrammar.getContentSpec(wildcardBaseNode, tempContentSpec2);
5276
5277      if ((tempContentSpec2.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY)
5278        return true;
5279
5280      if ((tempContentSpec1.type & 0x0f)==XMLContentSpec.CONTENTSPECNODE_ANY_OTHER) {
5281        if ((tempContentSpec2.type & 0x0f)==XMLContentSpec.CONTENTSPECNODE_ANY_OTHER &&
5282            tempContentSpec1.otherValue == tempContentSpec2.otherValue)
5283           return true;
5284      }
5285
5286      if ((tempContentSpec1.type & 0x0f)==XMLContentSpec.CONTENTSPECNODE_ANY_NS) {
5287        if ((tempContentSpec2.type & 0x0f)==XMLContentSpec.CONTENTSPECNODE_ANY_NS &&
5288            tempContentSpec1.otherValue == tempContentSpec2.otherValue)
5289           return true;
5290
5291        if ((tempContentSpec2.type & 0x0f)==XMLContentSpec.CONTENTSPECNODE_ANY_OTHER &&
5292            tempContentSpec1.otherValue != tempContentSpec2.otherValue)
5293           return true;
5294
5295      }
5296
5297      return false;
5298    }
5299
5300    private void checkRecurseAsIfGroup(int csIndex1, int derivedScope, int csIndex2, Vector JavaDoc tempVector2, int baseScope, ComplexTypeInfo bInfo) throws Exception JavaDoc {
5301
5302      fSchemaGrammar.getContentSpec(csIndex2, tempContentSpec2);
5303
5304       // Treat the element as if it were in a group of the same type as csindex2
5305
int indexOfGrp=fSchemaGrammar.addContentSpecNode(tempContentSpec2.type,
5306                             csIndex1,-2, false);
5307      Vector JavaDoc tmpVector = new Vector JavaDoc();
5308      tmpVector.addElement(new Integer JavaDoc(csIndex1));
5309
5310
5311      if (tempContentSpec2.type == XMLContentSpec.CONTENTSPECNODE_ALL ||
5312          tempContentSpec2.type == XMLContentSpec.CONTENTSPECNODE_SEQ)
5313         checkRecurse(indexOfGrp, tmpVector, derivedScope, csIndex2,
5314                      tempVector2, baseScope, bInfo);
5315      else
5316         checkRecurseLax(indexOfGrp, tmpVector, derivedScope, csIndex2,
5317                         tempVector2, baseScope, bInfo);
5318
5319      tmpVector = null;
5320    }
5321
5322    private void checkNSRecurseCheckCardinality(int csIndex1, Vector JavaDoc tempVector1, int derivedScope, int csIndex2) throws Exception JavaDoc {
5323
5324      // Implement total range check
5325
int min1 = minEffectiveTotalRange(csIndex1);
5326      int max1 = maxEffectiveTotalRange(csIndex1);
5327
5328      int min2 = fSchemaGrammar.getContentSpecMinOccurs(csIndex2);
5329      int max2 = fSchemaGrammar.getContentSpecMaxOccurs(csIndex2);
5330
5331      // check Occurrence ranges
5332
if (!checkOccurrenceRange(min1,max1,min2,max2)) {
5333        throw new ParticleRecoverableError("rcase-NSSubset.2: Wildcard's occurrence range not a restriction of base wildcard's range");
5334      }
5335
5336      if (!wildcardEltSubset(csIndex1, csIndex2))
5337         throw new ParticleRecoverableError("rcase-NSSubset.1: Wildcard is not a subset of corresponding wildcard in base");
5338      // Check that each member of the group is a valid restriction of the wildcard
5339
int count = tempVector1.size();
5340      for (int i = 0; i < count; i++) {
5341         Integer JavaDoc particle1 = (Integer JavaDoc)tempVector1.elementAt(i);
5342         checkParticleDerivationOK(particle1.intValue(),derivedScope,csIndex2,-1,null);
5343      }
5344
5345    }
5346
5347    private void checkRecurse(int csIndex1, Vector JavaDoc tempVector1, int derivedScope, int csIndex2, Vector JavaDoc tempVector2, int baseScope, ComplexTypeInfo bInfo) throws Exception JavaDoc {
5348
5349      int min1 = fSchemaGrammar.getContentSpecMinOccurs(csIndex1);
5350      int max1 = fSchemaGrammar.getContentSpecMaxOccurs(csIndex1);
5351      int min2 = fSchemaGrammar.getContentSpecMinOccurs(csIndex2);
5352      int max2 = fSchemaGrammar.getContentSpecMaxOccurs(csIndex2);
5353
5354      // check Occurrence ranges
5355
if (!checkOccurrenceRange(min1,max1,min2,max2)) {
5356        throw new ParticleRecoverableError("rcase-Recurse.1: Occurrence range of group is not a valid restriction of occurence range of base group");
5357      }
5358
5359      int count1= tempVector1.size();
5360      int count2= tempVector2.size();
5361
5362      int current = 0;
5363      label: for (int i = 0; i<count1; i++) {
5364
5365        Integer JavaDoc particle1 = (Integer JavaDoc)tempVector1.elementAt(i);
5366        for (int j = current; j<count2; j++) {
5367           Integer JavaDoc particle2 = (Integer JavaDoc)tempVector2.elementAt(j);
5368           current +=1;
5369           try {
5370             checkParticleDerivationOK(particle1.intValue(),derivedScope,
5371                particle2.intValue(), baseScope, bInfo);
5372             continue label;
5373           }
5374           catch (ParticleRecoverableError e) {
5375             if (!particleEmptiable(particle2.intValue()))
5376                throw new ParticleRecoverableError("rcase-Recurse.2: There is not a complete functional mapping between the particles");
5377           }
5378        }
5379        throw new ParticleRecoverableError("rcase-Recurse.2: There is not a complete functional mapping between the particles");
5380      }
5381
5382      // Now, see if there are some elements in the base we didn't match up
5383
for (int j=current; j < count2; j++) {
5384        Integer JavaDoc particle2 = (Integer JavaDoc)tempVector2.elementAt(j);
5385        if (!particleEmptiable(particle2.intValue())) {
5386          throw new ParticleRecoverableError("rcase-Recurse.2: There is not a complete functional mapping between the particles");
5387        }
5388      }
5389
5390    }
5391
5392    private void checkRecurseUnordered(int csIndex1, Vector JavaDoc tempVector1, int derivedScope, int csIndex2, Vector JavaDoc tempVector2, int baseScope, ComplexTypeInfo bInfo) throws Exception JavaDoc {
5393      int min1 = fSchemaGrammar.getContentSpecMinOccurs(csIndex1);
5394      int max1 = fSchemaGrammar.getContentSpecMaxOccurs(csIndex1);
5395      int min2 = fSchemaGrammar.getContentSpecMinOccurs(csIndex2);
5396      int max2 = fSchemaGrammar.getContentSpecMaxOccurs(csIndex2);
5397
5398      // check Occurrence ranges
5399
if (!checkOccurrenceRange(min1,max1,min2,max2)) {
5400        throw new ParticleRecoverableError("rcase-RecurseUnordered.1: Occurrence range of group is not a valid restriction of occurence range of base group");
5401      }
5402
5403      int count1= tempVector1.size();
5404      int count2 = tempVector2.size();
5405
5406      boolean foundIt[] = new boolean[count2];
5407
5408      label: for (int i = 0; i<count1; i++) {
5409
5410        Integer JavaDoc particle1 = (Integer JavaDoc)tempVector1.elementAt(i);
5411        for (int j = 0; j<count2; j++) {
5412           Integer JavaDoc particle2 = (Integer JavaDoc)tempVector2.elementAt(j);
5413           try {
5414             checkParticleDerivationOK(particle1.intValue(),derivedScope,
5415                particle2.intValue(), baseScope, bInfo);
5416             if (foundIt[j])
5417            throw new ParticleRecoverableError("rcase-RecurseUnordered.2: There is not a complete functional mapping between the particles");
5418             else
5419                foundIt[j]=true;
5420
5421             continue label;
5422           }
5423           catch (ParticleRecoverableError e) {
5424           }
5425        }
5426        // didn't find a match. Detect an error
5427
throw new ParticleRecoverableError("rcase-RecurseUnordered.2: There is not a complete functional mapping between the particles");
5428      }
5429
5430    }
5431
5432    private void checkRecurseLax(int csIndex1, Vector JavaDoc tempVector1, int derivedScope, int csIndex2, Vector JavaDoc tempVector2, int baseScope, ComplexTypeInfo bInfo) throws Exception JavaDoc {
5433
5434      int min1 = fSchemaGrammar.getContentSpecMinOccurs(csIndex1);
5435      int max1 = fSchemaGrammar.getContentSpecMaxOccurs(csIndex1);
5436      int min2 = fSchemaGrammar.getContentSpecMinOccurs(csIndex2);
5437      int max2 = fSchemaGrammar.getContentSpecMaxOccurs(csIndex2);
5438
5439      // check Occurrence ranges
5440
if (!checkOccurrenceRange(min1,max1,min2,max2)) {
5441        throw new ParticleRecoverableError("rcase-RecurseLax.1: Occurrence range of group is not a valid restriction of occurence range of base group");
5442      }
5443
5444      int count1= tempVector1.size();
5445      int count2 = tempVector2.size();
5446
5447      int current = 0;
5448      label: for (int i = 0; i<count1; i++) {
5449
5450        Integer JavaDoc particle1 = (Integer JavaDoc)tempVector1.elementAt(i);
5451        for (int j = current; j<count2; j++) {
5452           Integer JavaDoc particle2 = (Integer JavaDoc)tempVector2.elementAt(j);
5453           current +=1;
5454           try {
5455             checkParticleDerivationOK(particle1.intValue(),derivedScope,
5456                particle2.intValue(), baseScope, bInfo);
5457             continue label;
5458           }
5459           catch (ParticleRecoverableError e) {
5460           }
5461        }
5462        // didn't find a match. Detect an error
5463
throw new ParticleRecoverableError("rcase-Recurse.2: There is not a complete functional mapping between the particles");
5464
5465      }
5466
5467    }
5468
5469    private void checkMapAndSum(int csIndex1, Vector JavaDoc tempVector1, int derivedScope, int csIndex2, Vector JavaDoc tempVector2, int baseScope, ComplexTypeInfo bInfo) throws Exception JavaDoc {
5470
5471      // See if the sequence group is a valid restriction of the choice
5472

5473      // Here is an example of a valid restriction:
5474
// <choice minOccurs="2">
5475
// <a/>
5476
// <b/>
5477
// <c/>
5478
// </choice>
5479
//
5480
// <sequence>
5481
// <b/>
5482
// <a/>
5483
// </sequence>
5484

5485      // check the occurrence ranges
5486
// Occurrence range for the sequence:
5487
// min1 = (length of particles) * min of sequence
5488
// max1 = (length of particles) * max of sequence (or unbounded)
5489
// min2 = minOccurs of choice
5490
// max2 = maxOccurs of choice
5491

5492      int count1 = tempVector1.size();
5493      int count2 = tempVector2.size();
5494      int min1 = fSchemaGrammar.getContentSpecMinOccurs(csIndex1) * count1;
5495      int max1 = fSchemaGrammar.getContentSpecMaxOccurs(csIndex1);
5496      if (max1!=SchemaSymbols.OCCURRENCE_UNBOUNDED)
5497        max1 = max1 * count1;
5498      int min2 = fSchemaGrammar.getContentSpecMinOccurs(csIndex2);
5499      int max2 = fSchemaGrammar.getContentSpecMaxOccurs(csIndex2);
5500
5501      // check Occurrence ranges
5502
if (!checkOccurrenceRange(min1,max1,min2,max2)) {
5503        throw new ParticleRecoverableError("rcase-MapAndSum.2: Occurrence range of group is not a valid restriction of occurence range of base group");
5504      }
5505
5506      label: for (int i = 0; i<count1; i++) {
5507
5508        Integer JavaDoc particle1 = (Integer JavaDoc)tempVector1.elementAt(i);
5509        for (int j = 0; j<count2; j++) {
5510           Integer JavaDoc particle2 = (Integer JavaDoc)tempVector2.elementAt(j);
5511           try {
5512             checkParticleDerivationOK(particle1.intValue(),derivedScope,
5513                particle2.intValue(), baseScope, bInfo);
5514
5515             continue label;
5516           }
5517           catch (ParticleRecoverableError e) {
5518           }
5519        }
5520        // didn't find a match. Detect an error
5521
throw new ParticleRecoverableError("rcase-MapAndSum.1: There is not a complete functional mapping between the particles");
5522      }
5523    }
5524
5525    private int importContentSpec(SchemaGrammar aGrammar, int contentSpecHead ) throws Exception JavaDoc {
5526        XMLContentSpec ctsp = new XMLContentSpec();
5527        aGrammar.getContentSpec(contentSpecHead, ctsp);
5528        int left = -1;
5529        int right = -1;
5530        if ( ctsp.type == XMLContentSpec.CONTENTSPECNODE_LEAF
5531             || (ctsp.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY
5532             || (ctsp.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_NS
5533             || (ctsp.type & 0x0f) == XMLContentSpec.CONTENTSPECNODE_ANY_OTHER ) {
5534            left = fSchemaGrammar.addContentSpecNode(ctsp.type, ctsp.value, ctsp.otherValue, false);
5535        }
5536        else if (ctsp.type == -1)
5537            // case where type being extended has no content
5538
return -2;
5539        else {
5540            if ( ctsp.value == -1 ) {
5541                left = -1;
5542            }
5543            else {
5544                left = importContentSpec(aGrammar, ctsp.value);
5545            }
5546
5547            if ( ctsp.otherValue == -1 ) {
5548                right = -1;
5549            }
5550            else {
5551                right = importContentSpec(aGrammar, ctsp.otherValue);
5552            }
5553            left = fSchemaGrammar.addContentSpecNode(ctsp.type, left, right, false);
5554        }
5555
5556        if (fFullConstraintChecking) {
5557            fSchemaGrammar.setContentSpecMaxOccurs(left, aGrammar.getContentSpecMaxOccurs(contentSpecHead));
5558            fSchemaGrammar.setContentSpecMinOccurs(left, aGrammar.getContentSpecMinOccurs(contentSpecHead));
5559        }
5560        return left;
5561    }
5562
5563    private int handleOccurrences(int index,
5564                                  Element JavaDoc particle) throws Exception JavaDoc {
5565        // Pass through, indicating we're not processing an <all>
5566
return handleOccurrences(index, particle, NOT_ALL_CONTEXT);
5567    }
5568
5569    // Checks constraints for minOccurs, maxOccurs and expands content model
5570
// accordingly
5571
private int handleOccurrences(int index, Element JavaDoc particle,
5572                                  int allContextFlags) throws Exception JavaDoc {
5573
5574        // if index is invalid, return
5575
if (index < 0)
5576          return index;
5577
5578        String JavaDoc minOccurs =
5579                    particle.getAttribute(SchemaSymbols.ATT_MINOCCURS).trim();
5580        String JavaDoc maxOccurs =
5581                    particle.getAttribute(SchemaSymbols.ATT_MAXOCCURS).trim();
5582        boolean processingAllEl = ((allContextFlags & PROCESSING_ALL_EL) != 0);
5583        boolean processingAllGP = ((allContextFlags & PROCESSING_ALL_GP) != 0);
5584        boolean groupRefWithAll = ((allContextFlags & GROUP_REF_WITH_ALL) != 0);
5585        boolean isGroupChild = ((allContextFlags & CHILD_OF_GROUP) != 0);
5586
5587        // Neither minOccurs nor maxOccurs may be specified
5588
// for the child of a model group definition.
5589
if (isGroupChild &&
5590            (minOccurs.length() != 0 || maxOccurs.length() != 0)) {
5591            Element JavaDoc group = (Element JavaDoc)particle.getParentNode();
5592            Object JavaDoc[] args = new Object JavaDoc[]{group.getAttribute(SchemaSymbols.ATT_NAME),
5593                                         particle.getNodeName()};
5594            reportSchemaError(SchemaMessageProvider.MinMaxOnGroupChild, args);
5595            minOccurs = (maxOccurs = "1");
5596        }
5597
5598        // If minOccurs=maxOccurs=0, no component is specified
5599
if(minOccurs.equals("0") && maxOccurs.equals("0")){
5600            return -2;
5601        }
5602
5603        int min=1, max=1;
5604
5605        if (minOccurs.length() == 0) {
5606            minOccurs = "1";
5607        }
5608        if (maxOccurs.length() == 0) {
5609            maxOccurs = "1";
5610        }
5611
5612        // For the elements referenced in an <all>, minOccurs attribute
5613
// must be zero or one, and maxOccurs attribute must be one.
5614
// For a complex type definition that contains an <all> or a
5615
// reference a <group> whose model group is an all model group,
5616
// minOccurs and maxOccurs must be one.
5617
if (processingAllEl || groupRefWithAll || processingAllGP) {
5618            if ((processingAllGP||groupRefWithAll||!minOccurs.equals("0")) &&
5619                 !minOccurs.equals("1")) {
5620                int minMsg;
5621
5622                if (processingAllEl) {
5623                    minMsg = SchemaMessageProvider.BadMinMaxForAllElem;
5624                }
5625                else if (processingAllGP) {
5626                    minMsg = SchemaMessageProvider.BadMinMaxForAllGp;
5627                }
5628                else {
5629                    minMsg = SchemaMessageProvider.BadMinMaxForGroupWithAll;
5630                }
5631
5632                reportSchemaError(minMsg, new Object JavaDoc [] { "minOccurs",
5633                                                          minOccurs });
5634                minOccurs = "1";
5635            }
5636
5637            if (!maxOccurs.equals("1")) {
5638                int maxMsg;
5639
5640                if (processingAllEl) {
5641                    maxMsg = SchemaMessageProvider.BadMinMaxForAllElem;
5642                }
5643                else if (processingAllGP) {
5644                    maxMsg = SchemaMessageProvider.BadMinMaxForAllGp;
5645                }
5646                else {
5647                    maxMsg = SchemaMessageProvider.BadMinMaxForGroupWithAll;
5648                }
5649
5650                reportSchemaError(maxMsg, new Object JavaDoc [] { "maxOccurs",
5651                                                          maxOccurs });
5652                maxOccurs = "1";
5653            }
5654        }
5655
5656        try {
5657            min = Integer.parseInt(minOccurs);
5658        }
5659        catch (Exception JavaDoc e){
5660            reportSchemaError(SchemaMessageProvider.GenericError,
5661                              new Object JavaDoc [] { "illegal value for minOccurs or maxOccurs : '" +e.getMessage()+ "' "});
5662        }
5663
5664        if (maxOccurs.equals("unbounded")) {
5665           max = SchemaSymbols.OCCURRENCE_UNBOUNDED;
5666        }
5667        else {
5668           try {
5669               max = Integer.parseInt(maxOccurs);
5670           }
5671           catch (Exception JavaDoc e){
5672               reportSchemaError(SchemaMessageProvider.GenericError,
5673                                new Object JavaDoc [] { "illegal value for minOccurs or maxOccurs : '" +e.getMessage()+ "' "});
5674           }
5675
5676           // Check that minOccurs isn't greater than maxOccurs.
5677
// p-props-correct 2.1
5678
if (min > max) {
5679               reportGenericSchemaError("p-props-correct:2.1 Value of minOccurs '" + minOccurs + "' must not be greater than value of maxOccurs '" + maxOccurs +"'");
5680           }
5681
5682           if (max < 1) {
5683               reportGenericSchemaError("p-props-correct:2.2 Value of maxOccurs " + maxOccurs + " is invalid. It must be greater than or equal to 1");
5684           }
5685        }
5686
5687        if (fSchemaGrammar.getDeferContentSpecExpansion()) {
5688          fSchemaGrammar.setContentSpecMinOccurs(index,min);
5689          fSchemaGrammar.setContentSpecMaxOccurs(index,max);
5690          return index;
5691        }
5692        else {
5693          return fSchemaGrammar.expandContentModel(index,min,max);
5694        }
5695
5696    }
5697
5698
5699    /**
5700     * Traverses Schema attribute declaration.
5701     *
5702     * <attribute
5703     * default = string
5704     * fixed = string
5705     * form = (qualified | unqualified)
5706     * id = ID
5707     * name = NCName
5708     * ref = QName
5709     * type = QName
5710     * use = (optional | prohibited | required) : optional
5711     * {any attributes with non-schema namespace ...}>
5712     * Content: (annotation? , simpleType?)
5713     * <attribute/>
5714     *
5715     * @param attributeDecl: the declaration of the attribute under consideration
5716     * @param typeInfo: Contains the index of the element to which the attribute declaration is attached.
5717     * @param referredTo: true iff traverseAttributeDecl was called because
5718     * of encountering a ``ref''property (used
5719     * to suppress error-reporting).
5720     * @return 0 if the attribute schema is validated successfully, otherwise -1
5721     * @exception Exception
5722     */

5723    private int traverseAttributeDecl( Element JavaDoc attrDecl, ComplexTypeInfo typeInfo, boolean referredTo ) throws Exception JavaDoc {
5724
5725        // General Attribute Checking
5726
int scope = isTopLevel(attrDecl)?
5727                    GeneralAttrCheck.ELE_CONTEXT_GLOBAL:
5728                    GeneralAttrCheck.ELE_CONTEXT_LOCAL;
5729        Hashtable JavaDoc attrValues = generalCheck(attrDecl, scope);
5730
5731        ////// Get declared fields of the attribute
5732
String JavaDoc defaultStr = attrDecl.getAttribute(SchemaSymbols.ATT_DEFAULT);
5733        String JavaDoc fixedStr = attrDecl.getAttribute(SchemaSymbols.ATT_FIXED);
5734        String JavaDoc formStr = attrDecl.getAttribute(SchemaSymbols.ATT_FORM);//form attribute
5735
String JavaDoc attNameStr = attrDecl.getAttribute(SchemaSymbols.ATT_NAME);
5736        String JavaDoc refStr = attrDecl.getAttribute(SchemaSymbols.ATT_REF);
5737        String JavaDoc datatypeStr = attrDecl.getAttribute(SchemaSymbols.ATT_TYPE);
5738        String JavaDoc useStr = attrDecl.getAttribute(SchemaSymbols.ATT_USE);
5739        Element JavaDoc simpleTypeChild = findAttributeSimpleType(attrDecl);
5740
5741        Attr JavaDoc defaultAtt = attrDecl.getAttributeNode(SchemaSymbols.ATT_DEFAULT);
5742        Attr JavaDoc fixedAtt = attrDecl.getAttributeNode(SchemaSymbols.ATT_FIXED);
5743        Attr JavaDoc formAtt = attrDecl.getAttributeNode(SchemaSymbols.ATT_FORM);
5744        Attr JavaDoc attNameAtt = attrDecl.getAttributeNode(SchemaSymbols.ATT_NAME);
5745        Attr JavaDoc refAtt = attrDecl.getAttributeNode(SchemaSymbols.ATT_REF);
5746        Attr JavaDoc datatypeAtt = attrDecl.getAttributeNode(SchemaSymbols.ATT_TYPE);
5747        Attr JavaDoc useAtt = attrDecl.getAttributeNode(SchemaSymbols.ATT_USE);
5748
5749        checkEnumerationRequiredNotation(attNameStr, datatypeStr);
5750
5751        ////// define attribute declaration Schema components
5752
int attName; // attribute name indexed in the string pool
5753
int uriIndex; // indexed for target namespace uri
5754
QName attQName; // QName combining attName and uriIndex
5755

5756        // attribute type
5757
int attType;
5758        boolean attIsList = false;
5759        int dataTypeSymbol = -1;
5760        String JavaDoc localpart = null;
5761
5762        // validator
5763
DatatypeValidator dv;
5764        boolean dvIsDerivedFromID = false;
5765
5766        // value constraints and use type
5767
int attValueAndUseType = 0;
5768        int attValueConstraint = -1; // indexed value in a string pool
5769

5770        ////// Check W3C's PR-Structure 3.2.3
5771
// --- Constraints on XML Representations of Attribute Declarations
5772
boolean isAttrTopLevel = isTopLevel(attrDecl);
5773        boolean isOptional = false;
5774        boolean isProhibited = false;
5775        boolean isRequired = false;
5776
5777        StringBuffer JavaDoc errorContext = new StringBuffer JavaDoc(30);
5778        errorContext.append(" -- ");
5779        if(typeInfo == null) {
5780            errorContext.append("(global attribute) ");
5781        }
5782        else if(typeInfo.typeName == null) {
5783            errorContext.append("(local attribute) ");
5784        }
5785        else {
5786            errorContext.append("(attribute) ").append(typeInfo.typeName).append("/");
5787        }
5788        errorContext.append(attNameStr).append(' ').append(refStr);
5789
5790        if(useStr.length() == 0 || useStr.equals(SchemaSymbols.ATTVAL_OPTIONAL)) {
5791            attValueAndUseType |= XMLAttributeDecl.USE_TYPE_OPTIONAL;
5792            isOptional = true;
5793        }
5794        else if(useStr.equals(SchemaSymbols.ATTVAL_PROHIBITED)) {
5795            attValueAndUseType |= XMLAttributeDecl.USE_TYPE_PROHIBITED;
5796            isProhibited = true;
5797        }
5798        else if(useStr.equals(SchemaSymbols.ATTVAL_REQUIRED)) {
5799            attValueAndUseType |= XMLAttributeDecl.USE_TYPE_REQUIRED;
5800            isRequired = true;
5801        }
5802        else {
5803            reportGenericSchemaError("An attribute cannot declare \"" +
5804                SchemaSymbols.ATT_USE + "\" as \"" + useStr + "\"" + errorContext);
5805        }
5806
5807        if(defaultAtt != null && fixedAtt != null) {
5808            reportGenericSchemaError("src-attribute.1: \"" + SchemaSymbols.ATT_DEFAULT +
5809                "\" and \"" + SchemaSymbols.ATT_FIXED +
5810                "\" cannot be both present" + errorContext);
5811        }
5812        else if(defaultAtt != null && !isOptional) {
5813            reportGenericSchemaError("src-attribute.2: If both \"" + SchemaSymbols.ATT_DEFAULT +
5814                "\" and \"" + SchemaSymbols.ATT_USE + "\" " +
5815                "are present for an attribute declaration, \"" +
5816                SchemaSymbols.ATT_USE + "\" can only be \"" +
5817                SchemaSymbols.ATTVAL_OPTIONAL + "\", not \"" + useStr + "\"." + errorContext);
5818        }
5819
5820        if(!isAttrTopLevel) {
5821            if((refAtt == null) == (attNameAtt == null)) {
5822                reportGenericSchemaError("src-attribute.3.1: When the attribute's parent is not <schema> , one of \"" +
5823                    SchemaSymbols.ATT_REF + "\" and \"" + SchemaSymbols.ATT_NAME +
5824                    "\" should be declared, but not both."+ errorContext);
5825                return -1;
5826            }
5827            else if((refAtt != null) && (simpleTypeChild != null || formAtt != null || datatypeAtt != null)) {
5828                reportGenericSchemaError("src-attribute.3.2: When the attribute's parent is not <schema> and \"" +
5829                    SchemaSymbols.ATT_REF + "\" is present, " +
5830                    "all of <" + SchemaSymbols.ELT_SIMPLETYPE + ">, " +
5831                    SchemaSymbols.ATT_FORM + " and " + SchemaSymbols.ATT_TYPE +
5832                    " must be absent."+ errorContext);
5833            }
5834        }
5835
5836        if(datatypeAtt != null && simpleTypeChild != null) {
5837            reportGenericSchemaError("src-attribute.4: \"" + SchemaSymbols.ATT_TYPE + "\" and <" +
5838                SchemaSymbols.ELT_SIMPLETYPE + "> cannot both be present"+ errorContext);
5839        }
5840
5841        ////// Check W3C's PR-Structure 3.2.2
5842
// --- XML Representation of Attribute Declaration Schema Components
5843

5844        // check case-dependent attribute declaration schema components
5845
if (isAttrTopLevel) {
5846            //// global attributes
5847
// set name component
5848
attName = fStringPool.addSymbol(attNameStr);
5849            if(fTargetNSURIString.length() == 0) {
5850                uriIndex = StringPool.EMPTY_STRING;
5851            }
5852            else {
5853                uriIndex = fTargetNSURI;
5854            }
5855
5856            // attQName = new QName(-1,attName,attName,uriIndex);
5857
// Above line replaced by following 2 to work around a JIT problem.
5858
attQName = new QName();
5859            attQName.setValues(-1,attName,attName,uriIndex);
5860
5861        }
5862        else if(refAtt == null) {
5863            //// local attributes
5864
// set name component
5865
attName = fStringPool.addSymbol(attNameStr);
5866            if((formStr.length() > 0 && formStr.equals(SchemaSymbols.ATTVAL_QUALIFIED)) ||
5867                (formStr.length() == 0 && fAttributeDefaultQualified)) {
5868                uriIndex = fTargetNSURI;
5869            }
5870            else {
5871                uriIndex = StringPool.EMPTY_STRING;
5872            }
5873            // attQName = new QName(-1,attName,attName,uriIndex);
5874
// Above line replaced by following 2 to work around a JIT problem.
5875
attQName = new QName();
5876            attQName.setValues(-1,attName,attName,uriIndex);
5877        }
5878        else {
5879            //// locally referenced global attributes
5880
String JavaDoc prefix;
5881            int colonptr = refStr.indexOf(":");
5882            if ( colonptr > 0) {
5883                prefix = refStr.substring(0,colonptr);
5884                localpart = refStr.substring(colonptr+1);
5885            }
5886            else {
5887                prefix = "";
5888                localpart = refStr;
5889            }
5890
5891            String JavaDoc uriStr = resolvePrefixToURI(prefix);
5892
5893            if (!uriStr.equals(fTargetNSURIString)) {
5894                addAttributeDeclFromAnotherSchema(localpart, uriStr, typeInfo, defaultAtt != null, fixedAtt != null, fixedStr, attValueAndUseType);
5895                return 0;
5896            }
5897
5898            Element JavaDoc referredAttribute = getTopLevelComponentByName(SchemaSymbols.ELT_ATTRIBUTE,localpart);
5899            if (referredAttribute != null) {
5900                    // don't need to traverse ref'd attribute if we're global; just make sure it's there...
5901
traverseAttributeDecl(referredAttribute, typeInfo, true);
5902
5903                Attr JavaDoc referFixedAttr = referredAttribute.getAttributeNode(SchemaSymbols.ATT_FIXED);
5904                String JavaDoc referFixed = referFixedAttr == null ? null : referFixedAttr.getValue();
5905                if (referFixed != null && (defaultAtt != null || fixedAtt != null && !referFixed.equals(fixedStr))) {
5906                    reportGenericSchemaError("au-props-correct.2: If the {attribute declaration} has a fixed {value constraint}, then if the attribute use itself has a {value constraint}, it must also be fixed and its value must match that of the {attribute declaration}'s {value constraint}" + errorContext);
5907                }
5908
5909                // this nasty hack needed to ``override'' the
5910
// global attribute with "use" and "fixed" on the ref'ing attribute
5911
if((typeInfo != null) && (!isOptional || fixedStr.length() > 0)) {
5912                    int referredAttName = fStringPool.addSymbol(referredAttribute.getAttribute(SchemaSymbols.ATT_NAME));
5913                    uriIndex = StringPool.EMPTY_STRING;
5914                    if ( fTargetNSURIString.length() > 0) {
5915                        uriIndex = fTargetNSURI;
5916                    }
5917                    QName referredAttQName = new QName(-1,referredAttName,referredAttName,uriIndex);
5918
5919                    int tempIndex = fSchemaGrammar.getAttributeDeclIndex(typeInfo.templateElementIndex, referredAttQName);
5920                    XMLAttributeDecl referredAttrDecl = new XMLAttributeDecl();
5921                    fSchemaGrammar.getAttributeDecl(tempIndex, referredAttrDecl);
5922
5923                    boolean updated = false;
5924
5925                    int useDigits = XMLAttributeDecl.USE_TYPE_OPTIONAL |
5926                                      XMLAttributeDecl.USE_TYPE_PROHIBITED |
5927                                      XMLAttributeDecl.USE_TYPE_REQUIRED;
5928
5929                    int valueDigits = XMLAttributeDecl.VALUE_CONSTRAINT_DEFAULT |
5930                                      XMLAttributeDecl.VALUE_CONSTRAINT_FIXED;
5931
5932                    if(!isOptional &&
5933                       (referredAttrDecl.defaultType & useDigits) !=
5934                       (attValueAndUseType & useDigits))
5935                    {
5936                        if(referredAttrDecl.defaultType != XMLAttributeDecl.USE_TYPE_PROHIBITED) {
5937                                referredAttrDecl.defaultType |= useDigits;
5938                                referredAttrDecl.defaultType ^= useDigits; // clear the use
5939
referredAttrDecl.defaultType |= (attValueAndUseType & useDigits);
5940                            updated = true;
5941                        }
5942                    }
5943
5944                    if(fixedStr.length() > 0) {
5945                        if((referredAttrDecl.defaultType & XMLAttributeDecl.VALUE_CONSTRAINT_FIXED) == 0) {
5946                            referredAttrDecl.defaultType |= valueDigits;
5947                            referredAttrDecl.defaultType ^= valueDigits; // clear the value
5948
referredAttrDecl.defaultType |= XMLAttributeDecl.VALUE_CONSTRAINT_FIXED;
5949                            referredAttrDecl.defaultValue = fixedStr;
5950                            updated = true;
5951                        }
5952                    }
5953
5954                    if(updated) {
5955                        fSchemaGrammar.setAttributeDecl(typeInfo.templateElementIndex, tempIndex, referredAttrDecl);
5956                    }
5957                }
5958            }
5959            else if (fAttributeDeclRegistry.get(localpart) != null) {
5960                addAttributeDeclFromAnotherSchema(localpart, uriStr, typeInfo, defaultAtt != null, fixedAtt != null, fixedStr, attValueAndUseType);
5961            }
5962            else {
5963                    // REVISIT: Localize
5964
reportGenericSchemaError ( "Couldn't find top level attribute " + refStr + errorContext);
5965            }
5966            return 0;
5967            }
5968
5969        if (uriIndex == fXsiURI) {
5970            reportGenericSchemaError("no-xsi: The {target namespace} of an attribute declaration must not match " + SchemaSymbols.URI_XSI + errorContext);
5971        }
5972
5973        // validation of attribute type is same for each case of declaration
5974
if (simpleTypeChild != null) {
5975            attType = XMLAttributeDecl.TYPE_SIMPLE;
5976            dataTypeSymbol = traverseSimpleTypeDecl(simpleTypeChild);
5977            localpart = fStringPool.toString(dataTypeSymbol);
5978            dv = fDatatypeRegistry.getDatatypeValidator(localpart);
5979        }
5980        else if (datatypeStr.length() != 0) {
5981            dataTypeSymbol = fStringPool.addSymbol(datatypeStr);
5982            String JavaDoc prefix;
5983            int colonptr = datatypeStr.indexOf(":");
5984            if ( colonptr > 0) {
5985                prefix = datatypeStr.substring(0,colonptr);
5986                localpart = datatypeStr.substring(colonptr+1);
5987            }
5988            else {
5989                prefix = "";
5990                localpart = datatypeStr;
5991            }
5992            String JavaDoc typeURI = resolvePrefixToURI(prefix);
5993
5994            if ( typeURI.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)) {
5995                dv = getDatatypeValidator(SchemaSymbols.URI_SCHEMAFORSCHEMA, localpart);
5996
5997                if (localpart.equals("ID")) {
5998                    attType = XMLAttributeDecl.TYPE_ID;
5999                } else if (localpart.equals("IDREF")) {
6000                    attType = XMLAttributeDecl.TYPE_IDREF;
6001                } else if (localpart.equals("IDREFS")) {
6002                    attType = XMLAttributeDecl.TYPE_IDREF;
6003                    attIsList = true;
6004                } else if (localpart.equals("ENTITY")) {
6005                    attType = XMLAttributeDecl.TYPE_ENTITY;
6006                } else if (localpart.equals("ENTITIES")) {
6007                    attType = XMLAttributeDecl.TYPE_ENTITY;
6008                    attIsList = true;
6009                } else if (localpart.equals("NMTOKEN")) {
6010                    attType = XMLAttributeDecl.TYPE_NMTOKEN;
6011                } else if (localpart.equals("NMTOKENS")) {
6012                    attType = XMLAttributeDecl.TYPE_NMTOKEN;
6013                    attIsList = true;
6014                } else if (localpart.equals(SchemaSymbols.ELT_NOTATION)) {
6015                    attType = XMLAttributeDecl.TYPE_NOTATION;
6016                }
6017                else {
6018                    attType = XMLAttributeDecl.TYPE_SIMPLE;
6019                    if(dv == null && !referredTo) {
6020                        // REVISIT: localize
6021
reportGenericSchemaError("attribute " + attNameStr + " has a type (" + datatypeStr + ") which is not recognized as one of the predefined schema datatypes");
6022                    }
6023                }
6024            } else { //isn't of the schema for schemas namespace...
6025
attType = XMLAttributeDecl.TYPE_SIMPLE;
6026                // check if the type is from the same Schema
6027

6028                dv = getDatatypeValidator(typeURI, localpart);
6029                if (dv == null && typeURI.equals(fTargetNSURIString) ) {
6030                    Element JavaDoc topleveltype = getTopLevelComponentByName(SchemaSymbols.ELT_SIMPLETYPE, localpart);
6031                    if (topleveltype != null) {
6032                        traverseSimpleTypeDecl( topleveltype );
6033                        dv = getDatatypeValidator(typeURI, localpart);
6034                    }else if (!referredTo) {
6035                        // REVISIT: Localize
6036
reportGenericSchemaError("simpleType not found : " + "("+typeURI+":"+ localpart+")"+ errorContext);
6037                    }
6038                } if(dv == null && !referredTo) {
6039                    // REVISIT: localize
6040
reportGenericSchemaError("attribute " + attNameStr + " has an unrecognized type " + datatypeStr);
6041                }
6042            }
6043        } else {
6044            attType = XMLAttributeDecl.TYPE_SIMPLE;
6045            localpart = "string";
6046            dataTypeSymbol = fStringPool.addSymbol(localpart);
6047            dv = fDatatypeRegistry.getDatatypeValidator(localpart);
6048        } // if(...Type)
6049

6050        // validation of data constraint is same for each case of declaration
6051
if(defaultStr.length() > 0) {
6052            attValueAndUseType |= XMLAttributeDecl.VALUE_CONSTRAINT_DEFAULT;
6053            attValueConstraint = fStringPool.addString(defaultStr);
6054            }
6055        else if(fixedStr.length() > 0) {
6056            attValueAndUseType |= XMLAttributeDecl.VALUE_CONSTRAINT_FIXED;
6057            attValueConstraint = fStringPool.addString(fixedStr);
6058        }
6059
6060        ////// Check W3C's PR-Structure 3.2.6
6061
// --- Constraints on Attribute Declaration Schema Components
6062
// check default value is valid for the datatype.
6063
if (attType == XMLAttributeDecl.TYPE_SIMPLE && attValueConstraint != -1) {
6064            try {
6065                if (dv != null) {
6066                    if(defaultStr.length() > 0) {
6067                    //REVISIT
6068
dv.validate(defaultStr, null);
6069                    }
6070                    else {
6071                        dv.validate(fixedStr, null);
6072                    }
6073                }
6074                else if (!referredTo)
6075                    reportSchemaError(SchemaMessageProvider.NoValidatorFor,
6076                            new Object JavaDoc [] { datatypeStr });
6077            } catch (InvalidDatatypeValueException idve) {
6078                if (!referredTo)
6079                    reportSchemaError(SchemaMessageProvider.IncorrectDefaultType,
6080                        new Object JavaDoc [] { attrDecl.getAttribute(SchemaSymbols.ATT_NAME), idve.getMessage() }); //a-props-correct.2
6081
}
6082        }
6083
6084        // check the coexistence of ID and value constraint
6085
dvIsDerivedFromID =
6086          ((dv != null) && dv instanceof IDDatatypeValidator);
6087        if (dvIsDerivedFromID && attValueConstraint != -1)
6088        {
6089            reportGenericSchemaError("a-props-correct.3: If type definition is or is derived from ID ," +
6090                "there must not be a value constraint" + errorContext);
6091        }
6092
6093        if (attNameStr.equals("xmlns")) {
6094            reportGenericSchemaError("no-xmlns: The {name} of an attribute declaration must not match 'xmlns'" + errorContext);
6095        }
6096
6097        ////// every contraints were matched. Now register the attribute declaration
6098
//put the top-levels in the attribute decl registry.
6099
if (isAttrTopLevel) {
6100            fTempAttributeDecl.datatypeValidator = dv;
6101            fTempAttributeDecl.name.setValues(attQName);
6102            fTempAttributeDecl.type = attType;
6103            fTempAttributeDecl.defaultType = attValueAndUseType;
6104            fTempAttributeDecl.list = attIsList;
6105            if (attValueConstraint != -1 ) {
6106                fTempAttributeDecl.defaultValue = fStringPool.toString(attValueConstraint);
6107            } else {
6108                fTempAttributeDecl.defaultValue = null;
6109            }
6110            fAttributeDeclRegistry.put(attNameStr, new XMLAttributeDecl(fTempAttributeDecl));
6111        }
6112
6113        // add attribute to attr decl pool in fSchemaGrammar,
6114
if (typeInfo != null) {
6115
6116            // check that there aren't duplicate attributes
6117
int temp = fSchemaGrammar.getAttributeDeclIndex(typeInfo.templateElementIndex, attQName);
6118            if (temp > -1) {
6119              reportGenericSchemaError("ct-props-correct.4: Duplicate attribute " +
6120              fStringPool.toString(attQName.rawname) + " in type definition");
6121            }
6122
6123            // check that there aren't multiple attributes with type derived from ID
6124
if (dvIsDerivedFromID) {
6125               if (typeInfo.containsAttrTypeID()) {
6126                 reportGenericSchemaError("ct-props-correct.5: More than one attribute derived from type ID cannot appear in the same complex type definition.");
6127               }
6128               typeInfo.setContainsAttrTypeID();
6129            }
6130            fSchemaGrammar.addAttDef( typeInfo.templateElementIndex,
6131                                      attQName, attType,
6132                                      dataTypeSymbol, attValueAndUseType,
6133                                      fStringPool.toString( attValueConstraint), dv, attIsList);
6134        }
6135
6136        return 0;
6137    } // end of method traverseAttribute
6138

6139    private int addAttributeDeclFromAnotherSchema( String JavaDoc name, String JavaDoc uriStr, ComplexTypeInfo typeInfo) throws Exception JavaDoc {
6140        Grammar grammar = fGrammarResolver.getGrammar(uriStr);
6141        if (uriStr == null || ! (grammar instanceof SchemaGrammar) ) {
6142            // REVISIT: Localize
6143
reportGenericSchemaError( "no attribute named \"" + name
6144                                      + "\" was defined in schema : " + uriStr);
6145            return -1;
6146        }
6147        SchemaGrammar aGrammar = (SchemaGrammar)grammar;
6148
6149        Hashtable JavaDoc attrRegistry = aGrammar.getAttributeDeclRegistry();
6150        if (attrRegistry == null) {
6151            // REVISIT: Localize
6152
reportGenericSchemaError( "no attribute named \"" + name
6153                                      + "\" was defined in schema : " + uriStr);
6154            return -1;
6155        }
6156
6157        XMLAttributeDecl referredAttrDecl = (XMLAttributeDecl) attrRegistry.get(name);
6158
6159        if (referredAttrDecl == null) {
6160            // REVISIT: Localize
6161
reportGenericSchemaError( "no attribute named \"" + name
6162                                      + "\" was defined in schema : " + uriStr);
6163            return -1;
6164        }
6165
6166
6167        if (typeInfo!= null) {
6168
6169            // check that there aren't duplicate attributes
6170
int temp = fSchemaGrammar.getAttributeDeclIndex(typeInfo.templateElementIndex, referredAttrDecl.name);
6171            if (temp > -1) {
6172              reportGenericSchemaError("ct-props-correct.4: Duplicate attribute " +
6173              fStringPool.toString(referredAttrDecl.name.rawname) + " in type definition");
6174            }
6175
6176            // check that there aren't multiple attributes with type derived from ID
6177
if (referredAttrDecl.datatypeValidator != null &&
6178                referredAttrDecl.datatypeValidator instanceof IDDatatypeValidator) {
6179               if (typeInfo.containsAttrTypeID()) {
6180                 reportGenericSchemaError("ct-props-correct.5: More than one attribute derived from type ID cannot appear in the same complex type definition");
6181               }
6182               typeInfo.setContainsAttrTypeID();
6183            }
6184
6185            fSchemaGrammar.addAttDef( typeInfo.templateElementIndex,
6186                                      referredAttrDecl.name, referredAttrDecl.type,
6187                                      -1, referredAttrDecl.defaultType,
6188                                      referredAttrDecl.defaultValue,
6189                                      referredAttrDecl.datatypeValidator,
6190                                      referredAttrDecl.list);
6191        }
6192
6193
6194        return 0;
6195    }
6196
6197    private int addAttributeDeclFromAnotherSchema( String JavaDoc name, String JavaDoc uriStr, ComplexTypeInfo typeInfo, boolean hasDefault, boolean hasFixed, String JavaDoc fixedValue, int attValueAndUseType) throws Exception JavaDoc {
6198        Grammar grammar = fGrammarResolver.getGrammar(uriStr);
6199        if (uriStr == null || ! (grammar instanceof SchemaGrammar) ) {
6200            // REVISIT: Localize
6201
reportGenericSchemaError( "no attribute named \"" + name
6202                                      + "\" was defined in schema : " + uriStr);
6203            return -1;
6204        }
6205        SchemaGrammar aGrammar = (SchemaGrammar)grammar;
6206
6207        Hashtable JavaDoc attrRegistry = aGrammar.getAttributeDeclRegistry();
6208        if (attrRegistry == null) {
6209            // REVISIT: Localize
6210
reportGenericSchemaError( "no attribute named \"" + name
6211                                      + "\" was defined in schema : " + uriStr);
6212            return -1;
6213        }
6214
6215        XMLAttributeDecl referredAttrDecl = (XMLAttributeDecl) attrRegistry.get(name);
6216
6217        if (referredAttrDecl == null) {
6218            // REVISIT: Localize
6219
reportGenericSchemaError( "no attribute named \"" + name
6220                                      + "\" was defined in schema : " + uriStr);
6221            return -1;
6222        }
6223
6224        referredAttrDecl = new XMLAttributeDecl(referredAttrDecl);
6225
6226        if (typeInfo!= null) {
6227
6228            // check that there aren't duplicate attributes
6229
int temp = fSchemaGrammar.getAttributeDeclIndex(typeInfo.templateElementIndex, referredAttrDecl.name);
6230            if (temp > -1) {
6231              reportGenericSchemaError("ct-props-correct.4: Duplicate attribute " +
6232              fStringPool.toString(referredAttrDecl.name.rawname) + " in type definition");
6233            }
6234
6235            // check that there aren't multiple attributes with type derived from ID
6236
if (referredAttrDecl.datatypeValidator != null &&
6237                referredAttrDecl.datatypeValidator instanceof IDDatatypeValidator) {
6238               if (typeInfo.containsAttrTypeID()) {
6239                 reportGenericSchemaError("ct-props-correct.5: More than one attribute derived from type ID cannot appear in the same complex type definition");
6240               }
6241               typeInfo.setContainsAttrTypeID();
6242            }
6243
6244            /**
6245             * Copied (and modified) the following code from traverseAttributeDecl
6246             * because we also need to override "use" and "fixed" of the attribute
6247             * from another namespace. - sandyg
6248             */

6249            boolean isReferFixed = (referredAttrDecl.defaultType & XMLAttributeDecl.DEFAULT_TYPE_FIXED) != 0;
6250            String JavaDoc referFixed = isReferFixed ? null : referredAttrDecl.defaultValue;
6251            if (referFixed != null && (hasDefault || hasFixed && !referFixed.equals(fixedValue))) {
6252                reportGenericSchemaError("au-props-correct.2: If the {attribute declaration} has a fixed {value constraint}, then if the attribute use itself has a {value constraint}, it must also be fixed and its value must match that of the {attribute declaration}'s {value constraint}");
6253            }
6254
6255            // this nasty hack needed to ``override'' the
6256
// global attribute with "use" and "fixed" on the ref'ing attribute
6257
if((attValueAndUseType & XMLAttributeDecl.USE_TYPE_OPTIONAL) == 0 ||
6258               fixedValue.length() > 0) {
6259
6260                int useDigits = XMLAttributeDecl.USE_TYPE_OPTIONAL |
6261                                  XMLAttributeDecl.USE_TYPE_PROHIBITED |
6262                                  XMLAttributeDecl.USE_TYPE_REQUIRED;
6263
6264                int valueDigits = XMLAttributeDecl.VALUE_CONSTRAINT_DEFAULT |
6265                                  XMLAttributeDecl.VALUE_CONSTRAINT_FIXED;
6266
6267                if((attValueAndUseType & XMLAttributeDecl.USE_TYPE_OPTIONAL) == 0 &&
6268                   (referredAttrDecl.defaultType & useDigits) !=
6269                   (attValueAndUseType & useDigits))
6270                {
6271                    if(referredAttrDecl.defaultType != XMLAttributeDecl.USE_TYPE_PROHIBITED) {
6272                            referredAttrDecl.defaultType |= useDigits;
6273                            referredAttrDecl.defaultType ^= useDigits; // clear the use
6274
referredAttrDecl.defaultType |= (attValueAndUseType & useDigits);
6275                    }
6276                }
6277
6278                if(fixedValue.length() > 0) {
6279                    if((referredAttrDecl.defaultType & XMLAttributeDecl.VALUE_CONSTRAINT_FIXED) == 0) {
6280                        referredAttrDecl.defaultType |= valueDigits;
6281                        referredAttrDecl.defaultType ^= valueDigits; // clear the value
6282
referredAttrDecl.defaultType |= XMLAttributeDecl.VALUE_CONSTRAINT_FIXED;
6283                        referredAttrDecl.defaultValue = fixedValue;
6284                    }
6285                }
6286            }
6287            //***************************************
6288

6289            fSchemaGrammar.addAttDef( typeInfo.templateElementIndex,
6290                                      referredAttrDecl.name, referredAttrDecl.type,
6291                                      -1, referredAttrDecl.defaultType,
6292                                      referredAttrDecl.defaultValue,
6293                                      referredAttrDecl.datatypeValidator,
6294                                      referredAttrDecl.list);
6295        }
6296
6297
6298        return 0;
6299    }
6300
6301    /*
6302    *
6303    * <attributeGroup
6304    * id = ID
6305    * name = NCName
6306    * ref = QName>
6307    * Content: (annotation?, (attribute|attributeGroup)*, anyAttribute?)
6308    * </>
6309    *
6310    */

6311    private int traverseAttributeGroupDecl( Element JavaDoc attrGrpDecl, ComplexTypeInfo typeInfo, Vector JavaDoc anyAttDecls ) throws Exception JavaDoc {
6312        // General Attribute Checking
6313
int scope = isTopLevel(attrGrpDecl)?
6314                    GeneralAttrCheck.ELE_CONTEXT_GLOBAL:
6315                    GeneralAttrCheck.ELE_CONTEXT_LOCAL;
6316        Hashtable JavaDoc attrValues = generalCheck(attrGrpDecl, scope);
6317
6318        // attributeGroup name
6319
String JavaDoc attGrpNameStr = attrGrpDecl.getAttribute(SchemaSymbols.ATT_NAME);
6320        int attGrpName = fStringPool.addSymbol(attGrpNameStr);
6321
6322        String JavaDoc ref = attrGrpDecl.getAttribute(SchemaSymbols.ATT_REF);
6323        Element JavaDoc child = checkContent( attrGrpDecl, XUtil.getFirstChildElement(attrGrpDecl), true );
6324
6325        if (ref.length() != 0) {
6326            if(isTopLevel(attrGrpDecl))
6327                // REVISIT: localize
6328
reportGenericSchemaError ( "An attributeGroup with \"ref\" present must not have <schema> or <redefine> as its parent");
6329            if(attGrpNameStr.length() != 0)
6330                // REVISIT: localize
6331
reportGenericSchemaError ( "attributeGroup " + attGrpNameStr + " cannot refer to another attributeGroup, but it refers to " + ref);
6332            if (child != null)
6333                // REVISIT: localize
6334
reportGenericSchemaError ( "An attributeGroup with \"ref\" present must be empty");
6335
6336            String JavaDoc prefix = "";
6337            String JavaDoc localpart = ref;
6338            int colonptr = ref.indexOf(":");
6339            if ( colonptr > 0) {
6340                prefix = ref.substring(0,colonptr);
6341                localpart = ref.substring(colonptr+1);
6342            }
6343            String JavaDoc uriStr = resolvePrefixToURI(prefix);
6344            if (!uriStr.equals(fTargetNSURIString)) {
6345
6346                traverseAttributeGroupDeclFromAnotherSchema(localpart, uriStr, typeInfo, anyAttDecls);
6347
6348                return -1;
6349                // TO DO
6350
// REVISIT: different NS, not supported yet.
6351
// REVISIT: Localize
6352
//reportGenericSchemaError("Feature not supported: see an attribute from different NS");
6353
} else {
6354                Element JavaDoc parent = (Element JavaDoc)attrGrpDecl.getParentNode();
6355                //if (parent.getLocalName().equals(SchemaSymbols.ELT_ATTRIBUTEGROUP) &&
6356
// parent.getAttribute(SchemaSymbols.ATT_NAME).equals(localpart)) {
6357
// Check if we are in the middle of traversing this attribute group (i.e. circular references)
6358
// ??? the spec only mentioned direct circular ref
6359
if (fCurrentAttrGroupNameStack.search(localpart) > - 1) {
6360                    if (!((Element JavaDoc)parent.getParentNode()).getLocalName().equals(SchemaSymbols.ELT_REDEFINE)) {
6361                        reportGenericSchemaError("src-attribute_group.3: Circular attribute group reference is disallowed outside <redefine> -- "+ref);
6362                    }
6363                    return -1;
6364                }
6365            }
6366
6367            if(typeInfo != null) {
6368                // only do this if we're traversing because we were ref'd here; when we come
6369
// upon this decl by itself we're just validating.
6370
Element JavaDoc referredAttrGrp = getTopLevelComponentByName(SchemaSymbols.ELT_ATTRIBUTEGROUP,localpart);
6371                if (referredAttrGrp != null) {
6372                    traverseAttributeGroupDecl(referredAttrGrp, typeInfo, anyAttDecls);
6373                }
6374                else {
6375                    // REVISIT: Localize
6376
reportGenericSchemaError ( "Couldn't find top level attributeGroup " + ref);
6377                }
6378                return -1;
6379            }
6380        } else if (attGrpNameStr.length() == 0)
6381                // REVISIT: localize
6382
reportGenericSchemaError ( "an attributeGroup must have a name or a ref attribute present");
6383
6384        fCurrentAttrGroupNameStack.push(attGrpNameStr);
6385
6386        for (;
6387             child != null ; child = XUtil.getNextSiblingElement(child)) {
6388
6389            if ( child.getLocalName().equals(SchemaSymbols.ELT_ATTRIBUTE) ){
6390                traverseAttributeDecl(child, typeInfo, false);
6391            }
6392            else if ( child.getLocalName().equals(SchemaSymbols.ELT_ATTRIBUTEGROUP) ) {
6393                NamespacesScope currScope = (NamespacesScope)fNamespacesScope.clone();
6394                // if(typeInfo != null)
6395
// only do this if we're traversing because we were ref'd here; when we come
6396
// upon this decl by itself we're just validating.
6397
traverseAttributeGroupDecl(child, typeInfo,anyAttDecls);
6398                fNamespacesScope = currScope;
6399            }
6400            else
6401                break;
6402        }
6403
6404        fCurrentAttrGroupNameStack.pop();
6405
6406        if (child != null) {
6407            if ( child.getLocalName().equals(SchemaSymbols.ELT_ANYATTRIBUTE) ) {
6408                if (anyAttDecls != null) {
6409                     anyAttDecls.addElement(traverseAnyAttribute(child));
6410                }
6411                if (XUtil.getNextSiblingElement(child) != null)
6412                    // REVISIT: localize
6413
reportGenericSchemaError ( "src-attribute_group.0: The content of an attributeGroup declaration must match (annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
6414                return -1;
6415            }
6416            else
6417                // REVISIT: localize
6418
reportGenericSchemaError ( "src-attribute_group.0: The content of an attributeGroup declaration must match (annotation?, ((attribute | attributeGroup)*, anyAttribute?))");
6419        }
6420        return -1;
6421    } // end of method traverseAttributeGroup
6422

6423    private int traverseAttributeGroupDeclFromAnotherSchema( String JavaDoc attGrpName , String JavaDoc uriStr,
6424                                                             ComplexTypeInfo typeInfo,
6425                                                             Vector JavaDoc anyAttDecls ) throws Exception JavaDoc {
6426
6427        Grammar grammar = fGrammarResolver.getGrammar(uriStr);
6428        if (uriStr == null || grammar == null || ! (grammar instanceof SchemaGrammar) ) {
6429            // REVISIT: Localize
6430
reportGenericSchemaError("!!Schema not found in #traverseAttributeGroupDeclFromAnotherSchema, schema uri : " + uriStr);
6431            return -1;
6432        }
6433        SchemaGrammar aGrammar = (SchemaGrammar)grammar;
6434
6435        // attribute name
6436
Element JavaDoc attGrpDecl = (Element JavaDoc) aGrammar.topLevelAttrGrpDecls.get((Object JavaDoc)attGrpName);
6437        if (attGrpDecl == null) {
6438            // REVISIT: Localize
6439
reportGenericSchemaError( "no attribute group named \"" + attGrpName
6440                                      + "\" was defined in schema : " + uriStr);
6441            return -1;
6442        }
6443
6444        NamespacesScope saveNSMapping = fNamespacesScope;
6445        int saveTargetNSUri = fTargetNSURI;
6446        fTargetNSURI = fStringPool.addSymbol(aGrammar.getTargetNamespaceURI());
6447        fNamespacesScope = aGrammar.getNamespacesScope();
6448
6449        // attribute type
6450
int attType = -1;
6451        int enumeration = -1;
6452
6453
6454        Element JavaDoc child = checkContent(attGrpDecl, XUtil.getFirstChildElement(attGrpDecl), true);
6455        for (;
6456             child != null ; child = XUtil.getNextSiblingElement(child)) {
6457
6458            //child attribute couldn't be a top-level attribute DEFINITION,
6459
if ( child.getLocalName().equals(SchemaSymbols.ELT_ATTRIBUTE) ){
6460                String JavaDoc childAttName = child.getAttribute(SchemaSymbols.ATT_NAME);
6461                if ( childAttName.length() > 0 ) {
6462                    Hashtable JavaDoc attDeclRegistry = aGrammar.getAttributeDeclRegistry();
6463                    if ((attDeclRegistry != null) &&
6464                            (attDeclRegistry.get((Object JavaDoc)childAttName) != null) ){
6465                        addAttributeDeclFromAnotherSchema(childAttName, uriStr, typeInfo);
6466                        fNamespacesScope = saveNSMapping;
6467                        fTargetNSURI = saveTargetNSUri;
6468                        return -1;
6469                    } else {
6470                        traverseAttributeDecl(child, typeInfo, false);
6471                    }
6472                }
6473                else
6474                    traverseAttributeDecl(child, typeInfo, false);
6475            }
6476            else if ( child.getLocalName().equals(SchemaSymbols.ELT_ATTRIBUTEGROUP) ) {
6477                traverseAttributeGroupDecl(child, typeInfo, anyAttDecls);
6478            }
6479            else if ( child.getLocalName().equals(SchemaSymbols.ELT_ANYATTRIBUTE) ) {
6480                anyAttDecls.addElement(traverseAnyAttribute(child));
6481                break;
6482            }
6483            else {
6484                // REVISIT: Localize
6485
reportGenericSchemaError("Invalid content for attributeGroup");
6486            }
6487        }
6488
6489        fNamespacesScope = saveNSMapping;
6490        fTargetNSURI = saveTargetNSUri;
6491        if(child != null) {
6492            // REVISIT: Localize
6493
reportGenericSchemaError("Invalid content for attributeGroup");
6494        }
6495        return -1;
6496    } // end of method traverseAttributeGroupFromAnotherSchema
6497

6498    // This simple method takes an attribute declaration as a parameter and
6499
// returns null if there is no simpleType defined or the simpleType
6500
// declaration if one exists. It also throws an error if more than one
6501
// <annotation> or <simpleType> group is present.
6502
private Element JavaDoc findAttributeSimpleType(Element JavaDoc attrDecl) throws Exception JavaDoc {
6503        Element JavaDoc child = checkContent(attrDecl, XUtil.getFirstChildElement(attrDecl), true);
6504        // if there is only a annotatoin, then no simpleType
6505
if (child == null)
6506            return null;
6507        // if the current one is not simpleType, or there are more elements,
6508
// report an error
6509
if (!child.getLocalName().equals(SchemaSymbols.ELT_SIMPLETYPE) ||
6510            XUtil.getNextSiblingElement(child) != null)
6511            //REVISIT: localize
6512
reportGenericSchemaError("src-attribute.0: the content must match (annotation?, (simpleType?)) -- attribute declaration '"+
6513                                     attrDecl.getAttribute(SchemaSymbols.ATT_NAME)+"'");
6514        if (child.getLocalName().equals(SchemaSymbols.ELT_SIMPLETYPE))
6515            return child;
6516            return null;
6517    } // end findAttributeSimpleType
6518

6519    /**
6520     * Traverse element declaration:
6521     * <element
6522     * abstract = boolean
6523     * block = #all or (possibly empty) subset of {substitutionGroup, extension, restriction}
6524     * default = string
6525     * substitutionGroup = QName
6526     * final = #all or (possibly empty) subset of {extension, restriction}
6527     * fixed = string
6528     * form = qualified | unqualified
6529     * id = ID
6530     * maxOccurs = string
6531     * minOccurs = nonNegativeInteger
6532     * name = NCName
6533     * nillable = boolean
6534     * ref = QName
6535     * type = QName>
6536     * Content: (annotation? , (simpleType | complexType)? , (unique | key | keyref)*)
6537     * </element>
6538     *
6539     *
6540     * The following are identity-constraint definitions
6541     * <unique
6542     * id = ID
6543     * name = NCName>
6544     * Content: (annotation? , (selector , field+))
6545     * </unique>
6546     *
6547     * <key
6548     * id = ID
6549     * name = NCName>
6550     * Content: (annotation? , (selector , field+))
6551     * </key>
6552     *
6553     * <keyref
6554     * id = ID
6555     * name = NCName
6556     * refer = QName>
6557     * Content: (annotation? , (selector , field+))
6558     * </keyref>
6559     *
6560     * <selector>
6561     * Content: XPathExprApprox : An XPath expression
6562     * </selector>
6563     *
6564     * <field>
6565     * Content: XPathExprApprox : An XPath expression
6566     * </field>
6567     *
6568     *
6569     * @param elementDecl
6570     * @return
6571     * @exception Exception
6572     */

6573    private QName traverseElementDecl(Element JavaDoc elementDecl) throws Exception JavaDoc {
6574
6575        // General Attribute Checking
6576
int scope = isTopLevel(elementDecl)?
6577                    GeneralAttrCheck.ELE_CONTEXT_GLOBAL:
6578                    GeneralAttrCheck.ELE_CONTEXT_LOCAL;
6579        Hashtable JavaDoc attrValues = generalCheck(elementDecl, scope);
6580
6581        int contentSpecType = -1;
6582        int contentSpecNodeIndex = -1;
6583        int typeNameIndex = -1;
6584        int scopeDefined = -2; //signal a error if -2 gets gets through
6585
//cause scope can never be -2.
6586
DatatypeValidator dv = null;
6587
6588        String JavaDoc abstractStr = elementDecl.getAttribute(SchemaSymbols.ATT_ABSTRACT);
6589        String JavaDoc blockStr = elementDecl.getAttribute(SchemaSymbols.ATT_BLOCK);
6590        String JavaDoc defaultStr = elementDecl.getAttribute(SchemaSymbols.ATT_DEFAULT);
6591        String JavaDoc finalStr = elementDecl.getAttribute(SchemaSymbols.ATT_FINAL);
6592        String JavaDoc fixedStr = elementDecl.getAttribute(SchemaSymbols.ATT_FIXED);
6593        String JavaDoc formStr = elementDecl.getAttribute(SchemaSymbols.ATT_FORM);
6594        String JavaDoc maxOccursStr = elementDecl.getAttribute(SchemaSymbols.ATT_MAXOCCURS);
6595        String JavaDoc minOccursStr = elementDecl.getAttribute(SchemaSymbols.ATT_MINOCCURS);
6596        String JavaDoc nameStr = elementDecl.getAttribute(SchemaSymbols.ATT_NAME);
6597        String JavaDoc nillableStr = elementDecl.getAttribute(SchemaSymbols.ATT_NILLABLE);
6598        String JavaDoc refStr = elementDecl.getAttribute(SchemaSymbols.ATT_REF);
6599        String JavaDoc substitutionGroupStr = elementDecl.getAttribute(SchemaSymbols.ATT_SUBSTITUTIONGROUP);
6600        String JavaDoc typeStr = elementDecl.getAttribute(SchemaSymbols.ATT_TYPE);
6601
6602        checkEnumerationRequiredNotation(nameStr, typeStr);
6603
6604        if ( DEBUGGING )
6605            System.out.println("traversing element decl : " + nameStr );
6606
6607        Attr JavaDoc abstractAtt = elementDecl.getAttributeNode(SchemaSymbols.ATT_ABSTRACT);
6608        Attr JavaDoc blockAtt = elementDecl.getAttributeNode(SchemaSymbols.ATT_BLOCK);
6609        Attr JavaDoc defaultAtt = elementDecl.getAttributeNode(SchemaSymbols.ATT_DEFAULT);
6610        Attr JavaDoc finalAtt = elementDecl.getAttributeNode(SchemaSymbols.ATT_FINAL);
6611        Attr JavaDoc fixedAtt = elementDecl.getAttributeNode(SchemaSymbols.ATT_FIXED);
6612        Attr JavaDoc formAtt = elementDecl.getAttributeNode(SchemaSymbols.ATT_FORM);
6613        Attr JavaDoc maxOccursAtt = elementDecl.getAttributeNode(SchemaSymbols.ATT_MAXOCCURS);
6614        Attr JavaDoc minOccursAtt = elementDecl.getAttributeNode(SchemaSymbols.ATT_MINOCCURS);
6615        Attr JavaDoc nameAtt = elementDecl.getAttributeNode(SchemaSymbols.ATT_NAME);
6616        Attr JavaDoc nillableAtt = elementDecl.getAttributeNode(SchemaSymbols.ATT_NILLABLE);
6617        Attr JavaDoc refAtt = elementDecl.getAttributeNode(SchemaSymbols.ATT_REF);
6618        Attr JavaDoc substitutionGroupAtt = elementDecl.getAttributeNode(SchemaSymbols.ATT_SUBSTITUTIONGROUP);
6619        Attr JavaDoc typeAtt = elementDecl.getAttributeNode(SchemaSymbols.ATT_TYPE);
6620
6621        if(defaultAtt != null && fixedAtt != null)
6622            // REVISIT: localize
6623
reportGenericSchemaError("src-element.1: an element cannot have both \"fixed\" and \"default\" present at the same time");
6624
6625        String JavaDoc fromAnotherSchema = null;
6626
6627        if (isTopLevel(elementDecl)) {
6628            if(nameAtt == null)
6629                // REVISIT: localize
6630
reportGenericSchemaError("globally-declared element must have a name");
6631            else if (refAtt != null)
6632                // REVISIT: localize
6633
reportGenericSchemaError("globally-declared element " + nameStr + " cannot have a ref attribute");
6634
6635            int nameIndex = fStringPool.addSymbol(nameStr);
6636            int eltKey = fSchemaGrammar.getElementDeclIndex(fTargetNSURI, nameIndex,TOP_LEVEL_SCOPE);
6637            if (eltKey > -1 ) {
6638                return new QName(-1,nameIndex,nameIndex,fTargetNSURI);
6639            }
6640        }
6641
6642        // parse out 'block', 'final', 'nillable', 'abstract'
6643
if (blockAtt == null)
6644            blockStr = null;
6645        int blockSet = parseBlockSet(blockStr);
6646        if( (blockStr != null) && blockStr.length() != 0 &&
6647                (!blockStr.equals(SchemaSymbols.ATTVAL_POUNDALL) &&
6648                (((blockSet & SchemaSymbols.RESTRICTION) == 0) &&
6649                (((blockSet & SchemaSymbols.EXTENSION) == 0) &&
6650                ((blockSet & SchemaSymbols.SUBSTITUTION) == 0)))))
6651            reportGenericSchemaError("The values of the 'block' attribute of an element must be either #all or a list of 'substitution', 'restriction' and 'extension'; " + blockStr + " was found");
6652        if (finalAtt == null)
6653            finalStr = null;
6654        int finalSet = parseFinalSet(finalStr);
6655        if( (finalStr != null) && finalStr.length() != 0 &&
6656                (!finalStr.equals(SchemaSymbols.ATTVAL_POUNDALL) &&
6657                (((finalSet & SchemaSymbols.RESTRICTION) == 0) &&
6658                ((finalSet & SchemaSymbols.EXTENSION) == 0))))
6659            reportGenericSchemaError("The values of the 'final' attribute of an element must be either #all or a list of 'restriction' and 'extension'; " + finalStr + " was found");
6660        boolean isNillable = nillableStr.equals(SchemaSymbols.ATTVAL_TRUE) || nillableStr.equals(SchemaSymbols.ATTVAL_TRUE_1);
6661        boolean isAbstract = abstractStr.equals(SchemaSymbols.ATTVAL_TRUE) || abstractStr.equals(SchemaSymbols.ATTVAL_TRUE_1);
6662        int elementMiscFlags = 0;
6663        if (isNillable) {
6664            elementMiscFlags += SchemaSymbols.NILLABLE;
6665        }
6666        if (isAbstract) {
6667            elementMiscFlags += SchemaSymbols.ABSTRACT;
6668        }
6669        // make the property of the element's value being fixed also appear in elementMiscFlags
6670
if(fixedAtt != null)
6671            elementMiscFlags += SchemaSymbols.FIXED;
6672
6673        //if this is a reference to a global element
6674
if (refAtt != null) {
6675            //REVISIT top level check for ref
6676
if (abstractAtt != null || blockAtt != null || defaultAtt != null ||
6677                finalAtt != null || fixedAtt != null || formAtt != null ||
6678                nillableAtt != null || substitutionGroupAtt != null || typeAtt != null)
6679                reportSchemaError(SchemaMessageProvider.BadAttWithRef, null); //src-element.2.2
6680
if (nameAtt != null)
6681                // REVISIT: Localize
6682
reportGenericSchemaError("src-element.2.1: element " + nameStr + " cannot also have a ref attribute");
6683
6684            Element JavaDoc child = XUtil.getFirstChildElement(elementDecl);
6685            if(child != null && child.getLocalName().equals(SchemaSymbols.ELT_ANNOTATION)) {
6686                if (XUtil.getNextSiblingElement(child) != null)
6687                    reportSchemaError(SchemaMessageProvider.NoContentForRef, null);
6688                else
6689                    traverseAnnotationDecl(child);
6690            }
6691            else if (child != null)
6692                reportSchemaError(SchemaMessageProvider.NoContentForRef, null);
6693            String JavaDoc prefix = "";
6694            String JavaDoc localpart = refStr;
6695            int colonptr = refStr.indexOf(":");
6696            if ( colonptr > 0) {
6697                prefix = refStr.substring(0,colonptr);
6698                localpart = refStr.substring(colonptr+1);
6699            }
6700            int localpartIndex = fStringPool.addSymbol(localpart);
6701            String JavaDoc uriString = resolvePrefixToURI(prefix);
6702            QName eltName = new QName(prefix != null ? fStringPool.addSymbol(prefix) : -1,
6703                                      localpartIndex,
6704                                      fStringPool.addSymbol(refStr),
6705                                      uriString != null ? fStringPool.addSymbol(uriString) : StringPool.EMPTY_STRING);
6706
6707            //if from another schema, just return the element QName
6708
if (! uriString.equals(fTargetNSURIString) ) {
6709                return eltName;
6710            }
6711
6712            int elementIndex = fSchemaGrammar.getElementDeclIndex(eltName, TOP_LEVEL_SCOPE);
6713            //if not found, traverse the top level element that if referenced
6714

6715            if (elementIndex == -1 ) {
6716                Element JavaDoc targetElement = getTopLevelComponentByName(SchemaSymbols.ELT_ELEMENT,localpart);
6717                if (targetElement == null ) {
6718                    // REVISIT: Localize
6719
reportGenericSchemaError("Element " + localpart + " not found in the Schema");
6720                    //REVISIT, for now, the QName anyway
6721
return eltName;
6722                    //return new QName(-1,fStringPool.addSymbol(localpart), -1, fStringPool.addSymbol(uriString));
6723
}
6724                else {
6725                    // Problem with recursive decls if we attempt the traversal now.
6726
//eltName= traverseElementDecl(targetElement);
6727

6728                }
6729            }
6730
6731
6732            if (fCurrentScope != TOP_LEVEL_SCOPE) {
6733               if (fFullConstraintChecking) {
6734                 // Add the name to a list of top-level elements we'll need to check later
6735
// for consistency wrt type
6736
fTopLevelElementsRefdFromGroup.addElement(eltName);
6737                 fTopLevelElementsRefdFromGroup.addElement(new Integer JavaDoc(fCurrentScope));
6738               }
6739
6740            }
6741
6742            return eltName;
6743        } else if (nameAtt == null)
6744            // REVISIT: Localize
6745
reportGenericSchemaError("src-element.2.1: a local element must have a name or a ref attribute present");
6746
6747
6748        // Handle the substitutionGroup
6749
Element JavaDoc substitutionGroupElementDecl = null;
6750        int substitutionGroupElementDeclIndex = -1;
6751        boolean noErrorSoFar = true;
6752
6753        //
6754
// resolving the type for this element right here
6755
//
6756

6757        ComplexTypeInfo typeInfo = null;
6758
6759        // element has a single child element, either a datatype or a type, null if primitive
6760
Element JavaDoc child = XUtil.getFirstChildElement(elementDecl);
6761
6762        if(child != null && child.getLocalName().equals(SchemaSymbols.ELT_ANNOTATION)) {
6763            traverseAnnotationDecl(child);
6764            child = XUtil.getNextSiblingElement(child);
6765        }
6766        if(child != null && child.getLocalName().equals(SchemaSymbols.ELT_ANNOTATION))
6767            // REVISIT: Localize
6768
reportGenericSchemaError("element declarations can contain at most one annotation Element Information Item");
6769
6770        boolean haveAnonType = false;
6771
6772        // Handle Anonymous type if there is one
6773
if (child != null) {
6774
6775            String JavaDoc childName = child.getLocalName();
6776
6777            if (childName.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
6778                if (child.getAttribute(SchemaSymbols.ATT_NAME).length() > 0) {
6779                    noErrorSoFar = false;
6780                    // REVISIT: Localize
6781
reportGenericSchemaError("anonymous complexType in element '" + nameStr +"' has a name attribute");
6782                }
6783
6784                else {
6785                    // Determine what the type name will be
6786
String JavaDoc anonTypeName = genAnonTypeName(child);
6787                    if (fCurrentTypeNameStack.search((Object JavaDoc)anonTypeName) > - 1) {
6788                        // A recursing element using an anonymous type
6789

6790                        int uriInd = StringPool.EMPTY_STRING;
6791                        if ( formStr.equals(SchemaSymbols.ATTVAL_QUALIFIED)||
6792                             fElementDefaultQualified) {
6793                             uriInd = fTargetNSURI;
6794                        }
6795                        int nameIndex = fStringPool.addSymbol(nameStr);
6796                        QName tempQName = new QName(-1, nameIndex, nameIndex, uriInd);
6797                        int eltIndex = fSchemaGrammar.addElementDecl(tempQName,
6798                              fCurrentScope, fCurrentScope, -1, -1, -1, null);
6799                        fElementRecurseComplex.addElement(new ElementInfo(eltIndex,anonTypeName));
6800                        return tempQName;
6801
6802                    }
6803                    else {
6804                        typeNameIndex = traverseComplexTypeDecl(child);
6805                        if (typeNameIndex != -1 ) {
6806                            typeInfo = (ComplexTypeInfo)
6807                                fComplexTypeRegistry.get(fStringPool.toString(typeNameIndex));
6808                        }
6809                        else {
6810                            noErrorSoFar = false;
6811                            // REVISIT: Localize
6812
reportGenericSchemaError("traverse complexType error in element '" + nameStr +"'");
6813                        }
6814                    }
6815                }
6816
6817                haveAnonType = true;
6818                child = XUtil.getNextSiblingElement(child);
6819            }
6820            else if (childName.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
6821                if (child.getAttribute(SchemaSymbols.ATT_NAME).length() > 0) {
6822                    noErrorSoFar = false;
6823                    // REVISIT: Localize
6824
reportGenericSchemaError("anonymous simpleType in element '" + nameStr +"' has a name attribute");
6825                }
6826                else
6827                    typeNameIndex = traverseSimpleTypeDecl(child);
6828                if (typeNameIndex != -1) {
6829                    dv = fDatatypeRegistry.getDatatypeValidator(fStringPool.toString(typeNameIndex));
6830                }
6831                else {
6832                    noErrorSoFar = false;
6833                    // REVISIT: Localize
6834
reportGenericSchemaError("traverse simpleType error in element '" + nameStr +"'");
6835                }
6836                contentSpecType = XMLElementDecl.TYPE_SIMPLE;
6837                haveAnonType = true;
6838                child = XUtil.getNextSiblingElement(child);
6839            } else if (typeAtt == null) { // "ur-typed" leaf
6840
contentSpecType = XMLElementDecl.TYPE_ANY;
6841                    //REVISIT: is this right?
6842
//contentSpecType = fStringPool.addSymbol("UR_TYPE");
6843
// set occurrence count
6844
contentSpecNodeIndex = -1;
6845            }
6846            // see if there's something here; it had better be key, keyref or unique.
6847
if (child != null)
6848                childName = child.getLocalName();
6849            while ((child != null) && ((childName.equals(SchemaSymbols.ELT_KEY))
6850                    || (childName.equals(SchemaSymbols.ELT_KEYREF))
6851                    || (childName.equals(SchemaSymbols.ELT_UNIQUE)))) {
6852                child = XUtil.getNextSiblingElement(child);
6853                if (child != null) {
6854                    childName = child.getLocalName();
6855                }
6856            }
6857            if (child != null) {
6858                // REVISIT: Localize
6859
noErrorSoFar = false;
6860                reportGenericSchemaError("src-element.0: the content of an element information item must match (annotation?, (simpleType | complexType)?, (unique | key | keyref)*)");
6861            }
6862        }
6863
6864        // handle type="" here
6865
if (haveAnonType && (typeAtt != null)) {
6866            noErrorSoFar = false;
6867            // REVISIT: Localize
6868
reportGenericSchemaError( "src-element.3: Element '"+ nameStr +
6869                                      "' have both a type attribute and a annoymous type child" );
6870        }
6871        // type specified as an attribute and no child is type decl.
6872
else if (typeAtt != null) {
6873            String JavaDoc prefix = "";
6874            String JavaDoc localpart = typeStr;
6875            int colonptr = typeStr.indexOf(":");
6876            if ( colonptr > 0) {
6877                prefix = typeStr.substring(0,colonptr);
6878                localpart = typeStr.substring(colonptr+1);
6879            }
6880            String JavaDoc typeURI = resolvePrefixToURI(prefix);
6881
6882            if (!(typeURI.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA) &&
6883                localpart.equals("anyType"))) {
6884                // check if the type is from the same Schema
6885
if ( !typeURI.equals(fTargetNSURIString)
6886                     && !typeURI.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)) {
6887                    fromAnotherSchema = typeURI;
6888                    typeInfo = getTypeInfoFromNS(typeURI, localpart);
6889                    if (typeInfo == null) {
6890                        dv = getTypeValidatorFromNS(typeURI, localpart);
6891                        if (dv == null) {
6892                            //TO DO: report error here;
6893
noErrorSoFar = false;
6894                            reportGenericSchemaError("Could not find type " +localpart
6895                                               + " in schema " + typeURI);
6896                        }
6897                    }
6898                }
6899                else {
6900                    typeInfo = (ComplexTypeInfo) fComplexTypeRegistry.get(typeURI+","+localpart);
6901                    if (typeInfo == null) {
6902                        dv = getDatatypeValidator(typeURI, localpart);
6903                        if (dv == null )
6904                        if (typeURI.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)
6905                            && !fTargetNSURIString.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA))
6906                        {
6907                            noErrorSoFar = false;
6908                            // REVISIT: Localize
6909
reportGenericSchemaError("type not found : " + typeURI+":"+localpart);
6910                        }
6911                        else {
6912                            Element JavaDoc topleveltype = getTopLevelComponentByName(SchemaSymbols.ELT_COMPLEXTYPE,localpart);
6913                            if (topleveltype != null) {
6914                                if (fCurrentTypeNameStack.search((Object JavaDoc)localpart) > - 1) {
6915                                    //then we found a recursive element using complexType.
6916
// REVISIT: this will be broken when recursing happens between 2 schemas
6917
int uriInd = StringPool.EMPTY_STRING;
6918                                    if ( formStr.equals(SchemaSymbols.ATTVAL_QUALIFIED)||
6919                                         fElementDefaultQualified) {
6920                                        uriInd = fTargetNSURI;
6921                                    }
6922                                    int nameIndex = fStringPool.addSymbol(nameStr);
6923                                    QName tempQName = new QName(-1, nameIndex, nameIndex, uriInd);
6924                                    int eltIndex = fSchemaGrammar.addElementDecl(tempQName,
6925                                            fCurrentScope, fCurrentScope, -1, -1, -1, null);
6926                                    fElementRecurseComplex.addElement(new ElementInfo(eltIndex,localpart));
6927                                    return tempQName;
6928                                }
6929                                else {
6930                                    // Squirrel away the baseTypeNameStack.
6931
Stack JavaDoc savedbaseNameStack = null;
6932                                    if (!fBaseTypeNameStack.isEmpty()) {
6933                                      savedbaseNameStack = fBaseTypeNameStack;
6934                                      fBaseTypeNameStack = new Stack JavaDoc();
6935                                    }
6936                                    typeNameIndex = traverseComplexTypeDecl( topleveltype, true );
6937                                    if (savedbaseNameStack != null)
6938                                        fBaseTypeNameStack = savedbaseNameStack;
6939                                    typeInfo = (ComplexTypeInfo)
6940                                        fComplexTypeRegistry.get(fStringPool.toString(typeNameIndex));
6941                                }
6942                            }
6943                            else {
6944                                topleveltype = getTopLevelComponentByName(SchemaSymbols.ELT_SIMPLETYPE, localpart);
6945                                if (topleveltype != null) {
6946                                    typeNameIndex = traverseSimpleTypeDecl( topleveltype );
6947                                    dv = getDatatypeValidator(typeURI, localpart);
6948                                }
6949                                else {
6950                                    noErrorSoFar = false;
6951                                    // REVISIT: Localize
6952
reportGenericSchemaError("type not found : " + typeURI+":"+localpart);
6953                                }
6954
6955                            }
6956
6957                        }
6958                    }
6959                }
6960            }
6961        }
6962        // now we need to make sure that our substitution (if any)
6963
// is valid, now that we have all the requisite type-related info.
6964
String JavaDoc substitutionGroupUri = null;
6965        String JavaDoc substitutionGroupLocalpart = null;
6966        String JavaDoc substitutionGroupFullName = null;
6967        ComplexTypeInfo substitutionGroupEltTypeInfo = null;
6968        DatatypeValidator substitutionGroupEltDV = null;
6969        SchemaGrammar subGrammar = fSchemaGrammar;
6970        boolean ignoreSub = false;
6971
6972        if ( substitutionGroupStr.length() > 0 ) {
6973            if(refAtt != null)
6974                // REVISIT: Localize
6975
reportGenericSchemaError("a local element cannot have a substitutionGroup");
6976            substitutionGroupUri = resolvePrefixToURI(getPrefix(substitutionGroupStr));
6977            substitutionGroupLocalpart = getLocalPart(substitutionGroupStr);
6978            substitutionGroupFullName = substitutionGroupUri+","+substitutionGroupLocalpart;
6979
6980            if ( !substitutionGroupUri.equals(fTargetNSURIString) ) {
6981                Grammar grammar = fGrammarResolver.getGrammar(substitutionGroupUri);
6982                if (grammar != null && grammar instanceof SchemaGrammar) {
6983                    subGrammar = (SchemaGrammar) grammar;
6984                    substitutionGroupElementDeclIndex = subGrammar.getElementDeclIndex(fStringPool.addSymbol(substitutionGroupUri),
6985                                                              fStringPool.addSymbol(substitutionGroupLocalpart),
6986                                                              TOP_LEVEL_SCOPE);
6987                    if (substitutionGroupElementDeclIndex<=-1) {
6988                        // REVISIT: localize
6989
noErrorSoFar = false;
6990                        reportGenericSchemaError("couldn't find substitutionGroup " + substitutionGroupLocalpart + " referenced by element " + nameStr
6991                                         + " in the SchemaGrammar "+substitutionGroupUri);
6992
6993                    } else {
6994                        substitutionGroupEltTypeInfo = getElementDeclTypeInfoFromNS(substitutionGroupUri, substitutionGroupLocalpart);
6995                        if (substitutionGroupEltTypeInfo == null) {
6996                            substitutionGroupEltDV = getElementDeclTypeValidatorFromNS(substitutionGroupUri, substitutionGroupLocalpart);
6997                            /*if (substitutionGroupEltDV == null) {
6998                                //TO DO: report error here;
6999                                noErrorSoFar = false;
7000                                reportGenericSchemaError("Could not find type for element '" +substitutionGroupLocalpart
7001                                                 + "' in schema '" + substitutionGroupUri+"'");
7002                            }*/

7003                        }
7004                    }
7005                } else {
7006                    // REVISIT: locallize
7007
noErrorSoFar = false;
7008                    reportGenericSchemaError("couldn't find a schema grammar with target namespace '" + substitutionGroupUri + "' for element '" + substitutionGroupStr + "'");
7009                }
7010            }
7011            else {
7012                substitutionGroupElementDecl = getTopLevelComponentByName(SchemaSymbols.ELT_ELEMENT, substitutionGroupLocalpart);
7013                if (substitutionGroupElementDecl == null) {
7014                    substitutionGroupElementDeclIndex =
7015                        fSchemaGrammar.getElementDeclIndex(fTargetNSURI, getLocalPartIndex(substitutionGroupStr),TOP_LEVEL_SCOPE);
7016                    if ( substitutionGroupElementDeclIndex == -1) {
7017                        noErrorSoFar = false;
7018                        // REVISIT: Localize
7019
reportGenericSchemaError("unable to locate substitutionGroup affiliation element "
7020                                                  +substitutionGroupStr
7021                                                  +" in element declaration "
7022                                                  +nameStr);
7023                    }
7024                }
7025                else {
7026                    substitutionGroupElementDeclIndex =
7027                        fSchemaGrammar.getElementDeclIndex(fTargetNSURI, getLocalPartIndex(substitutionGroupStr),TOP_LEVEL_SCOPE);
7028
7029                    if ( substitutionGroupElementDeclIndex == -1) {
7030                        // check for mutual recursion!
7031
if(fSubstitutionGroupRecursionRegistry.contains(fTargetNSURIString+","+substitutionGroupElementDecl.getAttribute(SchemaSymbols.ATT_NAME))) {
7032                            ignoreSub = true;
7033                        } else {
7034                            fSubstitutionGroupRecursionRegistry.addElement(fTargetNSURIString+","+substitutionGroupElementDecl.getAttribute(SchemaSymbols.ATT_NAME));
7035                            traverseElementDecl(substitutionGroupElementDecl);
7036                            substitutionGroupElementDeclIndex =
7037                                fSchemaGrammar.getElementDeclIndex(fTargetNSURI, getLocalPartIndex(substitutionGroupStr),TOP_LEVEL_SCOPE);
7038                            fSubstitutionGroupRecursionRegistry.removeElement((Object JavaDoc)fTargetNSURIString+","+substitutionGroupElementDecl.getAttribute(SchemaSymbols.ATT_NAME));
7039                        }
7040                    }
7041                }
7042
7043                if (!ignoreSub && substitutionGroupElementDeclIndex != -1) {
7044                    substitutionGroupEltTypeInfo = fSchemaGrammar.getElementComplexTypeInfo( substitutionGroupElementDeclIndex );
7045                    if (substitutionGroupEltTypeInfo == null) {
7046                        fSchemaGrammar.getElementDecl(substitutionGroupElementDeclIndex, fTempElementDecl);
7047                        substitutionGroupEltDV = fTempElementDecl.datatypeValidator;
7048                        /*if (substitutionGroupEltDV == null) {
7049                            //TO DO: report error here;
7050                            noErrorSoFar = false;
7051                            reportGenericSchemaError("Could not find type for element '" +substitutionGroupLocalpart
7052                                                     + "' in schema '" + substitutionGroupUri+"'");
7053                        }*/

7054                    }
7055                }
7056            }
7057            if (substitutionGroupElementDeclIndex <= -1)
7058                ignoreSub = true;
7059            if(!ignoreSub)
7060                checkSubstitutionGroupOK(elementDecl, substitutionGroupElementDecl, noErrorSoFar, substitutionGroupElementDeclIndex, subGrammar, typeInfo, substitutionGroupEltTypeInfo, dv, substitutionGroupEltDV);
7061        }
7062
7063        // this element is ur-type, check its substitutionGroup affiliation.
7064
// if there is substitutionGroup affiliation and not type definition found for this element,
7065
// then grab substitutionGroup affiliation's type and give it to this element
7066
if ( noErrorSoFar && typeInfo == null && dv == null ) {
7067            typeInfo = substitutionGroupEltTypeInfo;
7068            dv = substitutionGroupEltDV;
7069        }
7070
7071        boolean isAnyType = false;
7072        if (typeInfo == null && dv==null) {
7073            if (noErrorSoFar) {
7074                // Actually this Element's type definition is ur-type;
7075
isAnyType = true;
7076                contentSpecType = XMLElementDecl.TYPE_ANY;
7077            }
7078            else {
7079                noErrorSoFar = false;
7080                // REVISIT: Localize
7081
reportGenericSchemaError ("untyped element : " + nameStr );
7082            }
7083        }
7084
7085        // if element belongs to a compelx type
7086
if (typeInfo!=null) {
7087            contentSpecNodeIndex = typeInfo.contentSpecHandle;
7088            contentSpecType = typeInfo.contentType;
7089            scopeDefined = typeInfo.scopeDefined;
7090            dv = typeInfo.datatypeValidator;
7091        }
7092
7093        // if element belongs to a simple type
7094
if (dv!=null) {
7095            contentSpecType = XMLElementDecl.TYPE_SIMPLE;
7096            if (typeInfo == null) {
7097                fromAnotherSchema = null; // not to switch schema in this case
7098
}
7099        }
7100
7101        // Now we can handle validation etc. of default and fixed attributes,
7102
// since we finally have all the type information.
7103
if(fixedAtt != null) defaultStr = fixedStr;
7104        if(defaultStr.length() != 0) {
7105            if(typeInfo != null &&
7106                    (typeInfo.contentType != XMLElementDecl.TYPE_MIXED_SIMPLE &&
7107                     typeInfo.contentType != XMLElementDecl.TYPE_MIXED_COMPLEX &&
7108                    typeInfo.contentType != XMLElementDecl.TYPE_SIMPLE)) {
7109                // REVISIT: Localize
7110
reportGenericSchemaError ("e-props-correct.2.1: element " + nameStr + " has a fixed or default value and must have a mixed or simple content model");
7111            }
7112            if(typeInfo != null &&
7113               (typeInfo.contentType == XMLElementDecl.TYPE_MIXED_SIMPLE ||
7114                typeInfo.contentType == XMLElementDecl.TYPE_MIXED_COMPLEX)) {
7115                if (!particleEmptiable(typeInfo.contentSpecHandle))
7116                    reportGenericSchemaError ("e-props-correct.2.2.2: for element " + nameStr + ", the {content type} is mixed, then the {content type}'s particle must be emptiable");
7117            }
7118
7119            try {
7120                if(dv != null) {
7121                    dv.validate(defaultStr, null);
7122                }
7123            } catch (InvalidDatatypeValueException ide) {
7124                reportGenericSchemaError ("e-props-correct.2: invalid fixed or default value '" + defaultStr + "' in element " + nameStr);
7125            }
7126        }
7127
7128        if (defaultStr.length() != 0 &&
7129            dv != null && dv instanceof IDDatatypeValidator) {
7130            reportGenericSchemaError ("e-props-correct.4: If the {type definition} or {type definition}'s {content type} is or is derived from ID then there must not be a {value constraint} -- element " + nameStr);
7131        }
7132
7133        //
7134
// Create element decl
7135
//
7136

7137        int elementNameIndex = fStringPool.addSymbol(nameStr);
7138        int localpartIndex = elementNameIndex;
7139        int uriIndex = StringPool.EMPTY_STRING;
7140        int enclosingScope = fCurrentScope;
7141
7142        //refer to 4.3.2 in "XML Schema Part 1: Structures"
7143
if ( isTopLevel(elementDecl)) {
7144            uriIndex = fTargetNSURI;
7145            enclosingScope = TOP_LEVEL_SCOPE;
7146        }
7147        else if ( !formStr.equals(SchemaSymbols.ATTVAL_UNQUALIFIED) &&
7148                    (( formStr.equals(SchemaSymbols.ATTVAL_QUALIFIED)||
7149                        fElementDefaultQualified ))) {
7150
7151            uriIndex = fTargetNSURI;
7152        }
7153
7154        QName eltQName = new QName(-1,localpartIndex,elementNameIndex,uriIndex);
7155
7156        // Check if an element exists at this scope.
7157
// If it does, check it against the type of the new element
7158
int existingEltNdx = fSchemaGrammar.getElementDeclIndex(eltQName.uri,
7159                                                 eltQName.localpart,enclosingScope);
7160
7161        if (existingEltNdx > -1) {
7162          if (!checkDuplicateElementTypes(existingEltNdx,typeInfo,dv)) {
7163             noErrorSoFar = false;
7164
7165             reportGenericSchemaError("duplicate element decl in the same scope with different types : " +
7166                                      fStringPool.toString(localpartIndex));
7167
7168          }
7169        }
7170
7171        // add element decl to pool
7172

7173        int attrListHead = -1 ;
7174
7175        // copy up attribute decls from type object
7176
if (typeInfo != null) {
7177            attrListHead = typeInfo.attlistHead;
7178        }
7179        int elementIndex = fSchemaGrammar.addElementDecl(eltQName, enclosingScope, scopeDefined,
7180                                                         contentSpecType, contentSpecNodeIndex,
7181                                                         attrListHead, dv);
7182        // for anyType, we add an attribute wildcard for this element
7183
if (isAnyType) {
7184            fSchemaGrammar.addAttDef( elementIndex,
7185                                      // name
7186
new QName(),
7187                                      // type (namespace constaint)
7188
XMLAttributeDecl.TYPE_ANY_ANY,
7189                                      // enumeration (namespace list)
7190
-1,
7191                                      // defaultType (process contents)
7192
XMLAttributeDecl.PROCESSCONTENTS_STRICT,
7193                                      // defaultValue
7194
null,
7195                                      // datatypeValidator
7196
null,
7197                                      // list
7198
false);
7199        }
7200
7201        if ( DEBUGGING ) {
7202            /***/
7203            System.out.println("########elementIndex:"+elementIndex+" ("+fStringPool.toString(eltQName.uri)+","
7204                               + fStringPool.toString(eltQName.localpart) + ")"+
7205                               " eltType:"+typeStr+" contentSpecType:"+contentSpecType+
7206                               " SpecNodeIndex:"+ contentSpecNodeIndex +" enclosingScope: " +enclosingScope +
7207                               " scopeDefined: " +scopeDefined+"\n");
7208             /***/
7209        }
7210
7211        fSchemaGrammar.setElementComplexTypeInfo(elementIndex, typeInfo);
7212        // REVISIT: should we report error if typeInfo was null?
7213

7214        // mark element if its type belongs to different Schema.
7215
fSchemaGrammar.setElementFromAnotherSchemaURI(elementIndex, fromAnotherSchema);
7216
7217        // set BlockSet, FinalSet, Nillable and Abstract for this element decl
7218
fSchemaGrammar.setElementDeclBlockSet(elementIndex, blockSet);
7219        fSchemaGrammar.setElementDeclFinalSet(elementIndex, finalSet);
7220        fSchemaGrammar.setElementDeclMiscFlags(elementIndex, elementMiscFlags);
7221        fSchemaGrammar.setElementDefault(elementIndex, defaultStr);
7222
7223        // setSubstitutionGroupElementFullName
7224
fSchemaGrammar.setElementDeclSubstitutionGroupAffFullName(elementIndex, substitutionGroupFullName);
7225
7226        // substitutionGroup: double-direction
7227
if ( substitutionGroupStr.length() > 0 && !ignoreSub) {
7228            subGrammar.addElementDeclOneSubstitutionGroupQName(substitutionGroupElementDeclIndex, eltQName, fSchemaGrammar, elementIndex);
7229        }
7230
7231        //
7232
// key/keyref/unique processing
7233
//
7234

7235        Element JavaDoc ic = XUtil.getFirstChildElementNS(elementDecl, IDENTITY_CONSTRAINTS);
7236        if (ic != null) {
7237            Integer JavaDoc elementIndexObj = new Integer JavaDoc(elementIndex);
7238            Vector JavaDoc identityConstraints = (Vector JavaDoc)fIdentityConstraints.get(elementIndexObj);
7239            if (identityConstraints == null) {
7240                identityConstraints = new Vector JavaDoc();
7241                fIdentityConstraints.put(elementIndexObj, identityConstraints);
7242            }
7243            while (ic != null) {
7244                if (DEBUG_IC_DATATYPES) {
7245                    System.out.println("<ICD>: adding ic for later traversal: "+ic);
7246                }
7247                identityConstraints.addElement(ic);
7248                ic = XUtil.getNextSiblingElementNS(ic, IDENTITY_CONSTRAINTS);
7249            }
7250        }
7251
7252        return eltQName;
7253
7254    }// end of method traverseElementDecl(Element)
7255

7256    private boolean checkDuplicateElementTypes(int eltNdx, ComplexTypeInfo typeInfo,
7257                                       DatatypeValidator dv) {
7258
7259
7260        fSchemaGrammar.getElementDecl(eltNdx, fTempElementDecl);
7261        DatatypeValidator edv = fTempElementDecl.datatypeValidator;
7262        ComplexTypeInfo eTypeInfo = fSchemaGrammar.getElementComplexTypeInfo(eltNdx);
7263        if ( ((eTypeInfo != null)&&(eTypeInfo!=typeInfo))
7264             || ((edv != null)&&(edv != dv)) )
7265            return false;
7266        else
7267            return true;
7268
7269    }
7270
7271    private void traverseIdentityNameConstraintsFor(int elementIndex,
7272                                                Vector JavaDoc identityConstraints)
7273        throws Exception JavaDoc {
7274
7275        // iterate over identity constraints for this element
7276
int size = identityConstraints != null ? identityConstraints.size() : 0;
7277        if (size > 0) {
7278            // REVISIT: Use cached copy. -Ac
7279
XMLElementDecl edecl = new XMLElementDecl();
7280            fSchemaGrammar.getElementDecl(elementIndex, edecl);
7281            for (int i = 0; i < size; i++) {
7282                Element JavaDoc ic = (Element JavaDoc)identityConstraints.elementAt(i);
7283                String JavaDoc icName = ic.getLocalName();
7284                if ( icName.equals(SchemaSymbols.ELT_KEY) ) {
7285                    traverseKey(ic, edecl);
7286                }
7287                else if ( icName.equals(SchemaSymbols.ELT_UNIQUE) ) {
7288                    traverseUnique(ic, edecl);
7289                }
7290                fSchemaGrammar.setElementDecl(elementIndex, edecl);
7291
7292            } // loop over vector elements
7293

7294        } // if size > 0
7295

7296    } // traverseIdentityNameConstraints(Vector)
7297

7298    private void traverseIdentityRefConstraintsFor(int elementIndex,
7299                                                Vector JavaDoc identityConstraints)
7300        throws Exception JavaDoc {
7301
7302        // iterate over identity constraints for this element
7303
int size = identityConstraints != null ? identityConstraints.size() : 0;
7304        if (size > 0) {
7305            // REVISIT: Use cached copy. -Ac
7306
XMLElementDecl edecl = new XMLElementDecl();
7307            fSchemaGrammar.getElementDecl(elementIndex, edecl);
7308            for (int i = 0; i < size; i++) {
7309                Element JavaDoc ic = (Element JavaDoc)identityConstraints.elementAt(i);
7310                String JavaDoc icName = ic.getLocalName();
7311                if ( icName.equals(SchemaSymbols.ELT_KEYREF) ) {
7312                    traverseKeyRef(ic, edecl);
7313                }
7314                fSchemaGrammar.setElementDecl(elementIndex, edecl);
7315
7316            } // loop over vector elements
7317

7318        } // if size > 0
7319

7320    } // traverseIdentityRefConstraints(Vector)
7321

7322    private void traverseUnique(Element JavaDoc uElem, XMLElementDecl eDecl)
7323        throws Exception JavaDoc {
7324
7325        // General Attribute Checking
7326
int scope = GeneralAttrCheck.ELE_CONTEXT_LOCAL;
7327        Hashtable JavaDoc attrValues = generalCheck(uElem, scope);
7328
7329        // create identity constraint
7330
String JavaDoc uName = uElem.getAttribute(SchemaSymbols.ATT_NAME);
7331        if (DEBUG_IDENTITY_CONSTRAINTS) {
7332            System.out.println("<IC>: traverseUnique(\""+uElem.getNodeName()+"\") ["+uName+']');
7333        }
7334        String JavaDoc eName = getElementNameFor(uElem);
7335        Unique unique = new Unique(uName, eName);
7336        if(fIdentityConstraintNames.get(fTargetNSURIString+","+uName) != null) {
7337            reportGenericSchemaError("More than one identity constraint named " + uName);
7338        }
7339        fIdentityConstraintNames.put(fTargetNSURIString+","+uName, unique);
7340
7341        // get selector and fields
7342
traverseIdentityConstraint(unique, uElem);
7343
7344        // add to element decl
7345
eDecl.unique.addElement(unique);
7346
7347    } // traverseUnique(Element,XMLElementDecl)
7348

7349    private void traverseKey(Element JavaDoc kElem, XMLElementDecl eDecl)
7350        throws Exception JavaDoc {
7351
7352        // General Attribute Checking
7353
int scope = GeneralAttrCheck.ELE_CONTEXT_LOCAL;
7354        Hashtable JavaDoc attrValues = generalCheck(kElem, scope);
7355
7356        // create identity constraint
7357
String JavaDoc kName = kElem.getAttribute(SchemaSymbols.ATT_NAME);
7358        if (DEBUG_IDENTITY_CONSTRAINTS) {
7359            System.out.println("<IC>: traverseKey(\""+kElem.getNodeName()+"\") ["+kName+']');
7360        }
7361        String JavaDoc eName = getElementNameFor(kElem);
7362        Key key = new Key(kName, eName);
7363        if(fIdentityConstraintNames.get(fTargetNSURIString+","+kName) != null) {
7364            reportGenericSchemaError("More than one identity constraint named " + kName);
7365        }
7366        fIdentityConstraintNames.put(fTargetNSURIString+","+kName, key);
7367
7368        // get selector and fields
7369
traverseIdentityConstraint(key, kElem);
7370
7371        // add to element decl
7372
eDecl.key.addElement(key);
7373
7374    } // traverseKey(Element,XMLElementDecl)
7375

7376    private void traverseKeyRef(Element JavaDoc krElem, XMLElementDecl eDecl)
7377        throws Exception JavaDoc {
7378
7379        // General Attribute Checking
7380
int scope = GeneralAttrCheck.ELE_CONTEXT_LOCAL;
7381        Hashtable JavaDoc attrValues = generalCheck(krElem, scope);
7382
7383        // create identity constraint
7384
String JavaDoc krName = krElem.getAttribute(SchemaSymbols.ATT_NAME);
7385        String JavaDoc kName = krElem.getAttribute(SchemaSymbols.ATT_REFER);
7386        if (DEBUG_IDENTITY_CONSTRAINTS) {
7387            System.out.println("<IC>: traverseKeyRef(\""+krElem.getNodeName()+"\") ["+krName+','+kName+']');
7388        }
7389
7390        if(fIdentityConstraintNames.get(fTargetNSURIString+","+krName) != null) {
7391            reportGenericSchemaError("More than one identity constraint named " + krName);
7392        }
7393
7394        // verify that key reference "refer" attribute is valid
7395
String JavaDoc prefix = "";
7396        String JavaDoc localpart = kName;
7397        int colonptr = kName.indexOf(":");
7398        if ( colonptr > 0) {
7399            prefix = kName.substring(0,colonptr);
7400            localpart = kName.substring(colonptr+1);
7401        }
7402        String JavaDoc uriStr = resolvePrefixToURI(prefix);
7403        IdentityConstraint kId = (IdentityConstraint)fIdentityConstraintNames.get(uriStr+","+localpart);
7404        if (kId== null) {
7405            reportSchemaError(SchemaMessageProvider.KeyRefReferNotFound,
7406                              new Object JavaDoc[]{krName,kName});
7407            return;
7408        }
7409
7410        String JavaDoc eName = getElementNameFor(krElem);
7411        KeyRef keyRef = new KeyRef(krName, kId, eName);
7412
7413        // add to element decl
7414
traverseIdentityConstraint(keyRef, krElem);
7415        if(keyRef.getFieldCount() != kId.getFieldCount()){
7416                 reportSchemaError(SchemaMessageProvider.CardinalityNotEqual, new Object JavaDoc[]{krName,kName});
7417                 return ;
7418        }
7419
7420        // add key reference to element decl
7421
eDecl.keyRef.addElement(keyRef);
7422        // store in fIdentityConstraintNames so can flag schemas in which multiple
7423
// keyrefs with the same name are present.
7424
fIdentityConstraintNames.put(fTargetNSURIString+","+krName, keyRef);
7425
7426    } // traverseKeyRef(Element,XMLElementDecl)
7427

7428    private void traverseIdentityConstraint(IdentityConstraint ic,
7429                                            Element JavaDoc icElem) throws Exception JavaDoc {
7430
7431        // General Attribute Checking
7432
int scope = GeneralAttrCheck.ELE_CONTEXT_LOCAL;
7433        Hashtable JavaDoc attrValues = generalCheck(icElem, scope);
7434
7435        // check for <annotation> and get selector
7436
Element JavaDoc sElem = XUtil.getFirstChildElement(icElem);
7437        if(sElem == null) {
7438            // REVISIT: localize
7439
reportGenericSchemaError("The content of an identity constraint must match (annotation?, selector, field+)");
7440            return;
7441        }
7442        sElem = checkContent( icElem, sElem, false);
7443        // General Attribute Checking
7444
attrValues = generalCheck(sElem, scope);
7445
7446        if(!sElem.getLocalName().equals(SchemaSymbols.ELT_SELECTOR)) {
7447            // REVISIT: localize
7448
reportGenericSchemaError("The content of an identity constraint must match (annotation?, selector, field+)");
7449        }
7450        // and make sure <selector>'s content is fine:
7451
checkContent(icElem, XUtil.getFirstChildElement(sElem), true);
7452
7453        String JavaDoc sText = sElem.getAttribute(SchemaSymbols.ATT_XPATH);
7454        sText = sText.trim();
7455        Selector.XPath sXpath = null;
7456        try {
7457            // REVISIT: Must get ruling from XML Schema working group
7458
// regarding whether steps in the XPath must be
7459
// fully qualified if the grammar has a target
7460
// namespace. -Ac
7461
// RESOLUTION: Yes.
7462
sXpath = new Selector.XPath(sText, fStringPool,
7463                                        fNamespacesScope);
7464            Selector selector = new Selector(sXpath, ic);
7465            if (DEBUG_IDENTITY_CONSTRAINTS) {
7466                System.out.println("<IC>: selector: "+selector);
7467            }
7468            ic.setSelector(selector);
7469        }
7470        catch (XPathException e) {
7471            // REVISIT: Add error message.
7472
reportGenericSchemaError(e.getMessage());
7473            return;
7474        }
7475
7476        // get fields
7477
Element JavaDoc fElem = XUtil.getNextSiblingElement(sElem);
7478        if(fElem == null) {
7479            // REVISIT: localize
7480
reportGenericSchemaError("The content of an identity constraint must match (annotation?, selector, field+)");
7481        }
7482        while (fElem != null) {
7483            // General Attribute Checking
7484
attrValues = generalCheck(fElem, scope);
7485
7486            if(!fElem.getLocalName().equals(SchemaSymbols.ELT_FIELD))
7487                // REVISIT: localize
7488
reportGenericSchemaError("The content of an identity constraint must match (annotation?, selector, field+)");
7489            // and make sure <field>'s content is fine:
7490
checkContent(icElem, XUtil.getFirstChildElement(fElem), true);
7491            String JavaDoc fText = fElem.getAttribute(SchemaSymbols.ATT_XPATH);
7492            fText = fText.trim();
7493            try {
7494                // REVISIT: Must get ruling from XML Schema working group
7495
// regarding whether steps in the XPath must be
7496
// fully qualified if the grammar has a target
7497
// namespace. -Ac
7498
// RESOLUTION: Yes.
7499
Field.XPath fXpath = new Field.XPath(fText, fStringPool,
7500                                                     fNamespacesScope);
7501                // REVISIT: Get datatype validator. -Ac
7502
// cannot statically determine type of field; not just because of descendant/union
7503
// but because of <any> and <anyAttribute>. - NG
7504
// DatatypeValidator validator = getDatatypeValidatorFor(parent, sXpath, fXpath);
7505
// if (DEBUG_IC_DATATYPES) {
7506
// System.out.println("<ICD>: datatype validator: "+validator);
7507
// }
7508
// must find DatatypeValidator in the Validator...
7509
Field field = new Field(fXpath, ic);
7510                if (DEBUG_IDENTITY_CONSTRAINTS) {
7511                    System.out.println("<IC>: field: "+field);
7512                }
7513                ic.addField(field);
7514            }
7515            catch (XPathException e) {
7516                // REVISIT: Add error message.
7517
reportGenericSchemaError(e.getMessage());
7518                return;
7519            }
7520            fElem = XUtil.getNextSiblingElement(fElem);
7521        }
7522
7523    } // traverseIdentityConstraint(IdentityConstraint,Element)
7524

7525    /* This code is no longer used because datatypes can't be found statically for ID constraints.
7526    private DatatypeValidator getDatatypeValidatorFor(Element element,
7527                                                      Selector.XPath sxpath,
7528                                                      Field.XPath fxpath)
7529        throws Exception {
7530
7531        // variables
7532        String ename = element.getAttribute("name");
7533        if (DEBUG_IC_DATATYPES) {
7534            System.out.println("<ICD>: XMLValidator#getDatatypeValidatorFor("+
7535                               ename+','+sxpath+','+fxpath+')');
7536        }
7537        int localpart = fStringPool.addSymbol(ename);
7538        String targetNamespace = fSchemaRootElement.getAttribute("targetNamespace");
7539        int uri = fStringPool.addSymbol(targetNamespace);
7540        int edeclIndex = fSchemaGrammar.getElementDeclIndex(uri, localpart,
7541                                                            Grammar.TOP_LEVEL_SCOPE);
7542
7543        // walk selector
7544        XPath.LocationPath spath = sxpath.getLocationPath();
7545        XPath.Step[] ssteps = spath.steps;
7546        for (int i = 0; i < ssteps.length; i++) {
7547            XPath.Step step = ssteps[i];
7548            XPath.Axis axis = step.axis;
7549            XPath.NodeTest nodeTest = step.nodeTest;
7550            switch (axis.type) {
7551                case XPath.Axis.ATTRIBUTE: {
7552                    // REVISIT: Add message. -Ac
7553                    reportGenericSchemaError("not allowed to select attribute");
7554                    return null;
7555                }
7556                case XPath.Axis.CHILD: {
7557                    int index = fSchemaGrammar.getElementDeclIndex(nodeTest.name, edeclIndex);
7558                    if (index == -1) {
7559                        index = fSchemaGrammar.getElementDeclIndex(nodeTest.name, Grammar.TOP_LEVEL_SCOPE);
7560                    }
7561                    if (index == -1) {
7562                        // REVISIT: Add message. -Ac
7563                        reportGenericSchemaError("no such element \""+fStringPool.toString(nodeTest.name.rawname)+'"');
7564                        return null;
7565                    }
7566                    edeclIndex = index;
7567                    break;
7568                }
7569                case XPath.Axis.SELF: {
7570                    // no-op
7571                    break;
7572                }
7573                default: {
7574                    // REVISIT: Add message. -Ac
7575                    reportGenericSchemaError("invalid selector axis");
7576                    return null;
7577                }
7578            }
7579        }
7580
7581        // walk field
7582        XPath.LocationPath fpath = fxpath.getLocationPath();
7583        XPath.Step[] fsteps = fpath.steps;
7584        for (int i = 0; i < fsteps.length; i++) {
7585            XPath.Step step = fsteps[i];
7586            XPath.Axis axis = step.axis;
7587            XPath.NodeTest nodeTest = step.nodeTest;
7588            switch (axis.type) {
7589                case XPath.Axis.ATTRIBUTE: {
7590                    if (i != fsteps.length - 1) {
7591                        // REVISIT: Add message. -Ac
7592                        reportGenericSchemaError("attribute must be last step");
7593                        return null;
7594                    }
7595                    // look up validator
7596                    int adeclIndex = fSchemaGrammar.getAttributeDeclIndex(edeclIndex, nodeTest.name);
7597                    if (adeclIndex == -1) {
7598                        // REVISIT: Add message. -Ac
7599                        reportGenericSchemaError("no such attribute \""+fStringPool.toString(nodeTest.name.rawname)+'"');
7600                    }
7601                    XMLAttributeDecl adecl = new XMLAttributeDecl();
7602                    fSchemaGrammar.getAttributeDecl(adeclIndex, adecl);
7603                    DatatypeValidator validator = adecl.datatypeValidator;
7604                    return validator;
7605                }
7606                case XPath.Axis.CHILD: {
7607                    int index = fSchemaGrammar.getElementDeclIndex(nodeTest.name, edeclIndex);
7608                    if (index == -1) {
7609                        index = fSchemaGrammar.getElementDeclIndex(nodeTest.name, Grammar.TOP_LEVEL_SCOPE);
7610                    }
7611                    if (index == -1) {
7612                        // REVISIT: Add message. -Ac
7613                        reportGenericSchemaError("no such element \""+fStringPool.toString(nodeTest.name.rawname)+'"');
7614                        return null;
7615                    }
7616                    edeclIndex = index;
7617                    if (i < fsteps.length - 1) {
7618                        break;
7619                    }
7620                    // NOTE: Let fall through to self case so that we
7621                    // avoid duplicating code. -Ac
7622                }
7623                case XPath.Axis.SELF: {
7624                    // look up validator, if needed
7625                    if (i == fsteps.length - 1) {
7626                        XMLElementDecl edecl = new XMLElementDecl();
7627                        fSchemaGrammar.getElementDecl(edeclIndex, edecl);
7628                        if (edecl.type != XMLElementDecl.TYPE_SIMPLE) {
7629                            // REVISIT: Add message. -Ac
7630                            reportGenericSchemaError("selected element is not of simple type");
7631                            return null;
7632                        }
7633                        DatatypeValidator validator = edecl.datatypeValidator;
7634                        if (validator == null) validator = new StringDatatypeValidator();
7635                        return validator;
7636                    }
7637                    break;
7638                }
7639                default: {
7640                    // REVISIT: Add message. -Ac
7641                    reportGenericSchemaError("invalid selector axis");
7642                    return null;
7643                }
7644            }
7645        }
7646
7647        // no validator!
7648        // REVISIT: Add message. -Ac
7649        reportGenericSchemaError("No datatype validator for field "+fxpath+
7650                                 " of element "+ename);
7651        return null;
7652
7653    } // getDatatypeValidatorFor(XPath):DatatypeValidator
7654    */
// back in to live code...
7655

7656    private String JavaDoc getElementNameFor(Element JavaDoc icnode) {
7657        Element JavaDoc enode = (Element JavaDoc)icnode.getParentNode();
7658        String JavaDoc ename = enode.getAttribute("name");
7659        if (ename.length() == 0) {
7660            ename = enode.getAttribute("ref");
7661        }
7662        return ename;
7663    } // getElementNameFor(Element):String
7664

7665    int getLocalPartIndex(String JavaDoc fullName){
7666        int colonAt = fullName.indexOf(":");
7667        String JavaDoc localpart = fullName;
7668        if ( colonAt > -1 ) {
7669            localpart = fullName.substring(colonAt+1);
7670        }
7671        return fStringPool.addSymbol(localpart);
7672    }
7673
7674    String JavaDoc getLocalPart(String JavaDoc fullName){
7675        int colonAt = fullName.indexOf(":");
7676        String JavaDoc localpart = fullName;
7677        if ( colonAt > -1 ) {
7678            localpart = fullName.substring(colonAt+1);
7679        }
7680        return localpart;
7681    }
7682
7683    int getPrefixIndex(String JavaDoc fullName){
7684        int colonAt = fullName.indexOf(":");
7685        String JavaDoc prefix = "";
7686        if ( colonAt > -1 ) {
7687            prefix = fullName.substring(0,colonAt);
7688        }
7689        return fStringPool.addSymbol(prefix);
7690    }
7691
7692    String JavaDoc getPrefix(String JavaDoc fullName){
7693        int colonAt = fullName.indexOf(":");
7694        String JavaDoc prefix = "";
7695        if ( colonAt > -1 ) {
7696            prefix = fullName.substring(0,colonAt);
7697        }
7698        return prefix;
7699    }
7700
7701    private void checkSubstitutionGroupOK(Element JavaDoc elementDecl, Element JavaDoc substitutionGroupElementDecl,
7702            boolean noErrorSoFar, int substitutionGroupElementDeclIndex, SchemaGrammar substitutionGroupGrammar, ComplexTypeInfo typeInfo,
7703            ComplexTypeInfo substitutionGroupEltTypeInfo, DatatypeValidator dv,
7704            DatatypeValidator substitutionGroupEltDV) throws Exception JavaDoc {
7705
7706        // if final="#all" or final="extension restriction"
7707
// then it can't be substituted at all (according to 3.3.1)
7708
// ??? REVISIT: but it's not mentioned in 3.3.6, where it should be.
7709
int finalSet = substitutionGroupGrammar.getElementDeclFinalSet(substitutionGroupElementDeclIndex);
7710        if ((finalSet&SchemaSymbols.RESTRICTION) != 0 &&
7711            (finalSet&SchemaSymbols.EXTENSION) != 0) {
7712            reportGenericSchemaError("element " + elementDecl.getAttribute(SchemaSymbols.ATT_NAME)
7713                + " cannot be part of the substitution group headed by "
7714                + substitutionGroupElementDecl.getAttribute(SchemaSymbols.ATT_NAME));
7715        }
7716
7717        // here we must do two things:
7718
// 1. Make sure there actually *is* a relation between the types of
7719
// the element being nominated and the element doing the nominating;
7720
// (see PR 3.3.6 point #3 in the first tableau, for instance; this
7721
// and the corresponding tableaux from 3.4.6 and 3.14.6 rule out the nominated
7722
// element having an anonymous type declaration.
7723
// 2. Make sure the nominated element allows itself to be nominated by
7724
// an element with the given type-relation.
7725
// Note: we assume that (complex|simple)Type processing checks
7726
// whether the type in question allows itself to
7727
// be modified as this element desires.
7728

7729        // Check for type relationship;
7730
// that is, make sure that the type we're deriving has some relationship
7731
// to substitutionGroupElt's type.
7732
if (typeInfo != null) {
7733            // if the two types are the same, just return
7734
if (substitutionGroupEltTypeInfo == typeInfo)
7735                return;
7736            int derivationMethod = typeInfo.derivedBy;
7737            if(typeInfo.baseComplexTypeInfo == null) {
7738                if (typeInfo.baseDataTypeValidator != null) { // take care of complexType based on simpleType case...
7739
if (!checkSimpleTypeDerivationOK(typeInfo.baseDataTypeValidator,
7740                                                     substitutionGroupEltDV) &&
7741                        !(substitutionGroupEltTypeInfo == null &&
7742                          substitutionGroupEltDV == null)) {
7743                        // REVISIT: localize
7744
reportGenericSchemaError("Element " + elementDecl.getAttribute(SchemaSymbols.ATT_NAME) + " has a type which does not derive from the type of the element at the head of the substitution group");
7745                        noErrorSoFar = false;
7746                    } else { // now let's see if substitutionGroup element allows this:
7747
if((derivationMethod & finalSet) != 0) {
7748                            noErrorSoFar = false;
7749                            // REVISIT: localize
7750
reportGenericSchemaError("element " + elementDecl.getAttribute(SchemaSymbols.ATT_NAME)
7751                                + " cannot be part of the substitution group headed by "
7752                                + substitutionGroupElementDecl.getAttribute(SchemaSymbols.ATT_NAME));
7753                        }
7754                    }
7755                } else if (!(substitutionGroupEltTypeInfo == null &&
7756                             substitutionGroupEltDV == null)) {
7757                    // REVISIT: localize
7758
reportGenericSchemaError("Element " + elementDecl.getAttribute(SchemaSymbols.ATT_NAME) + " which is part of a substitution must have a type which derives from the type of the element at the head of the substitution group");
7759                    noErrorSoFar = false;
7760                }
7761            } else {
7762                ComplexTypeInfo subTypeInfo = typeInfo;
7763                for (; subTypeInfo != null && substitutionGroupEltTypeInfo != null && subTypeInfo != substitutionGroupEltTypeInfo; subTypeInfo = subTypeInfo.baseComplexTypeInfo);
7764                if (subTypeInfo == null ||
7765                    (substitutionGroupEltTypeInfo == null &&
7766                      substitutionGroupEltDV != null)) { // then this type isn't in the chain...
7767
// REVISIT: localize
7768
reportGenericSchemaError("Element " + elementDecl.getAttribute(SchemaSymbols.ATT_NAME) + " has a type which does not derive from the type of the element at the head of the substitution group");
7769                    noErrorSoFar = false;
7770                } else { // type is fine; does substitutionElement allow this?
7771
if((derivationMethod & finalSet) != 0) {
7772                        noErrorSoFar = false;
7773                        // REVISIT: localize
7774
reportGenericSchemaError("element " + elementDecl.getAttribute(SchemaSymbols.ATT_NAME)
7775                            + " cannot be part of the substitution group headed by "
7776                            + substitutionGroupElementDecl.getAttribute(SchemaSymbols.ATT_NAME));
7777                    }
7778                }
7779            }
7780        } else if (dv != null) { // do simpleType case...
7781
// if the two types are the same, just return
7782
if (dv == substitutionGroupEltDV)
7783                return;
7784            // first, check for type relation.
7785
if (!(checkSimpleTypeDerivationOK(dv,substitutionGroupEltDV)) &&
7786                !(substitutionGroupEltTypeInfo == null &&
7787                  substitutionGroupEltDV == null)) {
7788               // REVISIT: localize
7789
reportGenericSchemaError("Element " + elementDecl.getAttribute(SchemaSymbols.ATT_NAME) + " has a type which does not derive from the type of the element at the head of the substitution group");
7790               noErrorSoFar = false;
7791            }
7792            else { // now let's see if substitutionGroup element allows this:
7793
if((SchemaSymbols.RESTRICTION & finalSet) != 0) {
7794                    noErrorSoFar = false;
7795                    // REVISIT: localize
7796
reportGenericSchemaError("element " + elementDecl.getAttribute(SchemaSymbols.ATT_NAME)
7797                        + " cannot be part of the substitution group headed by "
7798                        + substitutionGroupElementDecl.getAttribute(SchemaSymbols.ATT_NAME));
7799                }
7800            }
7801        }
7802    }
7803
7804    //
7805
// A utility method to check whether a particular datatypevalidator d, was validly
7806
// derived from another datatypevalidator, b
7807
//
7808
private boolean checkSimpleTypeDerivationOK(DatatypeValidator d, DatatypeValidator b) {
7809       // if b is anySimpleType, then the derivation is OK.
7810
if (b instanceof AnySimpleType)
7811          return true;
7812
7813       DatatypeValidator dTemp = d;
7814       for(; dTemp != null; dTemp = dTemp.getBaseValidator()) {
7815           // WARNING!!! This uses comparison by reference andTemp is thus inherently suspect!
7816
if(dTemp == b) break;
7817       }
7818       if (dTemp == null) {
7819           // now if b is a union, then we can
7820
// derive from it if we derive from any of its members' types.
7821
if(b instanceof UnionDatatypeValidator) {
7822               // d must derive from one of its members...
7823
Vector JavaDoc subUnionMemberDV = ((UnionDatatypeValidator)b).getBaseValidators();
7824               int subUnionSize = subUnionMemberDV.size();
7825               boolean found = false;
7826               for (int i=0; i<subUnionSize && !found; i++) {
7827                   DatatypeValidator dTempSub = (DatatypeValidator)subUnionMemberDV.elementAt(i);
7828                   // if dTempSub is anySimpleType, then the derivation is OK.
7829
if (dTempSub instanceof AnySimpleType)
7830                      return true;
7831
7832                   DatatypeValidator dTempOrig = d;
7833                   for(; dTempOrig != null; dTempOrig = dTempOrig.getBaseValidator()) {
7834                       // WARNING!!! This uses comparison by reference andTemp is thus inherently suspect!
7835
if(dTempSub == dTempOrig) {
7836                           found = true;
7837                           break;
7838                       }
7839                   }
7840               }
7841               if(!found) {
7842                  return false;
7843               }
7844           } else {
7845               return false;
7846           }
7847       }
7848
7849    return true;
7850    }
7851
7852    // this originally-simple method is much -complicated by the fact that, when we're
7853
// redefining something, we've not only got to look at the space of the thing
7854
// we're redefining but at the original schema too.
7855
// The idea is to start from the top, then go down through
7856
// our list of schemas until we find what we aant.
7857
// This should not often be necessary, because we've processed
7858
// all redefined schemas, but three are conditions in which
7859
// not all elements so redefined may have been promoted to
7860
// the topmost level.
7861
private Element JavaDoc getTopLevelComponentByName(String JavaDoc componentCategory, String JavaDoc name) throws Exception JavaDoc {
7862        Element JavaDoc child = null;
7863        SchemaInfo curr = fSchemaInfoListRoot;
7864        for (; curr != null || curr == fSchemaInfoListRoot; curr = curr.getNext()) {
7865            if (curr != null) curr.restore();
7866            if ( componentCategory.equals(SchemaSymbols.ELT_GROUP) ) {
7867                child = (Element JavaDoc) fSchemaGrammar.topLevelGroupDecls.get(name);
7868            }
7869            else if ( componentCategory.equals(SchemaSymbols.ELT_ATTRIBUTEGROUP ) && fSchemaInfoListRoot == null ) {
7870                child = (Element JavaDoc) fSchemaGrammar.topLevelAttrGrpDecls.get(name);
7871            }
7872            else if ( componentCategory.equals(SchemaSymbols.ELT_ATTRIBUTE ) ) {
7873                child = (Element JavaDoc) fSchemaGrammar.topLevelAttrDecls.get(name);
7874            }
7875
7876            if (child != null ) {
7877                break;
7878            }
7879
7880            child = XUtil.getFirstChildElement(fSchemaRootElement);
7881
7882            if (child == null) {
7883                continue;
7884            }
7885
7886            while (child != null ){
7887                if ( child.getLocalName().equals(componentCategory)) {
7888                    if (child.getAttribute(SchemaSymbols.ATT_NAME).equals(name)) {
7889                        break;
7890                    }
7891                } else if (fRedefineSucceeded && child.getLocalName().equals(SchemaSymbols.ELT_REDEFINE)) {
7892                    Element JavaDoc gChild = XUtil.getFirstChildElement(child);
7893                    while (gChild != null ){
7894                        if (gChild.getLocalName().equals(componentCategory)) {
7895                            if (gChild.getAttribute(SchemaSymbols.ATT_NAME).equals(name)) {
7896                                break;
7897                            }
7898                        }
7899                        gChild = XUtil.getNextSiblingElement(gChild);
7900                    }
7901                    if (gChild != null) {
7902                        child = gChild;
7903                        break;
7904                    }
7905                }
7906                child = XUtil.getNextSiblingElement(child);
7907            }
7908            if (child != null || fSchemaInfoListRoot == null) break;
7909        }
7910        // have to reset fSchemaInfoList
7911
if(curr != null)
7912            curr.restore();
7913        else
7914            if (fSchemaInfoListRoot != null)
7915                fSchemaInfoListRoot.restore();
7916        return child;
7917    }
7918
7919    private boolean isTopLevel(Element JavaDoc component) {
7920        String JavaDoc parentName = component.getParentNode().getLocalName();
7921        return (parentName.endsWith(SchemaSymbols.ELT_SCHEMA))
7922            || (parentName.endsWith(SchemaSymbols.ELT_REDEFINE)) ;
7923    }
7924
7925    DatatypeValidator getTypeValidatorFromNS(String JavaDoc newSchemaURI, String JavaDoc localpart) throws Exception JavaDoc {
7926        // The following impl is for the case where every Schema Grammar has its own instance of DatatypeRegistry.
7927
// Now that we have only one DataTypeRegistry used by all schemas. this is not needed.
7928
/*****
7929        Grammar grammar = fGrammarResolver.getGrammar(newSchemaURI);
7930        if (grammar != null && grammar instanceof SchemaGrammar) {
7931            SchemaGrammar sGrammar = (SchemaGrammar) grammar;
7932            DatatypeValidator dv = (DatatypeValidator) fSchemaGrammar.getDatatypeRegistry().getDatatypeValidator(localpart);
7933            return dv;
7934        }
7935        else {
7936            reportGenericSchemaError("could not resolve URI : " + newSchemaURI + " to a SchemaGrammar in getTypeValidatorFromNS");
7937        }
7938        return null;
7939        /*****/

7940        return getDatatypeValidator(newSchemaURI, localpart);
7941    }
7942
7943    ComplexTypeInfo getTypeInfoFromNS(String JavaDoc newSchemaURI, String JavaDoc localpart) throws Exception JavaDoc {
7944        Grammar grammar = fGrammarResolver.getGrammar(newSchemaURI);
7945        if (grammar != null && grammar instanceof SchemaGrammar) {
7946            SchemaGrammar sGrammar = (SchemaGrammar) grammar;
7947            ComplexTypeInfo typeInfo = (ComplexTypeInfo) sGrammar.getComplexTypeRegistry().get(newSchemaURI+","+localpart);
7948            return typeInfo;
7949        }
7950        else {
7951            reportGenericSchemaError("could not resolve URI : " + newSchemaURI + " to a SchemaGrammar in getTypeInfoFromNS");
7952        }
7953        return null;
7954    }
7955
7956    DatatypeValidator getElementDeclTypeValidatorFromNS(String JavaDoc newSchemaURI, String JavaDoc localpart) throws Exception JavaDoc {
7957        Grammar grammar = fGrammarResolver.getGrammar(newSchemaURI);
7958        if (grammar != null && grammar instanceof SchemaGrammar) {
7959            SchemaGrammar sGrammar = (SchemaGrammar) grammar;
7960            int eltIndex = sGrammar.getElementDeclIndex(fStringPool.addSymbol(newSchemaURI),
7961                                                        fStringPool.addSymbol(localpart),
7962                                                        TOP_LEVEL_SCOPE);
7963
7964            DatatypeValidator dv = null;
7965            if (eltIndex>-1) {
7966                sGrammar.getElementDecl(eltIndex, fTempElementDecl);
7967                dv = fTempElementDecl.datatypeValidator;
7968            }
7969            else {
7970                reportGenericSchemaError("could not find global element : '" + localpart
7971                                         + " in the SchemaGrammar "+newSchemaURI);
7972            }
7973            return dv;
7974        }
7975        else {
7976            reportGenericSchemaError("could not resolve URI : " + newSchemaURI
7977                                      + " to a SchemaGrammar in getELementDeclTypeValidatorFromNS");
7978        }
7979        return null;
7980    }
7981
7982    ComplexTypeInfo getElementDeclTypeInfoFromNS(String JavaDoc newSchemaURI, String JavaDoc localpart) throws Exception JavaDoc {
7983        Grammar grammar = fGrammarResolver.getGrammar(newSchemaURI);
7984        if (grammar != null && grammar instanceof SchemaGrammar) {
7985            SchemaGrammar sGrammar = (SchemaGrammar) grammar;
7986            int eltIndex = sGrammar.getElementDeclIndex(fStringPool.addSymbol(newSchemaURI),
7987                                                              fStringPool.addSymbol(localpart),
7988                                                              TOP_LEVEL_SCOPE);
7989            ComplexTypeInfo typeInfo = null;
7990            if (eltIndex>-1) {
7991                 typeInfo = sGrammar.getElementComplexTypeInfo(eltIndex);
7992            }
7993            else {
7994                reportGenericSchemaError("could not find global element : '" + localpart
7995                                         + " in the SchemaGrammar "+newSchemaURI);
7996
7997            }
7998            return typeInfo;
7999        }
8000        else {
8001            reportGenericSchemaError("could not resolve URI : " + newSchemaURI
8002                                     + " to a SchemaGrammar in getElementDeclTypeInfoFromNS");
8003        }
8004        return null;
8005    }
8006
8007
8008
8009    /**
8010     * Traverses notation declaration
8011     * and saves it in a registry.
8012     * Notations are stored in registry with the following
8013     * key: "uri:localname"
8014     *
8015     * @param notation child <notation>
8016     * @return local name of notation
8017     * @exception Exception
8018     */

8019    private String JavaDoc traverseNotationDecl( Element JavaDoc notation ) throws Exception JavaDoc {
8020        // General Attribute Checking
8021
int scope = GeneralAttrCheck.ELE_CONTEXT_LOCAL;
8022        Hashtable JavaDoc attrValues = generalCheck(notation, scope);
8023
8024        String JavaDoc name = notation.getAttribute(SchemaSymbols.ATT_NAME);
8025        String JavaDoc qualifiedName =name;
8026        if (fTargetNSURIString.length () != 0) {
8027            qualifiedName = fTargetNSURIString+":"+name;
8028        }
8029        if (fNotationRegistry.get(qualifiedName)!=null) {
8030            return name;
8031        }
8032        String JavaDoc publicId = notation.getAttribute(SchemaSymbols.ATT_PUBLIC);
8033        String JavaDoc systemId = notation.getAttribute(SchemaSymbols.ATT_SYSTEM);
8034        if (publicId.length() == 0 && systemId.length() == 0) {
8035            //REVISIT: update error messages
8036
reportGenericSchemaError("<notation> declaration is invalid");
8037        }
8038        if (name.length() == 0) {
8039            //REVISIT: update error messages
8040
reportGenericSchemaError("<notation> declaration does not have a name");
8041
8042        }
8043
8044        fNotationRegistry.put(qualifiedName, name);
8045
8046        //we don't really care if something inside <notation> is wrong..
8047
checkContent( notation, XUtil.getFirstChildElement(notation), true );
8048
8049        //REVISIT: wait for DOM L3 APIs to pass info to application
8050
//REVISIT: SAX2 does not support notations. API should be changed.
8051
return name;
8052    }
8053
8054    /**
8055     * This methods will traverse notation from current schema,
8056     * as well as from included or imported schemas
8057     *
8058     * @param notationName
8059     * localName of notation
8060     * @param uriStr uriStr for schema grammar
8061     * @return return local name for Notation (if found), otherwise
8062     * return empty string;
8063     * @exception Exception
8064     */

8065    private String JavaDoc traverseNotationFromAnotherSchema( String JavaDoc notationName , String JavaDoc uriStr ) throws Exception JavaDoc {
8066
8067        Grammar grammar = fGrammarResolver.getGrammar(uriStr);
8068        if (uriStr == null || grammar==null ||! (grammar instanceof SchemaGrammar) ) {
8069            // REVISIT: Localize
8070
reportGenericSchemaError("!!Schema not found in #traverseNotationDeclFromAnotherSchema, "+
8071                                     "schema uri: " + uriStr
8072                                     +", groupName: " + notationName);
8073            return "";
8074        }
8075        SchemaGrammar aGrammar = (SchemaGrammar)grammar;
8076
8077        String JavaDoc savedNSURIString = fTargetNSURIString;
8078        fTargetNSURIString = fStringPool.toString(fStringPool.addSymbol(aGrammar.getTargetNamespaceURI()));
8079        if (DEBUGGING) {
8080            System.out.println("[traverseFromAnotherSchema]: " + fTargetNSURIString);
8081        }
8082
8083        String JavaDoc qualifiedName = fTargetNSURIString + ":" + notationName;
8084        String JavaDoc localName = (String JavaDoc)fNotationRegistry.get(qualifiedName);
8085
8086        if(localName != null ) // we've already traversed this notation
8087
return localName;
8088
8089        //notation decl has not been traversed yet
8090
Element JavaDoc notationDecl = (Element JavaDoc) aGrammar.topLevelNotationDecls.get((Object JavaDoc)notationName);
8091        if (notationDecl == null) {
8092            // REVISIT: Localize
8093
reportGenericSchemaError( "no notation named \"" + notationName
8094                                      + "\" was defined in schema : " + uriStr);
8095            return "";
8096        }
8097
8098        localName = traverseNotationDecl(notationDecl);
8099        fTargetNSURIString = savedNSURIString;
8100        return localName;
8101
8102    } // end of method traverseNotationFromAnotherSchema
8103

8104
8105    /**
8106     * Traverse Group Declaration.
8107     *
8108     * <group
8109     * id = ID
8110     * maxOccurs = string
8111     * minOccurs = nonNegativeInteger
8112     * name = NCName
8113     * ref = QName>
8114     * Content: (annotation? , (all | choice | sequence)?)
8115     * <group/>
8116     *
8117     * @param elementDecl
8118     * @return
8119     * @exception Exception
8120     */

8121    private GroupInfo traverseGroupDecl( Element JavaDoc groupDecl ) throws Exception JavaDoc {
8122
8123        // General Attribute Checking
8124
int scope = isTopLevel(groupDecl)?
8125                    GeneralAttrCheck.ELE_CONTEXT_GLOBAL:
8126                    GeneralAttrCheck.ELE_CONTEXT_LOCAL;
8127        Hashtable JavaDoc attrValues = generalCheck(groupDecl, scope);
8128
8129        String JavaDoc groupName = groupDecl.getAttribute(SchemaSymbols.ATT_NAME);
8130        String JavaDoc ref = groupDecl.getAttribute(SchemaSymbols.ATT_REF);
8131        GroupInfo gInfo = null;
8132    Element JavaDoc child = checkContent( groupDecl, XUtil.getFirstChildElement(groupDecl), true );
8133
8134        if (ref.length() != 0) {
8135            if (isTopLevel(groupDecl))
8136                // REVISIT: localize
8137
reportGenericSchemaError ( "A group with \"ref\" present must not have <schema> or <redefine> as its parent");
8138            if (groupName.length() != 0)
8139                // REVISIT: localize
8140
reportGenericSchemaError ( "group " + groupName + " cannot refer to another group, but it refers to " + ref);
8141
8142            // there should be no children for <group ref="...">
8143
if (XUtil.getFirstChildElement(groupDecl)!=null)
8144                reportGenericSchemaError ( "A group with \"ref\" present must not have children");
8145            String JavaDoc prefix = "";
8146            String JavaDoc localpart = ref;
8147            int colonptr = ref.indexOf(":");
8148            if ( colonptr > 0) {
8149                prefix = ref.substring(0,colonptr);
8150                localpart = ref.substring(colonptr+1);
8151            }
8152            int localpartIndex = fStringPool.addSymbol(localpart);
8153
8154            String JavaDoc uriStr = resolvePrefixToURI(prefix);
8155
8156            if (!uriStr.equals(fTargetNSURIString)) {
8157                gInfo = traverseGroupDeclFromAnotherSchema(localpart, uriStr);
8158                if (gInfo != null) {
8159                  if (DEBUG_NEW_GROUP)
8160                    findAndCreateElements(gInfo.contentSpecIndex,gInfo.scope);
8161                }
8162                return gInfo;
8163            }
8164
8165            try {
8166              gInfo = (GroupInfo) fGroupNameRegistry.get(uriStr + "," + localpart);
8167              if (gInfo != null) {
8168                // Ensure any LEAF elements are created at the
8169
// scope of the referencing type
8170
if (DEBUG_NEW_GROUP)
8171                  findAndCreateElements(gInfo.contentSpecIndex,gInfo.scope);
8172        return gInfo;
8173              }
8174
8175            }
8176            catch (ClassCastException JavaDoc c) {
8177            }
8178
8179
8180            // Check if we are in the middle of traversing this group (i.e. circular references)
8181
if (fCurrentGroupNameStack.search((Object JavaDoc)localpart) > - 1) {
8182                reportGenericSchemaError("mg-props-correct: Circular definition for group " + localpart);
8183                return null;
8184            }
8185
8186            int contentSpecIndex = -1;
8187            Element JavaDoc referredGroup = getTopLevelComponentByName(SchemaSymbols.ELT_GROUP,localpart);
8188            if (referredGroup == null) {
8189                // REVISIT: Localize
8190
reportGenericSchemaError("Group " + localpart + " not found in the Schema");
8191                //REVISIT, this should be some custom Exception
8192
//throw new RuntimeException("Group " + localpart + " not found in the Schema");
8193
}
8194            else {
8195                gInfo = traverseGroupDecl(referredGroup);
8196            }
8197
8198            // Now that we have a tree, ensure any LEAF elements are created at the
8199
// scope of the referencing type
8200
if (gInfo != null) {
8201               if (DEBUG_NEW_GROUP)
8202                 findAndCreateElements(gInfo.contentSpecIndex,gInfo.scope);
8203            }
8204            return gInfo;
8205
8206        } else if (groupName.length() == 0)
8207            // REVISIT: Localize
8208
reportGenericSchemaError("a <group> must have a name or a ref present");
8209
8210    String JavaDoc qualifiedGroupName = fTargetNSURIString + "," + groupName;
8211        try {
8212          gInfo = (GroupInfo) fGroupNameRegistry.get(qualifiedGroupName);
8213          if (gInfo != null) {
8214            // Ensure any LEAF elements are created at the
8215
// scope of the referencing type
8216
if (DEBUG_NEW_GROUP)
8217              findAndCreateElements(gInfo.contentSpecIndex,gInfo.scope);
8218        return gInfo;
8219          }
8220
8221        }
8222        catch (ClassCastException JavaDoc c) {
8223        }
8224
8225
8226    // if we're here then we're traversing a top-level group that we've never seen before.
8227
// Push the group name onto a stack, so that we can check for circular groups
8228
fCurrentGroupNameStack.push(groupName);
8229
8230        // Save the scope and set the current scope to -1
8231
int savedScope = fCurrentScope;
8232        if (DEBUG_NEW_GROUP)
8233           fCurrentScope = fScopeCount++;
8234        else
8235           fCurrentScope = -1;
8236
8237        int index = -2;
8238
8239        boolean illegalChild = false;
8240        String JavaDoc childName =
8241            (child != null) ? child.getLocalName() : "";
8242
8243        if (childName.equals(SchemaSymbols.ELT_ALL)) {
8244            index = traverseAll(child);
8245        }
8246        else if (childName.equals(SchemaSymbols.ELT_CHOICE)) {
8247            index = traverseChoice(child);
8248        }
8249        else if (childName.equals(SchemaSymbols.ELT_SEQUENCE)) {
8250            index = traverseSequence(child);
8251        }
8252        else if (childName.length() != 0 || (child != null && XUtil.getNextSiblingElement(child) != null)) {
8253            illegalChild = true;
8254            reportSchemaError(SchemaMessageProvider.GroupContentRestricted,
8255                              new Object JavaDoc [] { "group", childName });
8256        }
8257
8258        //Must have all or choice or sequence child.
8259
if (child == null) {
8260            reportGenericSchemaError("Named group must contain an 'all', 'choice' or 'sequence' child");
8261        }
8262        else if (XUtil.getNextSiblingElement(child) != null) {
8263            illegalChild = true;
8264            reportSchemaError(SchemaMessageProvider.GroupContentRestricted,
8265                              new Object JavaDoc [] { "group", childName });
8266        }
8267        if ( ! illegalChild && child != null) {
8268            index = handleOccurrences(index, child, CHILD_OF_GROUP);
8269        }
8270
8271    gInfo = new GroupInfo();
8272        gInfo.contentSpecIndex = index;
8273        gInfo.scope = fCurrentScope;
8274        fCurrentScope = savedScope;
8275        fCurrentGroupNameStack.pop();
8276    fGroupNameRegistry.put(qualifiedGroupName, gInfo);
8277        return gInfo;
8278    }
8279
8280    private void findAndCreateElements(int csIndex, int scope) {
8281
8282        if (csIndex<0 || fCurrentScope==TOP_LEVEL_SCOPE) {
8283           return;
8284        }
8285
8286        fSchemaGrammar.getContentSpec( csIndex, tempContentSpec1);
8287
8288        int type = tempContentSpec1.type;
8289        int left = tempContentSpec1.value;
8290        int right = tempContentSpec1.otherValue;
8291
8292        if (type == XMLContentSpec.CONTENTSPECNODE_LEAF) {
8293          int eltNdx = fSchemaGrammar.getElementDeclIndex(right, left, scope);
8294          if (eltNdx <0)
8295            return;
8296
8297          ComplexTypeInfo typeInfo = fSchemaGrammar.getElementComplexTypeInfo(eltNdx);
8298          int scopeDefined = typeInfo != null ? typeInfo.scopeDefined : fCurrentScope;
8299
8300          int newIdx = fSchemaGrammar.cloneElementDecl(eltNdx, fCurrentScope, scopeDefined);
8301
8302          // if the element being cloned is in fElementRecurseComplex,
8303
// which means it's inside a recursive declaration, we need to put
8304
// the cloned element in the vector too, so that its declaration
8305
// will be finished after we get all the type information - sgao
8306
int count = fElementRecurseComplex.size();
8307          for (int i = 0; i < count; i++) {
8308             ElementInfo eobj = (ElementInfo)fElementRecurseComplex.elementAt(i);
8309             if (eobj.elementIndex == eltNdx) {
8310                fElementRecurseComplex.addElement(new ElementInfo(newIdx,eobj.typeName));
8311                break;
8312             }
8313          }
8314        }
8315        else if (type == XMLContentSpec.CONTENTSPECNODE_CHOICE ||
8316                 type == XMLContentSpec.CONTENTSPECNODE_ALL ||
8317                 type == XMLContentSpec.CONTENTSPECNODE_SEQ) {
8318
8319          findAndCreateElements(left,scope);
8320
8321          if (right != -2)
8322             findAndCreateElements(right,scope);
8323        }
8324
8325    else if (type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_MORE
8326          || type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE
8327          || type == XMLContentSpec.CONTENTSPECNODE_ONE_OR_MORE) {
8328
8329          findAndCreateElements(left,scope);
8330    }
8331        return;
8332
8333    }
8334
8335    private GroupInfo traverseGroupDeclFromAnotherSchema( String JavaDoc groupName , String JavaDoc uriStr ) throws Exception JavaDoc {
8336
8337        GroupInfo gInfo = null;
8338        Grammar grammar = fGrammarResolver.getGrammar(uriStr);
8339        if (uriStr == null || grammar==null ||! (grammar instanceof SchemaGrammar) ) {
8340            // REVISIT: Localize
8341
reportGenericSchemaError("!!Schema not found in #traverseGroupDeclFromAnotherSchema, "+
8342                                     "schema uri: " + uriStr
8343                                     +", groupName: " + groupName);
8344            return null;
8345        }
8346        SchemaGrammar aGrammar = (SchemaGrammar)grammar;
8347
8348        Element JavaDoc groupDecl = (Element JavaDoc) aGrammar.topLevelGroupDecls.get((Object JavaDoc)groupName);
8349        if (groupDecl == null) {
8350            // REVISIT: Localize
8351
reportGenericSchemaError( "no group named \"" + groupName
8352                                      + "\" was defined in schema : " + uriStr);
8353            return null;
8354        }
8355
8356        NamespacesScope saveNSMapping = fNamespacesScope;
8357        int saveTargetNSUri = fTargetNSURI;
8358        fTargetNSURI = fStringPool.addSymbol(aGrammar.getTargetNamespaceURI());
8359        fNamespacesScope = aGrammar.getNamespacesScope();
8360
8361    Element JavaDoc child = checkContent( groupDecl, XUtil.getFirstChildElement(groupDecl), true );
8362
8363    String JavaDoc qualifiedGroupName = fTargetNSURIString + "," + groupName;
8364        try {
8365        gInfo = (GroupInfo) fGroupNameRegistry.get(qualifiedGroupName);
8366            if (gInfo != null)
8367              return gInfo;
8368        } catch (ClassCastException JavaDoc c) {
8369        }
8370
8371        // ------------------------------------
8372
// if we're here then we're traversing a top-level group that we've never seen before.
8373

8374        int index = -2;
8375        int savedScope = fCurrentScope;
8376        if (DEBUG_NEW_GROUP)
8377          fCurrentScope = fScopeCount++;
8378
8379        boolean illegalChild = false;
8380    String JavaDoc childName = (child != null) ? child.getLocalName() : "";
8381        if (childName.equals(SchemaSymbols.ELT_ALL)) {
8382            index = traverseAll(child);
8383        }
8384        else if (childName.equals(SchemaSymbols.ELT_CHOICE)) {
8385            index = traverseChoice(child);
8386        }
8387        else if (childName.equals(SchemaSymbols.ELT_SEQUENCE)) {
8388            index = traverseSequence(child);
8389        }
8390        else if (childName.length() != 0 || (child != null && XUtil.getNextSiblingElement(child) != null)) {
8391            illegalChild = true;
8392            reportSchemaError(SchemaMessageProvider.GroupContentRestricted,
8393                              new Object JavaDoc [] { "group", childName });
8394        }
8395        if ( ! illegalChild && child != null) {
8396            index = handleOccurrences( index, child);
8397        }
8398
8399    gInfo = new GroupInfo();
8400        gInfo.contentSpecIndex = index;
8401        gInfo.scope = fCurrentScope;
8402        fCurrentScope = savedScope;
8403    fGroupNameRegistry.put(qualifiedGroupName, gInfo);
8404    fNamespacesScope = saveNSMapping;
8405    fTargetNSURI = saveTargetNSUri;
8406        return gInfo;
8407
8408
8409    } // end of method traverseGroupDeclFromAnotherSchema
8410

8411    /**
8412    *
8413    * Traverse the Sequence declaration
8414    *
8415    * <sequence
8416    * id = ID
8417    * maxOccurs = string
8418    * minOccurs = nonNegativeInteger>
8419    * Content: (annotation? , (element | group | choice | sequence | any)*)
8420    * </sequence>
8421    *
8422    **/

8423    int traverseSequence (Element JavaDoc sequenceDecl) throws Exception JavaDoc {
8424        // General Attribute Checking
8425
int scope = GeneralAttrCheck.ELE_CONTEXT_LOCAL;
8426        Hashtable JavaDoc attrValues = generalCheck(sequenceDecl, scope);
8427
8428        Element JavaDoc child = checkContent(sequenceDecl, XUtil.getFirstChildElement(sequenceDecl), true);
8429
8430        int csnType = XMLContentSpec.CONTENTSPECNODE_SEQ;
8431
8432        int left = -2;
8433        int right = -2;
8434        boolean hadContent = false;
8435
8436        for (;
8437             child != null;
8438             child = XUtil.getNextSiblingElement(child)) {
8439            int index = -2;
8440
8441            boolean seeParticle = false;
8442            String JavaDoc childName = child.getLocalName();
8443            if (childName.equals(SchemaSymbols.ELT_ELEMENT)) {
8444                QName eltQName = traverseElementDecl(child);
8445                index = fSchemaGrammar.addContentSpecNode( XMLContentSpec.CONTENTSPECNODE_LEAF,
8446                                                       eltQName.localpart,
8447                                                       eltQName.uri,
8448                                                       false);
8449                seeParticle = true;
8450
8451            }
8452            else if (childName.equals(SchemaSymbols.ELT_GROUP)) {
8453                GroupInfo grpInfo = traverseGroupDecl(child);
8454                index = (grpInfo != null) ? grpInfo.contentSpecIndex:-2;
8455
8456                // A content type of all can only appear
8457
// as the content type of a complex type definition.
8458
if (hasAllContent(index)) {
8459                    reportSchemaError(SchemaMessageProvider.AllContentLimited,
8460                                      new Object JavaDoc [] { "sequence" });
8461                    continue;
8462                }
8463
8464                seeParticle = true;
8465
8466            }
8467            else if (childName.equals(SchemaSymbols.ELT_CHOICE)) {
8468                index = traverseChoice(child);
8469                seeParticle = true;
8470
8471            }
8472            else if (childName.equals(SchemaSymbols.ELT_SEQUENCE)) {
8473                index = traverseSequence(child);
8474                seeParticle = true;
8475
8476            }
8477            else if (childName.equals(SchemaSymbols.ELT_ANY)) {
8478                index = traverseAny(child);
8479                seeParticle = true;
8480            }
8481            else {
8482                reportSchemaError(
8483                             SchemaMessageProvider.SeqChoiceContentRestricted,
8484                             new Object JavaDoc [] { "sequence", childName });
8485                continue;
8486            }
8487
8488            if (index != -2)
8489                hadContent = true;
8490
8491            if (seeParticle) {
8492                index = handleOccurrences( index, child);
8493            }
8494            if (left == -2) {
8495                left = index;
8496            } else if (right == -2) {
8497                right = index;
8498            } else {
8499                left = fSchemaGrammar.addContentSpecNode(csnType, left, right, false);
8500                right = index;
8501            }
8502        }
8503
8504        if (hadContent) {
8505            if (right != -2 || fSchemaGrammar.getDeferContentSpecExpansion())
8506                left = fSchemaGrammar.addContentSpecNode(csnType, left, right,
8507                                                         false);
8508        }
8509
8510        return left;
8511    }
8512
8513    /**
8514    *
8515    * Traverse the Choice declaration
8516    *
8517    * <choice
8518    * id = ID
8519    * maxOccurs = string
8520    * minOccurs = nonNegativeInteger>
8521    * Content: (annotation? , (element | group | choice | sequence | any)*)
8522    * </choice>
8523    *
8524    **/

8525    int traverseChoice (Element JavaDoc choiceDecl) throws Exception JavaDoc {
8526        // General Attribute Checking
8527
int scope = GeneralAttrCheck.ELE_CONTEXT_LOCAL;
8528        Hashtable JavaDoc attrValues = generalCheck(choiceDecl, scope);
8529
8530        // REVISIT: traverseChoice, traverseSequence can be combined
8531
Element JavaDoc child = checkContent(choiceDecl, XUtil.getFirstChildElement(choiceDecl), true);
8532
8533        int csnType = XMLContentSpec.CONTENTSPECNODE_CHOICE;
8534
8535        int left = -2;
8536        int right = -2;
8537        boolean hadContent = false;
8538
8539        for (;
8540             child != null;
8541             child = XUtil.getNextSiblingElement(child)) {
8542            int index = -2;
8543
8544            boolean seeParticle = false;
8545            String JavaDoc childName = child.getLocalName();
8546            if (childName.equals(SchemaSymbols.ELT_ELEMENT)) {
8547                QName eltQName = traverseElementDecl(child);
8548                index = fSchemaGrammar.addContentSpecNode( XMLContentSpec.CONTENTSPECNODE_LEAF,
8549                                                       eltQName.localpart,
8550                                                       eltQName.uri,
8551                                                       false);
8552                seeParticle = true;
8553
8554            }
8555            else if (childName.equals(SchemaSymbols.ELT_GROUP)) {
8556                GroupInfo grpInfo = traverseGroupDecl(child);
8557                index = (grpInfo != null) ? grpInfo.contentSpecIndex:-2;
8558
8559                // A model group whose {compositor} is "all" can only appear
8560
// as the {content type} of a complex type definition.
8561
if (hasAllContent(index)) {
8562                    reportSchemaError(SchemaMessageProvider.AllContentLimited,
8563                                      new Object JavaDoc [] { "choice" });
8564                    continue;
8565                }
8566
8567                seeParticle = true;
8568
8569            }
8570            else if (childName.equals(SchemaSymbols.ELT_CHOICE)) {
8571                index = traverseChoice(child);
8572                seeParticle = true;
8573
8574            }
8575            else if (childName.equals(SchemaSymbols.ELT_SEQUENCE)) {
8576                index = traverseSequence(child);
8577                seeParticle = true;
8578
8579            }
8580            else if (childName.equals(SchemaSymbols.ELT_ANY)) {
8581                index = traverseAny(child);
8582                seeParticle = true;
8583            }
8584            else {
8585                reportSchemaError(
8586                              SchemaMessageProvider.SeqChoiceContentRestricted,
8587                              new Object JavaDoc [] { "choice", childName });
8588                continue;
8589            }
8590
8591            if (index != -2)
8592                hadContent = true;
8593
8594            if (seeParticle) {
8595                index = handleOccurrences( index, child);
8596            }
8597
8598            if (left == -2) {
8599                left = index;
8600            } else if (right == -2) {
8601                right = index;
8602            } else {
8603                left = fSchemaGrammar.addContentSpecNode(csnType, left, right, false);
8604                right = index;
8605            }
8606        }
8607
8608
8609        if (hadContent) {
8610            if (right != -2 || fSchemaGrammar.getDeferContentSpecExpansion())
8611                left = fSchemaGrammar.addContentSpecNode(csnType, left, right,
8612                                                         false);
8613        }
8614        return left;
8615    }
8616
8617
8618   /**
8619    *
8620    * Traverse the "All" declaration
8621    *
8622    * <all
8623    * id = ID
8624    * maxOccurs = 1 : 1
8625    * minOccurs = (0 | 1) : 1>
8626    * Content: (annotation? , element*)
8627    * </all>
8628    **/

8629
8630    int traverseAll(Element JavaDoc allDecl) throws Exception JavaDoc {
8631        // General Attribute Checking
8632
int scope = GeneralAttrCheck.ELE_CONTEXT_LOCAL;
8633        Hashtable JavaDoc attrValues = generalCheck(allDecl, scope);
8634
8635        Element JavaDoc child = checkContent(allDecl,
8636                                     XUtil.getFirstChildElement(allDecl), true);
8637
8638        int csnType = XMLContentSpec.CONTENTSPECNODE_ALL;
8639
8640        int left = -2;
8641        int right = -2;
8642        boolean hadContent = false;
8643
8644        for (;
8645             child != null;
8646             child = XUtil.getNextSiblingElement(child)) {
8647            int index = -2;
8648
8649            String JavaDoc childName = child.getLocalName();
8650
8651            // Only elements are allowed in <all>
8652
if (childName.equals(SchemaSymbols.ELT_ELEMENT)) {
8653                QName eltQName = traverseElementDecl(child);
8654                index = fSchemaGrammar.addContentSpecNode(
8655                                           XMLContentSpec.CONTENTSPECNODE_LEAF,
8656                                           eltQName.localpart,
8657                                           eltQName.uri,
8658                                           false);
8659
8660                index = handleOccurrences(index, child, PROCESSING_ALL_EL);
8661            }
8662            else {
8663                reportSchemaError(SchemaMessageProvider.AllContentRestricted,
8664                                  new Object JavaDoc [] { childName });
8665                continue;
8666            }
8667
8668            hadContent = true;
8669
8670            if (left == -2) {
8671                left = index;
8672            } else if (right == -2) {
8673                right = index;
8674            } else {
8675                left = fSchemaGrammar.addContentSpecNode(csnType, left, right,
8676                                                         false);
8677                right = index;
8678            }
8679        }
8680
8681        if (hadContent) {
8682            if (right != -2 || fSchemaGrammar.getDeferContentSpecExpansion())
8683                left = fSchemaGrammar.addContentSpecNode(csnType, left, right,
8684                                                         false);
8685        }
8686
8687        return left;
8688    }
8689
8690    // Determines whether a content spec tree represents an "all" content model
8691
private boolean hasAllContent(int contentSpecIndex) {
8692        // If the content is not empty, is the top node ALL?
8693
if (contentSpecIndex > -1) {
8694            XMLContentSpec content = new XMLContentSpec();
8695            fSchemaGrammar.getContentSpec(contentSpecIndex, content);
8696
8697            // An ALL node could be optional, so we have to be prepared
8698
// to look one level below a ZERO_OR_ONE node for an ALL.
8699
if (content.type == XMLContentSpec.CONTENTSPECNODE_ZERO_OR_ONE) {
8700                fSchemaGrammar.getContentSpec(content.value, content);
8701            }
8702
8703            return (content.type == XMLContentSpec.CONTENTSPECNODE_ALL);
8704        }
8705
8706        return false;
8707    }
8708
8709    // check the prefix of each element: must be SchemaForSchema
8710
// general constrain checking on attriubtes
8711
private Hashtable JavaDoc generalCheck(Element JavaDoc element, int scope) throws Exception JavaDoc{
8712        String JavaDoc uri = element.getNamespaceURI();
8713        if (uri == null || !uri.equals(SchemaSymbols.URI_SCHEMAFORSCHEMA)) {
8714            reportGenericSchemaError("The namespce name for '"+element.getLocalName()+"' must be "+SchemaSymbols.URI_SCHEMAFORSCHEMA);
8715        }
8716        return fGeneralAttrCheck.checkAttributes (element, scope);
8717    }
8718
8719    // utilities from Tom Watson's SchemaParser class
8720
// TO DO: Need to make this more conformant with Schema int type parsing
8721

8722    private int parseInt (String JavaDoc intString) throws Exception JavaDoc
8723    {
8724            if ( intString.equals("*") ) {
8725                    return SchemaSymbols.INFINITY;
8726            } else {
8727                    return Integer.parseInt (intString);
8728            }
8729    }
8730
8731
8732    private int parseSimpleFinal (String JavaDoc finalString) throws Exception JavaDoc
8733    {
8734            if ( finalString.equals (SchemaSymbols.ATTVAL_POUNDALL) ) {
8735                    return SchemaSymbols.ENUMERATION+SchemaSymbols.RESTRICTION+SchemaSymbols.LIST;
8736            } else {
8737                    int enumerate = 0;
8738                    int restrict = 0;
8739                    int list = 0;
8740
8741                    StringTokenizer JavaDoc t = new StringTokenizer JavaDoc (finalString, " ");
8742                    while (t.hasMoreTokens()) {
8743                            String JavaDoc token = t.nextToken ();
8744
8745                            if ( token.equals (SchemaSymbols.ATTVAL_RESTRICTION) ) {
8746                                    if ( restrict == 0 ) {
8747                                            restrict = SchemaSymbols.RESTRICTION;
8748                                    } else {
8749                                        // REVISIT: Localize
8750
reportGenericSchemaError ("restriction in set twice");
8751                                    }
8752                            } else if ( token.equals (SchemaSymbols.ELT_LIST) ) {
8753                                    if ( list == 0 ) {
8754                                            list = SchemaSymbols.LIST;
8755                                    } else {
8756                                        // REVISIT: Localize
8757
reportGenericSchemaError ("list in set twice");
8758                                    }
8759                            }
8760                            else {
8761                                // REVISIT: Localize
8762
reportGenericSchemaError ( "Invalid value (" +
8763                                                            finalString +
8764                                                            ")" );
8765                            }
8766                    }
8767
8768                    return enumerate+list;
8769            }
8770    }
8771
8772
8773    private int parseDerivationSet (String JavaDoc finalString) throws Exception JavaDoc
8774    {
8775            if ( finalString.equals (SchemaSymbols.ATTVAL_POUNDALL) ) {
8776                    return SchemaSymbols.EXTENSION+SchemaSymbols.RESTRICTION;
8777            } else {
8778                    int extend = 0;
8779                    int restrict = 0;
8780
8781                    StringTokenizer JavaDoc t = new StringTokenizer JavaDoc (finalString, " ");
8782                    while (t.hasMoreTokens()) {
8783                            String JavaDoc token = t.nextToken ();
8784
8785                            if ( token.equals (SchemaSymbols.ATTVAL_EXTENSION) ) {
8786                                    if ( extend == 0 ) {
8787                                            extend = SchemaSymbols.EXTENSION;
8788                                    } else {
8789                                        // REVISIT: Localize
8790
reportGenericSchemaError ( "extension already in set" );
8791                                    }
8792                            } else if ( token.equals (SchemaSymbols.ATTVAL_RESTRICTION) ) {
8793                                    if ( restrict == 0 ) {
8794                                            restrict = SchemaSymbols.RESTRICTION;
8795                                    } else {
8796                                        // REVISIT: Localize
8797
reportGenericSchemaError ( "restriction already in set" );
8798                                    }
8799                            } else {
8800                                // REVISIT: Localize
8801
reportGenericSchemaError ( "Invalid final value (" + finalString + ")" );
8802                            }
8803                    }
8804
8805                    return extend+restrict;
8806            }
8807    }
8808
8809    private int parseBlockSet (String JavaDoc blockString) throws Exception JavaDoc
8810    {
8811            if( blockString == null)
8812                return fBlockDefault;
8813            else if ( blockString.equals (SchemaSymbols.ATTVAL_POUNDALL) ) {
8814                    return SchemaSymbols.SUBSTITUTION+SchemaSymbols.EXTENSION+SchemaSymbols.RESTRICTION;
8815            } else {
8816                    int extend = 0;
8817                    int restrict = 0;
8818                    int substitute = 0;
8819
8820                    StringTokenizer JavaDoc t = new StringTokenizer JavaDoc (blockString, " ");
8821                    while (t.hasMoreTokens()) {
8822                            String JavaDoc token = t.nextToken ();
8823
8824                            if ( token.equals (SchemaSymbols.ATTVAL_SUBSTITUTION) ) {
8825                                    if ( substitute == 0 ) {
8826                                            substitute = SchemaSymbols.SUBSTITUTION;
8827                                    } else {
8828                                        // REVISIT: Localize
8829
reportGenericSchemaError ( "The value 'substitution' already in the list" );
8830                                    }
8831                            } else if ( token.equals (SchemaSymbols.ATTVAL_EXTENSION) ) {
8832                                    if ( extend == 0 ) {
8833                                            extend = SchemaSymbols.EXTENSION;
8834                                    } else {
8835                                        // REVISIT: Localize
8836
reportGenericSchemaError ( "The value 'extension' is already in the list" );
8837                                    }
8838                            } else if ( token.equals (SchemaSymbols.ATTVAL_RESTRICTION) ) {
8839                                    if ( restrict == 0 ) {
8840                                            restrict = SchemaSymbols.RESTRICTION;
8841                                    } else {
8842                                        // REVISIT: Localize
8843
reportGenericSchemaError ( "The value 'restriction' is already in the list" );
8844                                    }
8845                            } else {
8846                                // REVISIT: Localize
8847
reportGenericSchemaError ( "Invalid block value (" + blockString + ")" );
8848                            }
8849                    }
8850
8851                    int defaultVal = extend+restrict+substitute;
8852                    return (defaultVal == 0 ? fBlockDefault : defaultVal);
8853            }
8854    }
8855
8856    private int parseFinalSet (String JavaDoc finalString) throws Exception JavaDoc
8857    {
8858            if( finalString == null) {
8859                return fFinalDefault;
8860            }
8861            else if ( finalString.equals (SchemaSymbols.ATTVAL_POUNDALL) ) {
8862                    return SchemaSymbols.EXTENSION+SchemaSymbols.LIST+SchemaSymbols.RESTRICTION+SchemaSymbols.UNION;
8863            } else {
8864                    int extend = 0;
8865                    int restrict = 0;
8866                    int list = 0;
8867                    int union = 0;
8868
8869                    StringTokenizer JavaDoc t = new StringTokenizer JavaDoc (finalString, " ");
8870                    while (t.hasMoreTokens()) {
8871                            String JavaDoc token = t.nextToken ();
8872
8873                            if ( token.equals (SchemaSymbols.ELT_UNION) ) {
8874                                    if ( union == 0 ) {
8875                                            union = SchemaSymbols.UNION;
8876                                    } else {
8877                                        // REVISIT: Localize
8878
reportGenericSchemaError ( "The value 'union' is already in the list" );
8879                                    }
8880                            } else if ( token.equals (SchemaSymbols.ATTVAL_EXTENSION) ) {
8881                                    if ( extend == 0 ) {
8882                                            extend = SchemaSymbols.EXTENSION;
8883                                    } else {
8884                                        // REVISIT: Localize
8885
reportGenericSchemaError ( "The value 'extension' is already in the list" );
8886                                    }
8887                            } else if ( token.equals (SchemaSymbols.ELT_LIST) ) {
8888                                    if ( list == 0 ) {
8889                                            list = SchemaSymbols.LIST;
8890                                    } else {
8891                                        // REVISIT: Localize
8892
reportGenericSchemaError ( "The value 'list' is already in the list" );
8893                                    }
8894                            } else if ( token.equals (SchemaSymbols.ATTVAL_RESTRICTION) ) {
8895                                    if ( restrict == 0 ) {
8896                                            restrict = SchemaSymbols.RESTRICTION;
8897                                    } else {
8898                                        // REVISIT: Localize
8899
reportGenericSchemaError ( "The value 'restriction' is already in the list" );
8900                                    }
8901                            } else {
8902                                // REVISIT: Localize
8903
reportGenericSchemaError ( "Invalid final value (" + finalString + ")" );
8904                            }
8905                    }
8906
8907                    int defaultVal = extend+restrict+list+union;
8908                    return (defaultVal == 0 ? fFinalDefault : defaultVal);
8909            }
8910    }
8911
8912    private void reportGenericSchemaError (String JavaDoc error) throws Exception JavaDoc {
8913        if (fErrorReporter == null) {
8914            System.err.println("__TraverseSchemaError__ : " + error);
8915        }
8916        else {
8917            reportSchemaError (SchemaMessageProvider.GenericError, new Object JavaDoc[] { error });
8918        }
8919    }
8920
8921
8922    private void reportSchemaError(int major, Object JavaDoc args[]) throws Exception JavaDoc {
8923        if (fErrorReporter == null) {
8924            System.out.println("__TraverseSchemaError__ : " + SchemaMessageProvider.fgMessageKeys[major]);
8925            for (int i=0; i< args.length ; i++) {
8926                System.out.println((String JavaDoc)args[i]);
8927            }
8928        }
8929        else {
8930            fErrorReporter.reportError(fErrorReporter.getLocator(),
8931                                       SchemaMessageProvider.SCHEMA_DOMAIN,
8932                                       major,
8933                                       SchemaMessageProvider.MSG_NONE,
8934                                       args,
8935                                       XMLErrorReporter.ERRORTYPE_RECOVERABLE_ERROR);
8936        }
8937    }
8938
8939    /** Don't check the following code in because it creates a dependency on
8940        the serializer, preventing to package the parser without the serializer
8941    //Unit Test here
8942    public static void main(String args[] ) {
8943
8944        if( args.length != 1 ) {
8945            System.out.println( "Error: Usage java TraverseSchema yourFile.xsd" );
8946            System.exit(0);
8947        }
8948
8949        DOMParser parser = new IgnoreWhitespaceParser();
8950        parser.setEntityResolver( (fEntityResolver != null)? (fEntityResolver):(new Resolver()) );
8951        parser.setErrorHandler( new ErrorHandler() );
8952
8953        try {
8954        parser.setFeature("http://xml.org/sax/features/validation", false);
8955        parser.setFeature("http://apache.org/xml/features/dom/defer-node-expansion", false);
8956        }catch( org.xml.sax.SAXNotRecognizedException e ) {
8957            e.printStackTrace();
8958        }catch( org.xml.sax.SAXNotSupportedException e ) {
8959            e.printStackTrace();
8960        }
8961
8962        try {
8963        parser.parse( args[0]);
8964        }catch( IOException e ) {
8965            e.printStackTrace();
8966        }catch( SAXException e ) {
8967            e.printStackTrace();
8968        }
8969
8970        Document document = parser.getDocument(); //Our Grammar
8971
8972        OutputFormat format = new OutputFormat( document );
8973        java.io.StringWriter outWriter = new java.io.StringWriter();
8974        XMLSerializer serial = new XMLSerializer( outWriter,format);
8975
8976        TraverseSchema tst = null;
8977        try {
8978            Element root = document.getDocumentElement();// This is what we pass to TraverserSchema
8979            //serial.serialize( root );
8980            //System.out.println(outWriter.toString());
8981
8982            tst = new TraverseSchema( root, new StringPool(), new SchemaGrammar(), (GrammarResolver) new GrammarResolverImpl() );
8983            }
8984            catch (Exception e) {
8985                e.printStackTrace(System.err);
8986            }
8987
8988            parser.getDocument();
8989    }
8990    **/

8991
8992    static class Resolver implements EntityResolver JavaDoc {
8993        private static final String JavaDoc SYSTEM[] = {
8994            "http://www.w3.org/TR/2000/WD-xmlschema-1-20000407/structures.dtd",
8995            "http://www.w3.org/TR/2000/WD-xmlschema-1-20000407/datatypes.dtd",
8996            "http://www.w3.org/TR/2000/WD-xmlschema-1-20000407/versionInfo.ent",
8997        };
8998        private static final String JavaDoc PATH[] = {
8999            "structures.dtd",
9000            "datatypes.dtd",
9001            "versionInfo.ent",
9002        };
9003
9004        public InputSource JavaDoc resolveEntity(String JavaDoc publicId, String JavaDoc systemId)
9005        throws IOException JavaDoc {
9006
9007            // looking for the schema DTDs?
9008
for (int i = 0; i < SYSTEM.length; i++) {
9009                if (systemId.equals(SYSTEM[i])) {
9010                    InputSource JavaDoc source = new InputSource JavaDoc(getClass().getResourceAsStream(PATH[i]));
9011                    source.setPublicId(publicId);
9012                    source.setSystemId(systemId);
9013                    return source;
9014                }
9015            }
9016
9017            // use default resolution
9018
return null;
9019
9020        } // resolveEntity(String,String):InputSource
9021

9022    } // class Resolver
9023

9024    static class ErrorHandler implements org.xml.sax.ErrorHandler JavaDoc {
9025
9026        /** Warning. */
9027        public void warning(SAXParseException JavaDoc ex) {
9028            System.err.println("[Warning] "+
9029                               getLocationString(ex)+": "+
9030                               ex.getMessage());
9031        }
9032
9033        /** Error. */
9034        public void error(SAXParseException JavaDoc ex) throws SAXException JavaDoc {
9035            System.err.println("[Error] "+
9036                               getLocationString(ex)+": "+
9037                               ex.getMessage());
9038        }
9039
9040        /** Fatal error. */
9041        public void fatalError(SAXParseException JavaDoc ex) throws SAXException JavaDoc {
9042            System.err.println("[Fatal Error] "+
9043                               getLocationString(ex)+": "+
9044                               ex.getMessage());
9045            throw ex;
9046        }
9047
9048        //
9049
// Private methods
9050
//
9051

9052        /** Returns a string of the location. */
9053        private String JavaDoc getLocationString(SAXParseException JavaDoc ex) {
9054            StringBuffer JavaDoc str = new StringBuffer JavaDoc();
9055
9056            String JavaDoc systemId_ = ex.getSystemId();
9057            if (systemId_ != null) {
9058                int index = systemId_.lastIndexOf('/');
9059                if (index != -1)
9060                    systemId_ = systemId_.substring(index + 1);
9061                str.append(systemId_);
9062            }
9063            str.append(':');
9064            str.append(ex.getLineNumber());
9065            str.append(':');
9066            str.append(ex.getColumnNumber());
9067
9068            return str.toString();
9069
9070        } // getLocationString(SAXParseException):String
9071
}
9072
9073    static class IgnoreWhitespaceParser
9074        extends DOMParser {
9075        public void ignorableWhitespace(char ch[], int start, int length) {}
9076        public void ignorableWhitespace(int dataIdx) {}
9077    } // class IgnoreWhitespaceParser
9078

9079    // When in a <redefine>, type definitions being used (and indeed
9080
// refs to <group>'s and <attributeGroup>'s) may refer to info
9081
// items either in the schema being redefined, in the <redefine>,
9082
// or else in the schema doing the redefining. Because of this
9083
// latter we have to be prepared sometimes to look for our type
9084
// definitions outside the schema stored in fSchemaRootElement.
9085
// This simple class does this; it's just a linked list that
9086
// lets us look at the <schema>'s on the queue; note also that this
9087
// should provide us with a mechanism to handle nested <redefine>'s.
9088
// It's also a handy way of saving schema info when importing/including; saves some code.
9089
public class SchemaInfo {
9090        private Element JavaDoc saveRoot;
9091        private SchemaInfo nextRoot;
9092        private SchemaInfo prevRoot;
9093        private String JavaDoc savedSchemaURL = fCurrentSchemaURL;
9094        private boolean saveElementDefaultQualified = fElementDefaultQualified;
9095        private boolean saveAttributeDefaultQualified = fAttributeDefaultQualified;
9096        private int saveBlockDefault = fBlockDefault;
9097        private int saveFinalDefault = fFinalDefault;
9098        private NamespacesScope saveNamespacesScope = fNamespacesScope;
9099
9100        public SchemaInfo ( boolean saveElementDefaultQualified, boolean saveAttributeDefaultQualified,
9101                int saveBlockDefault, int saveFinalDefault,
9102                String JavaDoc savedSchemaURL, Element JavaDoc saveRoot,
9103                NamespacesScope saveNamespacesScope, SchemaInfo nextRoot, SchemaInfo prevRoot) {
9104            this.saveElementDefaultQualified = saveElementDefaultQualified;
9105            this.saveAttributeDefaultQualified = saveAttributeDefaultQualified;
9106            this.saveBlockDefault = saveBlockDefault;
9107            this.saveFinalDefault = saveFinalDefault;
9108            this.savedSchemaURL = savedSchemaURL;
9109            this.saveRoot = saveRoot ;
9110            if(saveNamespacesScope != null)
9111                this.saveNamespacesScope = (NamespacesScope)saveNamespacesScope.clone();
9112            this.nextRoot = nextRoot;
9113            this.prevRoot = prevRoot;
9114        }
9115        public void setNext (SchemaInfo next) {
9116            nextRoot = next;
9117        }
9118        public SchemaInfo getNext () {
9119            return nextRoot;
9120        }
9121        public void setPrev (SchemaInfo prev) {
9122            prevRoot = prev;
9123        }
9124        public String JavaDoc getCurrentSchemaURL() { return savedSchemaURL; }
9125        public SchemaInfo getPrev () {
9126            return prevRoot;
9127        }
9128        public Element JavaDoc getRoot() { return saveRoot; }
9129        // NOTE: this has side-effects!!!
9130
public void restore() {
9131            fCurrentSchemaURL = savedSchemaURL;
9132            fElementDefaultQualified = saveElementDefaultQualified;
9133            fAttributeDefaultQualified = saveAttributeDefaultQualified;
9134            fBlockDefault = saveBlockDefault;
9135            fFinalDefault = saveFinalDefault;
9136            fNamespacesScope = (NamespacesScope)saveNamespacesScope.clone();
9137            fSchemaRootElement = saveRoot;
9138        }
9139    } // class SchemaInfo
9140

9141} // class TraverseSchema
9142
Popular Tags