KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > impl > xs > XSConstraints


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

16
17 package org.apache.xerces.impl.xs;
18
19 import org.apache.xerces.impl.dv.XSSimpleType;
20 import org.apache.xerces.impl.dv.InvalidDatatypeValueException;
21 import org.apache.xerces.impl.dv.ValidatedInfo;
22 import org.apache.xerces.impl.XMLErrorReporter;
23 import org.apache.xerces.impl.xs.models.CMBuilder;
24 import org.apache.xerces.impl.xs.models.XSCMValidator;
25 import org.apache.xerces.impl.xs.util.SimpleLocator;
26 import org.apache.xerces.xs.XSConstants;
27 import org.apache.xerces.xs.XSObjectList;
28 import org.apache.xerces.xs.XSTypeDefinition;
29 import org.apache.xerces.impl.dv.ValidationContext;
30 import org.apache.xerces.util.SymbolHash;
31 import java.util.Vector JavaDoc;
32
33 /**
34  * Constaints shared by traversers and validator
35  *
36  * @xerces.internal
37  *
38  * @author Sandy Gao, IBM
39  *
40  * @version $Id: XSConstraints.java,v 1.41 2004/10/06 15:14:54 mrglavas Exp $
41  */

42 public class XSConstraints {
43
44     static final int OCCURRENCE_UNKNOWN = SchemaSymbols.OCCURRENCE_UNBOUNDED-1;
45     static final XSSimpleType STRING_TYPE = (XSSimpleType)SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(SchemaSymbols.ATTVAL_STRING);
46
47     /**
48      * check whether derived is valid derived from base, given a subset
49      * of {restriction, extension}.B
50      */

51     public static boolean checkTypeDerivationOk(XSTypeDefinition derived, XSTypeDefinition base, short block) {
52         // if derived is anyType, then it's valid only if base is anyType too
53
if (derived == SchemaGrammar.fAnyType)
54             return derived == base;
55         // if derived is anySimpleType, then it's valid only if the base
56
// is ur-type
57
if (derived == SchemaGrammar.fAnySimpleType) {
58             return (base == SchemaGrammar.fAnyType ||
59                     base == SchemaGrammar.fAnySimpleType);
60         }
61
62         // if derived is simple type
63
if (derived.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
64             // if base is complex type
65
if (base.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
66                 // if base is anyType, change base to anySimpleType,
67
// otherwise, not valid
68
if (base == SchemaGrammar.fAnyType)
69                     base = SchemaGrammar.fAnySimpleType;
70                 else
71                     return false;
72             }
73             return checkSimpleDerivation((XSSimpleType)derived,
74                                          (XSSimpleType)base, block);
75         } else {
76             return checkComplexDerivation((XSComplexTypeDecl)derived, base, block);
77         }
78     }
79
80     /**
81      * check whether simple type derived is valid derived from base,
82      * given a subset of {restriction, extension}.
83      */

84     public static boolean checkSimpleDerivationOk(XSSimpleType derived, XSTypeDefinition base, short block) {
85         // if derived is anySimpleType, then it's valid only if the base
86
// is ur-type
87
if (derived == SchemaGrammar.fAnySimpleType) {
88             return (base == SchemaGrammar.fAnyType ||
89                     base == SchemaGrammar.fAnySimpleType);
90         }
91
92         // if base is complex type
93
if (base.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
94             // if base is anyType, change base to anySimpleType,
95
// otherwise, not valid
96
if (base == SchemaGrammar.fAnyType)
97                 base = SchemaGrammar.fAnySimpleType;
98             else
99                 return false;
100         }
101         return checkSimpleDerivation((XSSimpleType)derived,
102                                      (XSSimpleType)base, block);
103     }
104
105     /**
106      * check whether complex type derived is valid derived from base,
107      * given a subset of {restriction, extension}.
108      */

109     public static boolean checkComplexDerivationOk(XSComplexTypeDecl derived, XSTypeDefinition base, short block) {
110         // if derived is anyType, then it's valid only if base is anyType too
111
if (derived == SchemaGrammar.fAnyType)
112             return derived == base;
113         return checkComplexDerivation((XSComplexTypeDecl)derived, base, block);
114     }
115
116     /**
117      * Note: this will be a private method, and it assumes that derived is not
118      * anySimpleType, and base is not anyType. Another method will be
119      * introduced for public use, which will call this method.
120      */

121     private static boolean checkSimpleDerivation(XSSimpleType derived, XSSimpleType base, short block) {
122         // 1 They are the same type definition.
123
if (derived == base)
124             return true;
125
126         // 2 All of the following must be true:
127
// 2.1 restriction is not in the subset, or in the {final} of its own {base type definition};
128
if ((block & XSConstants.DERIVATION_RESTRICTION) != 0 ||
129             (derived.getBaseType().getFinal() & XSConstants.DERIVATION_RESTRICTION) != 0) {
130             return false;
131         }
132
133         // 2.2 One of the following must be true:
134
// 2.2.1 D's base type definition is B.
135
XSSimpleType directBase = (XSSimpleType)derived.getBaseType();
136         if (directBase == base)
137             return true;
138
139         // 2.2.2 D's base type definition is not the simple ur-type definition and is validly derived from B given the subset, as defined by this constraint.
140
if (directBase != SchemaGrammar.fAnySimpleType &&
141             checkSimpleDerivation(directBase, base, block)) {
142             return true;
143         }
144
145         // 2.2.3 D's {variety} is list or union and B is the simple ur-type definition.
146
if ((derived.getVariety() == XSSimpleType.VARIETY_LIST ||
147              derived.getVariety() == XSSimpleType.VARIETY_UNION) &&
148             base == SchemaGrammar.fAnySimpleType) {
149             return true;
150         }
151
152         // 2.2.4 B's {variety} is union and D is validly derived from a type definition in B's {member type definitions} given the subset, as defined by this constraint.
153
if (base.getVariety() == XSSimpleType.VARIETY_UNION) {
154             XSObjectList subUnionMemberDV = base.getMemberTypes();
155             int subUnionSize = subUnionMemberDV.getLength();
156             for (int i=0; i<subUnionSize; i++) {
157                 base = (XSSimpleType)subUnionMemberDV.item(i);
158                 if (checkSimpleDerivation(derived, base, block))
159                     return true;
160             }
161         }
162
163         return false;
164     }
165
166     /**
167      * Note: this will be a private method, and it assumes that derived is not
168      * anyType. Another method will be introduced for public use,
169      * which will call this method.
170      */

171     private static boolean checkComplexDerivation(XSComplexTypeDecl derived, XSTypeDefinition base, short block) {
172         // 2.1 B and D must be the same type definition.
173
if (derived == base)
174             return true;
175
176         // 1 If B and D are not the same type definition, then the {derivation method} of D must not be in the subset.
177
if ((derived.fDerivedBy & block) != 0)
178             return false;
179
180         // 2 One of the following must be true:
181
XSTypeDefinition directBase = derived.fBaseType;
182         // 2.2 B must be D's {base type definition}.
183
if (directBase == base)
184             return true;
185
186         // 2.3 All of the following must be true:
187
// 2.3.1 D's {base type definition} must not be the ur-type definition.
188
if (directBase == SchemaGrammar.fAnyType ||
189             directBase == SchemaGrammar.fAnySimpleType) {
190             return false;
191         }
192
193         // 2.3.2 The appropriate case among the following must be true:
194
// 2.3.2.1 If D's {base type definition} is complex, then it must be validly derived from B given the subset as defined by this constraint.
195
if (directBase.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE)
196             return checkComplexDerivation((XSComplexTypeDecl)directBase, base, block);
197
198         // 2.3.2.2 If D's {base type definition} is simple, then it must be validly derived from B given the subset as defined in Type Derivation OK (Simple) (3.14.6).
199
if (directBase.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
200             // if base is complex type
201
if (base.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
202                 // if base is anyType, change base to anySimpleType,
203
// otherwise, not valid
204
if (base == SchemaGrammar.fAnyType)
205                     base = SchemaGrammar.fAnySimpleType;
206                 else
207                     return false;
208             }
209             return checkSimpleDerivation((XSSimpleType)directBase,
210                                          (XSSimpleType)base, block);
211         }
212
213         return false;
214     }
215
216     /**
217      * check whether a value is a valid default for some type
218      * returns the compiled form of the value
219      * The parameter value could be either a String or a ValidatedInfo object
220      */

221     public static Object JavaDoc ElementDefaultValidImmediate(XSTypeDefinition type, String JavaDoc value, ValidationContext context, ValidatedInfo vinfo) {
222
223         XSSimpleType dv = null;
224
225         // e-props-correct
226
// For a string to be a valid default with respect to a type definition the appropriate case among the following must be true:
227
// 1 If the type definition is a simple type definition, then the string must be valid with respect to that definition as defined by String Valid (3.14.4).
228
if (type.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
229             dv = (XSSimpleType)type;
230         }
231
232         // 2 If the type definition is a complex type definition, then all of the following must be true:
233
else {
234             // 2.1 its {content type} must be a simple type definition or mixed.
235
XSComplexTypeDecl ctype = (XSComplexTypeDecl)type;
236             // 2.2 The appropriate case among the following must be true:
237
// 2.2.1 If the {content type} is a simple type definition, then the string must be valid with respect to that simple type definition as defined by String Valid (3.14.4).
238
if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
239                 dv = ctype.fXSSimpleType;
240             }
241             // 2.2.2 If the {content type} is mixed, then the {content type}'s particle must be emptiable as defined by Particle Emptiable (3.9.6).
242
else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
243                 if (!((XSParticleDecl)ctype.getParticle()).emptiable())
244                     return null;
245             }
246             else {
247                 return null;
248             }
249         }
250
251         // get the simple type declaration, and validate
252
Object JavaDoc actualValue = null;
253         if (dv == null) {
254             // complex type with mixed. to make sure that we store correct
255
// information in vinfo and return the correct value, we use
256
// "string" type for validation
257
dv = STRING_TYPE;
258         }
259         try {
260             // validate the original lexical rep, and set the actual value
261
actualValue = dv.validate(value, context, vinfo);
262             // validate the canonical lexical rep
263
if (vinfo != null)
264                 actualValue = dv.validate(vinfo.stringValue(), context, vinfo);
265         } catch (InvalidDatatypeValueException ide) {
266             return null;
267         }
268
269         return actualValue;
270     }
271
272     static void reportSchemaError(XMLErrorReporter errorReporter,
273                                   SimpleLocator loc,
274                                   String JavaDoc key, Object JavaDoc[] args) {
275         if (loc != null) {
276             errorReporter.reportError(loc, XSMessageFormatter.SCHEMA_DOMAIN,
277                                       key, args, XMLErrorReporter.SEVERITY_ERROR);
278         }
279         else {
280             errorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN,
281                                       key, args, XMLErrorReporter.SEVERITY_ERROR);
282         }
283     }
284
285     /**
286      * used to check the 3 constraints against each complex type
287      * (should be each model group):
288      * Unique Particle Attribution, Particle Derivation (Restriction),
289      * Element Declrations Consistent.
290      */

291     public static void fullSchemaChecking(XSGrammarBucket grammarBucket,
292                                           SubstitutionGroupHandler SGHandler,
293                                           CMBuilder cmBuilder,
294                                           XMLErrorReporter errorReporter) {
295         // get all grammars, and put all substitution group information
296
// in the substitution group handler
297
SchemaGrammar[] grammars = grammarBucket.getGrammars();
298         for (int i = grammars.length-1; i >= 0; i--) {
299             SGHandler.addSubstitutionGroup(grammars[i].getSubstitutionGroups());
300         }
301
302         XSParticleDecl fakeDerived = new XSParticleDecl();
303         XSParticleDecl fakeBase = new XSParticleDecl();
304         fakeDerived.fType = XSParticleDecl.PARTICLE_MODELGROUP;
305         fakeBase.fType = XSParticleDecl.PARTICLE_MODELGROUP;
306         // before worrying about complexTypes, let's get
307
// groups redefined by restriction out of the way.
308
for (int g = grammars.length-1; g >= 0; g--) {
309             XSGroupDecl [] redefinedGroups = grammars[g].getRedefinedGroupDecls();
310             SimpleLocator [] rgLocators = grammars[g].getRGLocators();
311             for(int i=0; i<redefinedGroups.length; ) {
312                 XSGroupDecl derivedGrp = redefinedGroups[i++];
313                 XSModelGroupImpl derivedMG = derivedGrp.fModelGroup;
314                 XSGroupDecl baseGrp = redefinedGroups[i++];
315                 XSModelGroupImpl baseMG = baseGrp.fModelGroup;
316                 if(baseMG == null) {
317                     if(derivedMG != null) { // can't be a restriction!
318
reportSchemaError(errorReporter, rgLocators[i/2-1],
319                                           "src-redefine.6.2.2",
320                                           new Object JavaDoc[]{derivedGrp.fName, "rcase-Recurse.2"});
321                     }
322                 } else {
323                     fakeDerived.fValue = derivedMG;
324                     fakeBase.fValue = baseMG;
325                     try {
326                         particleValidRestriction(fakeDerived, SGHandler, fakeBase, SGHandler);
327                     } catch (XMLSchemaException e) {
328                         String JavaDoc key = e.getKey();
329                         reportSchemaError(errorReporter, rgLocators[i/2-1],
330                                           key,
331                                           e.getArgs());
332                         reportSchemaError(errorReporter, rgLocators[i/2-1],
333                                           "src-redefine.6.2.2",
334                                           new Object JavaDoc[]{derivedGrp.fName, key});
335                     }
336                 }
337             }
338         }
339
340         // for each complex type, check the 3 constraints.
341
// types need to be checked
342
XSComplexTypeDecl[] types;
343         SimpleLocator [] ctLocators;
344         // to hold the errors
345
// REVISIT: do we want to report all errors? or just one?
346
//XMLSchemaError1D errors = new XMLSchemaError1D();
347
// whether need to check this type again;
348
// whether only do UPA checking
349
boolean further, fullChecked;
350         // if do all checkings, how many need to be checked again.
351
int keepType;
352         // i: grammar; j: type; k: error
353
// for all grammars
354
SymbolHash elemTable = new SymbolHash();
355         for (int i = grammars.length-1, j, k; i >= 0; i--) {
356             // get whether to skip EDC, and types need to be checked
357
keepType = 0;
358             fullChecked = grammars[i].fFullChecked;
359             types = grammars[i].getUncheckedComplexTypeDecls();
360             ctLocators = grammars[i].getUncheckedCTLocators();
361             // for each type
362
for (j = 0; j < types.length; j++) {
363                 // if we've already full-checked this grammar, then
364
// skip the EDC constraint
365
if (!fullChecked) {
366                 // 1. Element Decl Consistent
367
if (types[j].fParticle!=null) {
368                     elemTable.clear();
369                     try {
370                       checkElementDeclsConsistent(types[j], types[j].fParticle,
371                                                   elemTable, SGHandler);
372                     }
373                     catch (XMLSchemaException e) {
374                       reportSchemaError(errorReporter, ctLocators[j],
375                                         e.getKey(),
376                                         e.getArgs());
377                     }
378                   }
379                 }
380
381                 // 2. Particle Derivation
382

383                 if (types[j].fBaseType != null &&
384                     types[j].fBaseType != SchemaGrammar.fAnyType &&
385                     types[j].fDerivedBy == XSConstants.DERIVATION_RESTRICTION &&
386                     (types[j].fBaseType instanceof XSComplexTypeDecl)) {
387
388                   XSParticleDecl derivedParticle=types[j].fParticle;
389                   XSParticleDecl baseParticle=
390                     ((XSComplexTypeDecl)(types[j].fBaseType)).fParticle;
391                   if (derivedParticle==null) {
392                       if (baseParticle!=null && !baseParticle.emptiable()) {
393                           reportSchemaError(errorReporter,ctLocators[j],
394                                   "derivation-ok-restriction.5.3.2",
395                                   new Object JavaDoc[]{types[j].fName, types[j].fBaseType.getName()});
396                       }
397                   }
398                   else if (baseParticle!=null) {
399                       try {
400                           particleValidRestriction(types[j].fParticle,
401                                   SGHandler,
402                                   ((XSComplexTypeDecl)(types[j].fBaseType)).fParticle,
403                                   SGHandler);
404                       } catch (XMLSchemaException e) {
405                           reportSchemaError(errorReporter, ctLocators[j],
406                                   e.getKey(),
407                                   e.getArgs());
408                           reportSchemaError(errorReporter, ctLocators[j],
409                                   "derivation-ok-restriction.5.4.2",
410                                   new Object JavaDoc[]{types[j].fName});
411                       }
412                   }
413                   else {
414                       reportSchemaError(errorReporter, ctLocators[j],
415                               "derivation-ok-restriction.5.4.2",
416                               new Object JavaDoc[]{types[j].fName});
417                   }
418                 }
419                 // 3. UPA
420
// get the content model and check UPA
421
XSCMValidator cm = types[j].getContentModel(cmBuilder);
422                 further = false;
423                 if (cm != null) {
424                     try {
425                         further = cm.checkUniqueParticleAttribution(SGHandler);
426                     } catch (XMLSchemaException e) {
427                         reportSchemaError(errorReporter, ctLocators[j],
428                                           e.getKey(),
429                                           e.getArgs());
430                     }
431                 }
432                 // now report all errors
433
// REVISIT: do we want to report all errors? or just one?
434
/*for (k = errors.getErrorCodeNum()-1; k >= 0; k--) {
435                     reportSchemaError(errorReporter, ctLocators[j],
436                                       errors.getErrorCode(k),
437                                       errors.getArgs(k));
438                 }*/

439
440                 // if we are doing all checkings, and this one needs further
441
// checking, store it in the type array.
442
if (!fullChecked && further)
443                     types[keepType++] = types[j];
444
445                 // clear errors for the next type.
446
// REVISIT: do we want to report all errors? or just one?
447
//errors.clear();
448
}
449             // we've done with the types in this grammar. if we are checking
450
// all constraints, need to trim type array to a proper size:
451
// only contain those need further checking.
452
// and mark this grammar that it only needs UPA checking.
453
if (!fullChecked) {
454                 grammars[i].setUncheckedTypeNum(keepType);
455                 grammars[i].fFullChecked = true;
456             }
457         }
458     }
459
460     /*
461        Check that a given particle is a valid restriction of a base particle.
462     */

463
464     public static void checkElementDeclsConsistent(XSComplexTypeDecl type,
465                                      XSParticleDecl particle,
466                                      SymbolHash elemDeclHash,
467                                      SubstitutionGroupHandler sgHandler)
468                                      throws XMLSchemaException {
469
470        // check for elements in the tree with the same name and namespace
471

472        int pType = particle.fType;
473
474        if (pType == XSParticleDecl.PARTICLE_WILDCARD)
475           return;
476
477        if (pType == XSParticleDecl.PARTICLE_ELEMENT) {
478           XSElementDecl elem = (XSElementDecl)(particle.fValue);
479           findElemInTable(type, elem, elemDeclHash);
480
481           if (elem.fScope == XSConstants.SCOPE_GLOBAL) {
482              // Check for subsitution groups.
483
XSElementDecl[] subGroup = sgHandler.getSubstitutionGroup(elem);
484              for (int i = 0; i < subGroup.length; i++) {
485                findElemInTable(type, subGroup[i], elemDeclHash);
486              }
487           }
488           return;
489        }
490
491        XSModelGroupImpl group = (XSModelGroupImpl)particle.fValue;
492        for (int i = 0; i < group.fParticleCount; i++)
493            checkElementDeclsConsistent(type, group.fParticles[i], elemDeclHash, sgHandler);
494     }
495
496     public static void findElemInTable(XSComplexTypeDecl type, XSElementDecl elem,
497                                        SymbolHash elemDeclHash)
498                                        throws XMLSchemaException {
499
500         // How can we avoid this concat? LM.
501
String JavaDoc name = elem.fName + "," + elem.fTargetNamespace;
502
503         XSElementDecl existingElem = null;
504         if ((existingElem = (XSElementDecl)(elemDeclHash.get(name))) == null) {
505           // just add it in
506
elemDeclHash.put(name, elem);
507         }
508         else {
509           // If this is the same check element, we're O.K.
510
if (elem == existingElem)
511             return;
512
513           if (elem.fType != existingElem.fType) {
514             // Types are not the same
515
throw new XMLSchemaException("cos-element-consistent",
516                       new Object JavaDoc[] {type.fName, elem.fName});
517
518           }
519         }
520     }
521
522     /*
523        Check that a given particle is a valid restriction of a base particle.
524     */

525     private static void particleValidRestriction(XSParticleDecl dParticle,
526                                      SubstitutionGroupHandler dSGHandler,
527                                      XSParticleDecl bParticle,
528                                      SubstitutionGroupHandler bSGHandler)
529                                      throws XMLSchemaException {
530        particleValidRestriction(dParticle, dSGHandler, bParticle, bSGHandler, true);
531     }
532
533     private static void particleValidRestriction(XSParticleDecl dParticle,
534                                      SubstitutionGroupHandler dSGHandler,
535                                      XSParticleDecl bParticle,
536                                      SubstitutionGroupHandler bSGHandler,
537                                      boolean checkWCOccurrence)
538                                      throws XMLSchemaException {
539
540        Vector JavaDoc dChildren = null;
541        Vector JavaDoc bChildren = null;
542        int dMinEffectiveTotalRange=OCCURRENCE_UNKNOWN;
543        int dMaxEffectiveTotalRange=OCCURRENCE_UNKNOWN;
544
545
546        // Check for empty particles. If either base or derived particle is empty,
547
// (and the other isn't) it's an error.
548
if (dParticle.isEmpty() && !bParticle.emptiable()) {
549          throw new XMLSchemaException("cos-particle-restrict.a", null);
550        }
551        else if (!dParticle.isEmpty() && bParticle.isEmpty()) {
552          throw new XMLSchemaException("cos-particle-restrict.b", null);
553        }
554
555        //
556
// Do setup prior to invoking the Particle (Restriction) cases.
557
// This involves:
558
// - removing pointless occurrences for groups, and retrieving a vector of
559
// non-pointless children
560
// - turning top-level elements with substitution groups into CHOICE groups.
561
//
562

563        short dType = dParticle.fType;
564        //
565
// Handle pointless groups for the derived particle
566
//
567
if (dType == XSParticleDecl.PARTICLE_MODELGROUP) {
568          dType = ((XSModelGroupImpl)dParticle.fValue).fCompositor;
569
570          // Find a group, starting with this particle, with more than 1 child. There
571
// may be none, and the particle of interest trivially becomes an element or
572
// wildcard.
573
XSParticleDecl dtmp = getNonUnaryGroup(dParticle);
574          if (dtmp != dParticle) {
575             // Particle has been replaced. Retrieve new type info.
576
dParticle = dtmp;
577             dType = dParticle.fType;
578             if (dType == XSParticleDecl.PARTICLE_MODELGROUP)
579                dType = ((XSModelGroupImpl)dParticle.fValue).fCompositor;
580          }
581
582          // Fill in a vector with the children of the particle, removing any
583
// pointless model groups in the process.
584
dChildren = removePointlessChildren(dParticle);
585        }
586
587        int dMinOccurs = dParticle.fMinOccurs;
588        int dMaxOccurs = dParticle.fMaxOccurs;
589
590        //
591
// For elements which are the heads of substitution groups, treat as CHOICE
592
//
593
if (dSGHandler != null && dType == XSParticleDecl.PARTICLE_ELEMENT) {
594            XSElementDecl dElement = (XSElementDecl)dParticle.fValue;
595
596            if (dElement.fScope == XSConstants.SCOPE_GLOBAL) {
597              // Check for subsitution groups. Treat any element that has a
598
// subsitution group as a choice. Fill in the children vector with the
599
// members of the substitution group
600
XSElementDecl[] subGroup = dSGHandler.getSubstitutionGroup(dElement);
601              if (subGroup.length >0 ) {
602                 // Now, set the type to be CHOICE. The "group" will have the same
603
// occurrence information as the original particle.
604
dType = XSModelGroupImpl.MODELGROUP_CHOICE;
605                 dMinEffectiveTotalRange = dMinOccurs;
606                 dMaxEffectiveTotalRange = dMaxOccurs;
607
608                 // Fill in the vector of children
609
dChildren = new Vector JavaDoc(subGroup.length+1);
610                 for (int i = 0; i < subGroup.length; i++) {
611                   addElementToParticleVector(dChildren, subGroup[i]);
612                 }
613                 addElementToParticleVector(dChildren, dElement);
614
615                 // Set the handler to null, to indicate that we've finished handling
616
// substitution groups for this particle.
617
dSGHandler = null;
618              }
619            }
620        }
621
622        short bType = bParticle.fType;
623        //
624
// Handle pointless groups for the base particle
625
//
626
if (bType == XSParticleDecl.PARTICLE_MODELGROUP) {
627          bType = ((XSModelGroupImpl)bParticle.fValue).fCompositor;
628
629          // Find a group, starting with this particle, with more than 1 child. There
630
// may be none, and the particle of interest trivially becomes an element or
631
// wildcard.
632
XSParticleDecl btmp = getNonUnaryGroup(bParticle);
633          if (btmp != bParticle) {
634             // Particle has been replaced. Retrieve new type info.
635
bParticle = btmp;
636             bType = bParticle.fType;
637             if (bType == XSParticleDecl.PARTICLE_MODELGROUP)
638                bType = ((XSModelGroupImpl)bParticle.fValue).fCompositor;
639          }
640
641          // Fill in a vector with the children of the particle, removing any
642
// pointless model groups in the process.
643
bChildren = removePointlessChildren(bParticle);
644        }
645
646        int bMinOccurs = bParticle.fMinOccurs;
647        int bMaxOccurs = bParticle.fMaxOccurs;
648
649        if (bSGHandler != null && bType == XSParticleDecl.PARTICLE_ELEMENT) {
650            XSElementDecl bElement = (XSElementDecl)bParticle.fValue;
651
652            if (bElement.fScope == XSConstants.SCOPE_GLOBAL) {
653              // Check for subsitution groups. Treat any element that has a
654
// subsitution group as a choice. Fill in the children vector with the
655
// members of the substitution group
656
XSElementDecl[] bsubGroup = bSGHandler.getSubstitutionGroup(bElement);
657              if (bsubGroup.length >0 ) {
658                 // Now, set the type to be CHOICE
659
bType = XSModelGroupImpl.MODELGROUP_CHOICE;
660
661                 bChildren = new Vector JavaDoc(bsubGroup.length+1);
662                 for (int i = 0; i < bsubGroup.length; i++) {
663                   addElementToParticleVector(bChildren, bsubGroup[i]);
664                 }
665                 addElementToParticleVector(bChildren, bElement);
666                 // Set the handler to null, to indicate that we've finished handling
667
// substitution groups for this particle.
668
bSGHandler = null;
669              }
670            }
671        }
672
673        //
674
// O.K. - Figure out which particle derivation rule applies and call it
675
//
676
switch (dType) {
677          case XSParticleDecl.PARTICLE_ELEMENT:
678          {
679             switch (bType) {
680
681               // Elt:Elt NameAndTypeOK
682
case XSParticleDecl.PARTICLE_ELEMENT:
683               {
684                  checkNameAndTypeOK((XSElementDecl)dParticle.fValue,dMinOccurs,dMaxOccurs,
685                                     (XSElementDecl)bParticle.fValue,bMinOccurs,bMaxOccurs);
686                  return;
687               }
688
689               // Elt:Any NSCompat
690
case XSParticleDecl.PARTICLE_WILDCARD:
691               {
692                  checkNSCompat((XSElementDecl)dParticle.fValue,dMinOccurs,dMaxOccurs,
693                                (XSWildcardDecl)bParticle.fValue,bMinOccurs,bMaxOccurs,
694                                checkWCOccurrence);
695                  return;
696               }
697
698               // Elt:All RecurseAsIfGroup
699
case XSModelGroupImpl.MODELGROUP_CHOICE:
700               {
701                  // Treat the element as if it were in a group of the same type
702
// as the base Particle
703
dChildren = new Vector JavaDoc();
704                  dChildren.addElement(dParticle);
705
706                  checkRecurseLax(dChildren, 1, 1, dSGHandler,
707                                  bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
708                  return;
709               }
710               case XSModelGroupImpl.MODELGROUP_SEQUENCE:
711               case XSModelGroupImpl.MODELGROUP_ALL:
712               {
713                  // Treat the element as if it were in a group of the same type
714
// as the base Particle
715
dChildren = new Vector JavaDoc();
716                  dChildren.addElement(dParticle);
717
718                  checkRecurse(dChildren, 1, 1, dSGHandler,
719                               bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
720                  return;
721               }
722
723               default:
724               {
725                 throw new XMLSchemaException("Internal-Error",
726                                              new Object JavaDoc[]{"in particleValidRestriction"});
727               }
728             }
729          }
730
731          case XSParticleDecl.PARTICLE_WILDCARD:
732          {
733             switch (bType) {
734
735               // Any:Any NSSubset
736
case XSParticleDecl.PARTICLE_WILDCARD:
737               {
738                  checkNSSubset((XSWildcardDecl)dParticle.fValue, dMinOccurs, dMaxOccurs,
739                                (XSWildcardDecl)bParticle.fValue, bMinOccurs, bMaxOccurs);
740                  return;
741               }
742
743               case XSModelGroupImpl.MODELGROUP_CHOICE:
744               case XSModelGroupImpl.MODELGROUP_SEQUENCE:
745               case XSModelGroupImpl.MODELGROUP_ALL:
746               case XSParticleDecl.PARTICLE_ELEMENT:
747               {
748                  throw new XMLSchemaException("cos-particle-restrict.2",
749                                         new Object JavaDoc[]{"any:choice,sequence,all,elt"});
750               }
751
752               default:
753               {
754                 throw new XMLSchemaException("Internal-Error",
755                                              new Object JavaDoc[]{"in particleValidRestriction"});
756               }
757             }
758          }
759
760          case XSModelGroupImpl.MODELGROUP_ALL:
761          {
762             switch (bType) {
763
764               // All:Any NSRecurseCheckCardinality
765
case XSParticleDecl.PARTICLE_WILDCARD:
766               {
767                  if (dMinEffectiveTotalRange == OCCURRENCE_UNKNOWN)
768                     dMinEffectiveTotalRange = dParticle.minEffectiveTotalRange();
769                  if (dMaxEffectiveTotalRange == OCCURRENCE_UNKNOWN)
770                     dMaxEffectiveTotalRange = dParticle.maxEffectiveTotalRange();
771
772                  checkNSRecurseCheckCardinality(dChildren, dMinEffectiveTotalRange,
773                                                 dMaxEffectiveTotalRange,
774                                                 dSGHandler,
775                                                 bParticle,bMinOccurs,bMaxOccurs,
776                                                 checkWCOccurrence);
777
778                  return;
779               }
780
781               case XSModelGroupImpl.MODELGROUP_ALL:
782               {
783                  checkRecurse(dChildren, dMinOccurs, dMaxOccurs, dSGHandler,
784                               bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
785                  return;
786               }
787
788               case XSModelGroupImpl.MODELGROUP_CHOICE:
789               case XSModelGroupImpl.MODELGROUP_SEQUENCE:
790               case XSParticleDecl.PARTICLE_ELEMENT:
791               {
792                  throw new XMLSchemaException("cos-particle-restrict.2",
793                                         new Object JavaDoc[]{"all:choice,sequence,elt"});
794               }
795
796               default:
797               {
798                 throw new XMLSchemaException("Internal-Error",
799                                              new Object JavaDoc[]{"in particleValidRestriction"});
800               }
801             }
802          }
803
804          case XSModelGroupImpl.MODELGROUP_CHOICE:
805          {
806             switch (bType) {
807
808               // Choice:Any NSRecurseCheckCardinality
809
case XSParticleDecl.PARTICLE_WILDCARD:
810               {
811                  if (dMinEffectiveTotalRange == OCCURRENCE_UNKNOWN)
812                     dMinEffectiveTotalRange = dParticle.minEffectiveTotalRange();
813                  if (dMaxEffectiveTotalRange == OCCURRENCE_UNKNOWN)
814                     dMaxEffectiveTotalRange = dParticle.maxEffectiveTotalRange();
815
816                  checkNSRecurseCheckCardinality(dChildren, dMinEffectiveTotalRange,
817                                                 dMaxEffectiveTotalRange,
818                                                 dSGHandler,
819                                                 bParticle,bMinOccurs,bMaxOccurs,
820                                                 checkWCOccurrence);
821                  return;
822               }
823
824               case XSModelGroupImpl.MODELGROUP_CHOICE:
825               {
826                  checkRecurseLax(dChildren, dMinOccurs, dMaxOccurs, dSGHandler,
827                                  bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
828                  return;
829               }
830
831               case XSModelGroupImpl.MODELGROUP_ALL:
832               case XSModelGroupImpl.MODELGROUP_SEQUENCE:
833               case XSParticleDecl.PARTICLE_ELEMENT:
834               {
835                  throw new XMLSchemaException("cos-particle-restrict.2",
836                                         new Object JavaDoc[]{"choice:all,sequence,elt"});
837               }
838
839               default:
840               {
841                 throw new XMLSchemaException("Internal-Error",
842                                              new Object JavaDoc[]{"in particleValidRestriction"});
843               }
844             }
845          }
846
847
848          case XSModelGroupImpl.MODELGROUP_SEQUENCE:
849          {
850             switch (bType) {
851
852               // Choice:Any NSRecurseCheckCardinality
853
case XSParticleDecl.PARTICLE_WILDCARD:
854               {
855                  if (dMinEffectiveTotalRange == OCCURRENCE_UNKNOWN)
856                     dMinEffectiveTotalRange = dParticle.minEffectiveTotalRange();
857                  if (dMaxEffectiveTotalRange == OCCURRENCE_UNKNOWN)
858                     dMaxEffectiveTotalRange = dParticle.maxEffectiveTotalRange();
859
860                  checkNSRecurseCheckCardinality(dChildren, dMinEffectiveTotalRange,
861                                                 dMaxEffectiveTotalRange,
862                                                 dSGHandler,
863                                                 bParticle,bMinOccurs,bMaxOccurs,
864                                                 checkWCOccurrence);
865                  return;
866               }
867
868               case XSModelGroupImpl.MODELGROUP_ALL:
869               {
870                  checkRecurseUnordered(dChildren, dMinOccurs, dMaxOccurs, dSGHandler,
871                                        bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
872                  return;
873               }
874
875               case XSModelGroupImpl.MODELGROUP_SEQUENCE:
876               {
877                  checkRecurse(dChildren, dMinOccurs, dMaxOccurs, dSGHandler,
878                               bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
879                  return;
880               }
881
882               case XSModelGroupImpl.MODELGROUP_CHOICE:
883               {
884                  int min1 = dMinOccurs * dChildren.size();
885                  int max1 = (dMaxOccurs == SchemaSymbols.OCCURRENCE_UNBOUNDED)?
886                              dMaxOccurs : dMaxOccurs * dChildren.size();
887                  checkMapAndSum(dChildren, min1, max1, dSGHandler,
888                                 bChildren, bMinOccurs, bMaxOccurs, bSGHandler);
889                  return;
890               }
891
892               case XSParticleDecl.PARTICLE_ELEMENT:
893               {
894                  throw new XMLSchemaException("cos-particle-restrict.2",
895                                         new Object JavaDoc[]{"seq:elt"});
896               }
897
898               default:
899               {
900                 throw new XMLSchemaException("Internal-Error",
901                                              new Object JavaDoc[]{"in particleValidRestriction"});
902               }
903             }
904          }
905
906        }
907     }
908
909     private static void addElementToParticleVector (Vector JavaDoc v, XSElementDecl d) {
910
911        XSParticleDecl p = new XSParticleDecl();
912        p.fValue = d;
913        p.fType = XSParticleDecl.PARTICLE_ELEMENT;
914        v.addElement(p);
915
916     }
917
918     private static XSParticleDecl getNonUnaryGroup(XSParticleDecl p) {
919
920        if (p.fType == XSParticleDecl.PARTICLE_ELEMENT ||
921            p.fType == XSParticleDecl.PARTICLE_WILDCARD)
922          return p;
923
924        if (p.fMinOccurs==1 && p.fMaxOccurs==1 &&
925            p.fValue!=null && ((XSModelGroupImpl)p.fValue).fParticleCount == 1)
926          return getNonUnaryGroup(((XSModelGroupImpl)p.fValue).fParticles[0]);
927        else
928          return p;
929     }
930
931     private static Vector JavaDoc removePointlessChildren(XSParticleDecl p) {
932
933
934        if (p.fType == XSParticleDecl.PARTICLE_ELEMENT ||
935            p.fType == XSParticleDecl.PARTICLE_WILDCARD)
936          return null;
937
938        Vector JavaDoc children = new Vector JavaDoc();
939
940        XSModelGroupImpl group = (XSModelGroupImpl)p.fValue;
941        for (int i = 0; i < group.fParticleCount; i++)
942            gatherChildren(group.fCompositor, group.fParticles[i], children);
943
944        return children;
945     }
946
947
948     private static void gatherChildren(int parentType, XSParticleDecl p, Vector JavaDoc children) {
949
950        int min = p.fMinOccurs;
951        int max = p.fMaxOccurs;
952        int type = p.fType;
953        if (type == XSParticleDecl.PARTICLE_MODELGROUP)
954           type = ((XSModelGroupImpl)p.fValue).fCompositor;
955
956        if (type == XSParticleDecl.PARTICLE_ELEMENT ||
957            type== XSParticleDecl.PARTICLE_WILDCARD) {
958           children.addElement(p);
959           return;
960        }
961
962        if (! (min==1 && max==1)) {
963           children.addElement(p);
964        }
965        else if (parentType == type) {
966           XSModelGroupImpl group = (XSModelGroupImpl)p.fValue;
967           for (int i = 0; i < group.fParticleCount; i++)
968              gatherChildren(type, group.fParticles[i], children);
969        }
970        else if (!p.isEmpty()) {
971           children.addElement(p);
972        }
973
974     }
975
976     private static void checkNameAndTypeOK(XSElementDecl dElement, int dMin, int dMax,
977                                            XSElementDecl bElement, int bMin, int bMax)
978                                    throws XMLSchemaException {
979
980
981       //
982
// Check that the names are the same
983
//
984
if (dElement.fName != bElement.fName ||
985           dElement.fTargetNamespace != bElement.fTargetNamespace) {
986           throw new XMLSchemaException(
987               "rcase-NameAndTypeOK.1",new Object JavaDoc[]{dElement.fName,
988                dElement.fTargetNamespace, bElement.fName, bElement.fTargetNamespace});
989       }
990
991       //
992
// Check nillable
993
//
994
if (!bElement.getNillable() && dElement.getNillable()) {
995         throw new XMLSchemaException("rcase-NameAndTypeOK.2",
996                                      new Object JavaDoc[]{dElement.fName});
997       }
998
999       //
1000
// Check occurrence range
1001
//
1002
if (!checkOccurrenceRange(dMin, dMax, bMin, bMax)) {
1003        throw new XMLSchemaException("rcase-NameAndTypeOK.3",
1004                                      new Object JavaDoc[]{
1005                                        dElement.fName,
1006                                        Integer.toString(dMin),
1007                                        dMax==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(dMax),
1008                                        Integer.toString(bMin),
1009                                        bMax==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(bMax)});
1010      }
1011
1012      //
1013
// Check for consistent fixed values
1014
//
1015
if (bElement.getConstraintType() == XSConstants.VC_FIXED) {
1016         // derived one has to have a fixed value
1017
if (dElement.getConstraintType() != XSConstants.VC_FIXED) {
1018            throw new XMLSchemaException("rcase-NameAndTypeOK.4.a",
1019                                         new Object JavaDoc[]{dElement.fName, bElement.fDefault.stringValue()});
1020         }
1021
1022         // get simple type
1023
boolean isSimple = false;
1024         if (dElement.fType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE ||
1025             ((XSComplexTypeDecl)dElement.fType).fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
1026             isSimple = true;
1027         }
1028
1029         // if there is no simple type, then compare based on string
1030
if (!isSimple && !bElement.fDefault.normalizedValue.equals(dElement.fDefault.normalizedValue) ||
1031             isSimple && !bElement.fDefault.actualValue.equals(dElement.fDefault.actualValue)) {
1032            throw new XMLSchemaException("rcase-NameAndTypeOK.4.b",
1033                                         new Object JavaDoc[]{dElement.fName,
1034                                                      dElement.fDefault.stringValue(),
1035                                                      bElement.fDefault.stringValue()});
1036         }
1037      }
1038
1039      //
1040
// Check identity constraints
1041
//
1042
checkIDConstraintRestriction(dElement, bElement);
1043
1044      //
1045
// Check for disallowed substitutions
1046
//
1047
int blockSet1 = dElement.fBlock;
1048      int blockSet2 = bElement.fBlock;
1049      if (((blockSet1 & blockSet2)!=blockSet2) ||
1050            (blockSet1==XSConstants.DERIVATION_NONE && blockSet2!=XSConstants.DERIVATION_NONE))
1051        throw new XMLSchemaException("rcase-NameAndTypeOK.6",
1052                                  new Object JavaDoc[]{dElement.fName});
1053
1054
1055      //
1056
// Check that the derived element's type is derived from the base's.
1057
//
1058
if (!checkTypeDerivationOk(dElement.fType, bElement.fType,
1059                                 (short)(XSConstants.DERIVATION_EXTENSION|XSConstants.DERIVATION_LIST|XSConstants.DERIVATION_UNION))) {
1060          throw new XMLSchemaException("rcase-NameAndTypeOK.7",
1061                                  new Object JavaDoc[]{dElement.fName, dElement.fType.getName(), bElement.fType.getName()});
1062      }
1063
1064    }
1065
1066
1067    private static void checkIDConstraintRestriction(XSElementDecl derivedElemDecl,
1068                                                     XSElementDecl baseElemDecl)
1069                                             throws XMLSchemaException {
1070        // TODO
1071
} // checkIDConstraintRestriction
1072

1073
1074    private static boolean checkOccurrenceRange(int min1, int max1, int min2, int max2) {
1075
1076      if ((min1 >= min2) &&
1077          ((max2==SchemaSymbols.OCCURRENCE_UNBOUNDED) ||
1078           (max1!=SchemaSymbols.OCCURRENCE_UNBOUNDED && max1<=max2)))
1079        return true;
1080      else
1081        return false;
1082    }
1083
1084    private static void checkNSCompat(XSElementDecl elem, int min1, int max1,
1085                                      XSWildcardDecl wildcard, int min2, int max2,
1086                                      boolean checkWCOccurrence)
1087                              throws XMLSchemaException {
1088
1089      // check Occurrence ranges
1090
if (checkWCOccurrence && !checkOccurrenceRange(min1,max1,min2,max2)) {
1091        throw new XMLSchemaException("rcase-NSCompat.2",
1092                                  new Object JavaDoc[]{
1093                                    elem.fName,
1094                                    Integer.toString(min1),
1095                                    max1==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max1),
1096                                    Integer.toString(min2),
1097                                    max2==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max2)});
1098      }
1099
1100      // check wildcard allows namespace of element
1101
if (!wildcard.allowNamespace(elem.fTargetNamespace)) {
1102        throw new XMLSchemaException("rcase-NSCompat.1",
1103                                  new Object JavaDoc[]{elem.fName,elem.fTargetNamespace});
1104      }
1105
1106    }
1107
1108    private static void checkNSSubset(XSWildcardDecl dWildcard, int min1, int max1,
1109                                      XSWildcardDecl bWildcard, int min2, int max2)
1110                              throws XMLSchemaException {
1111
1112      // check Occurrence ranges
1113
if (!checkOccurrenceRange(min1,max1,min2,max2)) {
1114        throw new XMLSchemaException("rcase-NSSubset.2", new Object JavaDoc[]{
1115                                     Integer.toString(min1),
1116                                     max1==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max1),
1117                                     Integer.toString(min2),
1118                                     max2==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max2)});
1119      }
1120
1121      // check wildcard subset
1122
if (!dWildcard.isSubsetOf(bWildcard)) {
1123         throw new XMLSchemaException("rcase-NSSubset.1", null);
1124      }
1125
1126      if (dWildcard.weakerProcessContents(bWildcard)) {
1127          throw new XMLSchemaException("rcase-NSSubset.3",
1128                                       new Object JavaDoc[]{dWildcard.getProcessContentsAsString(),
1129                                                    bWildcard.getProcessContentsAsString()});
1130      }
1131
1132    }
1133
1134
1135    private static void checkNSRecurseCheckCardinality(Vector JavaDoc children, int min1, int max1,
1136                                          SubstitutionGroupHandler dSGHandler,
1137                                          XSParticleDecl wildcard, int min2, int max2,
1138                                          boolean checkWCOccurrence)
1139                                          throws XMLSchemaException {
1140
1141
1142      // check Occurrence ranges
1143
if (checkWCOccurrence && !checkOccurrenceRange(min1,max1,min2,max2)) {
1144         throw new XMLSchemaException("rcase-NSRecurseCheckCardinality.2", new Object JavaDoc[]{
1145                                        Integer.toString(min1),
1146                                        max1==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max1),
1147                                        Integer.toString(min2),
1148                                        max2==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max2)});
1149      }
1150
1151      // Check that each member of the group is a valid restriction of the wildcard
1152
int count = children.size();
1153      try {
1154        for (int i = 0; i < count; i++) {
1155           XSParticleDecl particle1 = (XSParticleDecl)children.elementAt(i);
1156           particleValidRestriction(particle1, dSGHandler, wildcard, null, false);
1157
1158        }
1159      }
1160      // REVISIT: should we really just ignore original cause of this error?
1161
// how can we report it?
1162
catch (XMLSchemaException e) {
1163         throw new XMLSchemaException("rcase-NSRecurseCheckCardinality.1", null);
1164      }
1165
1166    }
1167
1168    private static void checkRecurse(Vector JavaDoc dChildren, int min1, int max1,
1169                                     SubstitutionGroupHandler dSGHandler,
1170                                     Vector JavaDoc bChildren, int min2, int max2,
1171                                     SubstitutionGroupHandler bSGHandler)
1172                                     throws XMLSchemaException {
1173
1174      // check Occurrence ranges
1175
if (!checkOccurrenceRange(min1,max1,min2,max2)) {
1176        throw new XMLSchemaException("rcase-Recurse.1", new Object JavaDoc[]{
1177                                       Integer.toString(min1),
1178                                       max1==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max1),
1179                                       Integer.toString(min2),
1180                                       max2==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max2)});
1181      }
1182
1183      int count1= dChildren.size();
1184      int count2= bChildren.size();
1185
1186      int current = 0;
1187      label: for (int i = 0; i<count1; i++) {
1188
1189        XSParticleDecl particle1 = (XSParticleDecl)dChildren.elementAt(i);
1190        for (int j = current; j<count2; j++) {
1191           XSParticleDecl particle2 = (XSParticleDecl)bChildren.elementAt(j);
1192           current +=1;
1193           try {
1194             particleValidRestriction(particle1, dSGHandler, particle2, bSGHandler);
1195             continue label;
1196           }
1197           catch (XMLSchemaException e) {
1198             if (!particle2.emptiable())
1199                throw new XMLSchemaException("rcase-Recurse.2", null);
1200           }
1201        }
1202        throw new XMLSchemaException("rcase-Recurse.2", null);
1203      }
1204
1205      // Now, see if there are some elements in the base we didn't match up
1206
for (int j=current; j < count2; j++) {
1207        XSParticleDecl particle2 = (XSParticleDecl)bChildren.elementAt(j);
1208        if (!particle2.emptiable()) {
1209          throw new XMLSchemaException("rcase-Recurse.2", null);
1210        }
1211      }
1212
1213    }
1214
1215    private static void checkRecurseUnordered(Vector JavaDoc dChildren, int min1, int max1,
1216                                       SubstitutionGroupHandler dSGHandler,
1217                                       Vector JavaDoc bChildren, int min2, int max2,
1218                                       SubstitutionGroupHandler bSGHandler)
1219                                       throws XMLSchemaException {
1220
1221
1222      // check Occurrence ranges
1223
if (!checkOccurrenceRange(min1,max1,min2,max2)) {
1224        throw new XMLSchemaException("rcase-RecurseUnordered.1", new Object JavaDoc[]{
1225                                       Integer.toString(min1),
1226                                       max1==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max1),
1227                                       Integer.toString(min2),
1228                                       max2==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max2)});
1229      }
1230
1231      int count1= dChildren.size();
1232      int count2 = bChildren.size();
1233
1234      boolean foundIt[] = new boolean[count2];
1235
1236      label: for (int i = 0; i<count1; i++) {
1237        XSParticleDecl particle1 = (XSParticleDecl)dChildren.elementAt(i);
1238
1239        for (int j = 0; j<count2; j++) {
1240           XSParticleDecl particle2 = (XSParticleDecl)bChildren.elementAt(j);
1241           try {
1242             particleValidRestriction(particle1, dSGHandler, particle2, bSGHandler);
1243             if (foundIt[j])
1244                throw new XMLSchemaException("rcase-RecurseUnordered.2", null);
1245             else
1246                foundIt[j]=true;
1247
1248             continue label;
1249           }
1250           catch (XMLSchemaException e) {
1251           }
1252        }
1253        // didn't find a match. Detect an error
1254
throw new XMLSchemaException("rcase-RecurseUnordered.2", null);
1255      }
1256
1257      // Now, see if there are some elements in the base we didn't match up
1258
for (int j=0; j < count2; j++) {
1259        XSParticleDecl particle2 = (XSParticleDecl)bChildren.elementAt(j);
1260        if (!foundIt[j] && !particle2.emptiable()) {
1261          throw new XMLSchemaException("rcase-RecurseUnordered.2", null);
1262        }
1263      }
1264
1265    }
1266
1267    private static void checkRecurseLax(Vector JavaDoc dChildren, int min1, int max1,
1268                                       SubstitutionGroupHandler dSGHandler,
1269                                       Vector JavaDoc bChildren, int min2, int max2,
1270                                       SubstitutionGroupHandler bSGHandler)
1271                                       throws XMLSchemaException {
1272
1273      // check Occurrence ranges
1274
if (!checkOccurrenceRange(min1,max1,min2,max2)) {
1275        throw new XMLSchemaException("rcase-RecurseLax.1", new Object JavaDoc[]{
1276                                       Integer.toString(min1),
1277                                       max1==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max1),
1278                                       Integer.toString(min2),
1279                                       max2==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max2)});
1280      }
1281
1282      int count1= dChildren.size();
1283      int count2 = bChildren.size();
1284
1285      int current = 0;
1286      label: for (int i = 0; i<count1; i++) {
1287
1288        XSParticleDecl particle1 = (XSParticleDecl)dChildren.elementAt(i);
1289        for (int j = current; j<count2; j++) {
1290           XSParticleDecl particle2 = (XSParticleDecl)bChildren.elementAt(j);
1291           current +=1;
1292           try {
1293             particleValidRestriction(particle1, dSGHandler, particle2, bSGHandler);
1294             continue label;
1295           }
1296           catch (XMLSchemaException e) {
1297           }
1298        }
1299        // didn't find a match. Detect an error
1300
throw new XMLSchemaException("rcase-RecurseLax.2", null);
1301
1302      }
1303
1304    }
1305
1306    private static void checkMapAndSum(Vector JavaDoc dChildren, int min1, int max1,
1307                                       SubstitutionGroupHandler dSGHandler,
1308                                       Vector JavaDoc bChildren, int min2, int max2,
1309                                       SubstitutionGroupHandler bSGHandler)
1310                                       throws XMLSchemaException {
1311
1312      // See if the sequence group is a valid restriction of the choice
1313

1314      // Here is an example of a valid restriction:
1315
// <choice minOccurs="2">
1316
// <a/>
1317
// <b/>
1318
// <c/>
1319
// </choice>
1320
//
1321
// <sequence>
1322
// <b/>
1323
// <a/>
1324
// </sequence>
1325

1326      // check Occurrence ranges
1327
if (!checkOccurrenceRange(min1,max1,min2,max2)) {
1328        throw new XMLSchemaException("rcase-MapAndSum.2",
1329                                     new Object JavaDoc[]{Integer.toString(min1),
1330                                        max1==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max1),
1331                                        Integer.toString(min2),
1332                                        max2==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max2)});
1333      }
1334
1335      int count1 = dChildren.size();
1336      int count2 = bChildren.size();
1337
1338      label: for (int i = 0; i<count1; i++) {
1339
1340        XSParticleDecl particle1 = (XSParticleDecl)dChildren.elementAt(i);
1341        for (int j = 0; j<count2; j++) {
1342           XSParticleDecl particle2 = (XSParticleDecl)bChildren.elementAt(j);
1343           try {
1344             particleValidRestriction(particle1, dSGHandler, particle2, bSGHandler);
1345             continue label;
1346           }
1347           catch (XMLSchemaException e) {
1348           }
1349        }
1350        // didn't find a match. Detect an error
1351
throw new XMLSchemaException("rcase-MapAndSum.1", null);
1352      }
1353    }
1354    // to check whether two element overlap, as defined in constraint UPA
1355
public static boolean overlapUPA(XSElementDecl element1,
1356                                     XSElementDecl element2,
1357                                     SubstitutionGroupHandler sgHandler) {
1358        // if the two element have the same name and namespace,
1359
if (element1.fName == element2.fName &&
1360            element1.fTargetNamespace == element2.fTargetNamespace) {
1361            return true;
1362        }
1363
1364        // or if there is an element decl in element1's substitution group,
1365
// who has the same name/namespace with element2
1366
XSElementDecl[] subGroup = sgHandler.getSubstitutionGroup(element1);
1367        for (int i = subGroup.length-1; i >= 0; i--) {
1368            if (subGroup[i].fName == element2.fName &&
1369                subGroup[i].fTargetNamespace == element2.fTargetNamespace) {
1370                return true;
1371            }
1372        }
1373
1374        // or if there is an element decl in element2's substitution group,
1375
// who has the same name/namespace with element1
1376
subGroup = sgHandler.getSubstitutionGroup(element2);
1377        for (int i = subGroup.length-1; i >= 0; i--) {
1378            if (subGroup[i].fName == element1.fName &&
1379                subGroup[i].fTargetNamespace == element1.fTargetNamespace) {
1380                return true;
1381            }
1382        }
1383
1384        return false;
1385    }
1386
1387    // to check whether an element overlaps with a wildcard,
1388
// as defined in constraint UPA
1389
public static boolean overlapUPA(XSElementDecl element,
1390                                     XSWildcardDecl wildcard,
1391                                     SubstitutionGroupHandler sgHandler) {
1392        // if the wildcard allows the element
1393
if (wildcard.allowNamespace(element.fTargetNamespace))
1394            return true;
1395
1396        // or if the wildcard allows any element in the substitution group
1397
XSElementDecl[] subGroup = sgHandler.getSubstitutionGroup(element);
1398        for (int i = subGroup.length-1; i >= 0; i--) {
1399            if (wildcard.allowNamespace(subGroup[i].fTargetNamespace))
1400                return true;
1401        }
1402
1403        return false;
1404    }
1405
1406    public static boolean overlapUPA(XSWildcardDecl wildcard1,
1407                                     XSWildcardDecl wildcard2) {
1408        // if the intersection of the two wildcard is not empty list
1409
XSWildcardDecl intersect = wildcard1.performIntersectionWith(wildcard2, wildcard1.fProcessContents);
1410        if (intersect == null ||
1411            intersect.fType != XSWildcardDecl.NSCONSTRAINT_LIST ||
1412            intersect.fNamespaceList.length != 0) {
1413            return true;
1414        }
1415
1416        return false;
1417    }
1418
1419    // call one of the above methods according to the type of decls
1420
public static boolean overlapUPA(Object JavaDoc decl1, Object JavaDoc decl2,
1421                                     SubstitutionGroupHandler sgHandler) {
1422        if (decl1 instanceof XSElementDecl) {
1423            if (decl2 instanceof XSElementDecl) {
1424                return overlapUPA((XSElementDecl)decl1,
1425                                  (XSElementDecl)decl2,
1426                                  sgHandler);
1427            } else {
1428                return overlapUPA((XSElementDecl)decl1,
1429                                  (XSWildcardDecl)decl2,
1430                                  sgHandler);
1431            }
1432        } else {
1433            if (decl2 instanceof XSElementDecl) {
1434                return overlapUPA((XSElementDecl)decl2,
1435                                  (XSWildcardDecl)decl1,
1436                                  sgHandler);
1437            } else {
1438                return overlapUPA((XSWildcardDecl)decl1,
1439                                  (XSWildcardDecl)decl2);
1440            }
1441        }
1442    }
1443
1444} // class XSContraints
1445
Popular Tags