KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > org > apache > xerces > internal > impl > xs > XSConstraints


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 1999-2004 The Apache Software Foundation. All rights
6  * 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
58 package com.sun.org.apache.xerces.internal.impl.xs;
59
60 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
61 import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException;
62 import com.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo;
63 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
64 import com.sun.org.apache.xerces.internal.impl.xs.models.CMBuilder;
65 import com.sun.org.apache.xerces.internal.impl.xs.models.XSCMValidator;
66 import com.sun.org.apache.xerces.internal.impl.xs.util.SimpleLocator;
67 import com.sun.org.apache.xerces.internal.xs.XSConstants;
68 import com.sun.org.apache.xerces.internal.xs.XSObjectList;
69 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
70 import com.sun.org.apache.xerces.internal.impl.dv.ValidationContext;
71 import com.sun.org.apache.xerces.internal.util.SymbolHash;
72 import java.util.Vector JavaDoc;
73
74 /**
75  * Constaints shared by traversers and validator
76  *
77  * @author Sandy Gao, IBM
78  *
79  * @version $Id: XSConstraints.java,v 1.37 2004/02/03 17:27:45 sandygao Exp $
80  */

81 public class XSConstraints {
82
83     static final int OCCURRENCE_UNKNOWN = SchemaSymbols.OCCURRENCE_UNBOUNDED-1;
84     static final XSSimpleType STRING_TYPE = (XSSimpleType)SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(SchemaSymbols.ATTVAL_STRING);
85
86     /**
87      * check whether derived is valid derived from base, given a subset
88      * of {restriction, extension}.B
89      */

90     public static boolean checkTypeDerivationOk(XSTypeDefinition derived, XSTypeDefinition base, short block) {
91         // if derived is anyType, then it's valid only if base is anyType too
92
if (derived == SchemaGrammar.fAnyType)
93             return derived == base;
94         // if derived is anySimpleType, then it's valid only if the base
95
// is ur-type
96
if (derived == SchemaGrammar.fAnySimpleType) {
97             return (base == SchemaGrammar.fAnyType ||
98                     base == SchemaGrammar.fAnySimpleType);
99         }
100
101         // if derived is simple type
102
if (derived.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
103             // if base is complex type
104
if (base.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
105                 // if base is anyType, change base to anySimpleType,
106
// otherwise, not valid
107
if (base == SchemaGrammar.fAnyType)
108                     base = SchemaGrammar.fAnySimpleType;
109                 else
110                     return false;
111             }
112             return checkSimpleDerivation((XSSimpleType)derived,
113                                          (XSSimpleType)base, block);
114         } else {
115             return checkComplexDerivation((XSComplexTypeDecl)derived, base, block);
116         }
117     }
118
119     /**
120      * check whether simple type derived is valid derived from base,
121      * given a subset of {restriction, extension}.
122      */

123     public static boolean checkSimpleDerivationOk(XSSimpleType derived, XSTypeDefinition base, short block) {
124         // if derived is anySimpleType, then it's valid only if the base
125
// is ur-type
126
if (derived == SchemaGrammar.fAnySimpleType) {
127             return (base == SchemaGrammar.fAnyType ||
128                     base == SchemaGrammar.fAnySimpleType);
129         }
130
131         // if base is complex type
132
if (base.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
133             // if base is anyType, change base to anySimpleType,
134
// otherwise, not valid
135
if (base == SchemaGrammar.fAnyType)
136                 base = SchemaGrammar.fAnySimpleType;
137             else
138                 return false;
139         }
140         return checkSimpleDerivation((XSSimpleType)derived,
141                                      (XSSimpleType)base, block);
142     }
143
144     /**
145      * check whether complex type derived is valid derived from base,
146      * given a subset of {restriction, extension}.
147      */

148     public static boolean checkComplexDerivationOk(XSComplexTypeDecl derived, XSTypeDefinition base, short block) {
149         // if derived is anyType, then it's valid only if base is anyType too
150
if (derived == SchemaGrammar.fAnyType)
151             return derived == base;
152         return checkComplexDerivation((XSComplexTypeDecl)derived, base, block);
153     }
154
155     /**
156      * Note: this will be a private method, and it assumes that derived is not
157      * anySimpleType, and base is not anyType. Another method will be
158      * introduced for public use, which will call this method.
159      */

160     private static boolean checkSimpleDerivation(XSSimpleType derived, XSSimpleType base, short block) {
161         // 1 They are the same type definition.
162
if (derived == base)
163             return true;
164
165         // 2 All of the following must be true:
166
// 2.1 restriction is not in the subset, or in the {final} of its own {base type definition};
167
if ((block & XSConstants.DERIVATION_RESTRICTION) != 0 ||
168             (derived.getBaseType().getFinal() & XSConstants.DERIVATION_RESTRICTION) != 0) {
169             return false;
170         }
171
172         // 2.2 One of the following must be true:
173
// 2.2.1 D's base type definition is B.
174
XSSimpleType directBase = (XSSimpleType)derived.getBaseType();
175         if (directBase == base)
176             return true;
177
178         // 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.
179
if (directBase != SchemaGrammar.fAnySimpleType &&
180             checkSimpleDerivation(directBase, base, block)) {
181             return true;
182         }
183
184         // 2.2.3 D's {variety} is list or union and B is the simple ur-type definition.
185
if ((derived.getVariety() == XSSimpleType.VARIETY_LIST ||
186              derived.getVariety() == XSSimpleType.VARIETY_UNION) &&
187             base == SchemaGrammar.fAnySimpleType) {
188             return true;
189         }
190
191         // 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.
192
if (base.getVariety() == XSSimpleType.VARIETY_UNION) {
193             XSObjectList subUnionMemberDV = base.getMemberTypes();
194             int subUnionSize = subUnionMemberDV.getLength();
195             for (int i=0; i<subUnionSize; i++) {
196                 base = (XSSimpleType)subUnionMemberDV.item(i);
197                 if (checkSimpleDerivation(derived, base, block))
198                     return true;
199             }
200         }
201
202         return false;
203     }
204
205     /**
206      * Note: this will be a private method, and it assumes that derived is not
207      * anyType. Another method will be introduced for public use,
208      * which will call this method.
209      */

210     private static boolean checkComplexDerivation(XSComplexTypeDecl derived, XSTypeDefinition base, short block) {
211         // 2.1 B and D must be the same type definition.
212
if (derived == base)
213             return true;
214
215         // 1 If B and D are not the same type definition, then the {derivation method} of D must not be in the subset.
216
if ((derived.fDerivedBy & block) != 0)
217             return false;
218
219         // 2 One of the following must be true:
220
XSTypeDefinition directBase = derived.fBaseType;
221         // 2.2 B must be D's {base type definition}.
222
if (directBase == base)
223             return true;
224
225         // 2.3 All of the following must be true:
226
// 2.3.1 D's {base type definition} must not be the ur-type definition.
227
if (directBase == SchemaGrammar.fAnyType ||
228             directBase == SchemaGrammar.fAnySimpleType) {
229             return false;
230         }
231
232         // 2.3.2 The appropriate case among the following must be true:
233
// 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.
234
if (directBase.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE)
235             return checkComplexDerivation((XSComplexTypeDecl)directBase, base, block);
236
237         // 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).
238
if (directBase.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
239             // if base is complex type
240
if (base.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) {
241                 // if base is anyType, change base to anySimpleType,
242
// otherwise, not valid
243
if (base == SchemaGrammar.fAnyType)
244                     base = SchemaGrammar.fAnySimpleType;
245                 else
246                     return false;
247             }
248             return checkSimpleDerivation((XSSimpleType)directBase,
249                                          (XSSimpleType)base, block);
250         }
251
252         return false;
253     }
254
255     /**
256      * check whether a value is a valid default for some type
257      * returns the compiled form of the value
258      * The parameter value could be either a String or a ValidatedInfo object
259      */

260     public static Object JavaDoc ElementDefaultValidImmediate(XSTypeDefinition type, String JavaDoc value, ValidationContext context, ValidatedInfo vinfo) {
261
262         XSSimpleType dv = null;
263
264         // e-props-correct
265
// For a string to be a valid default with respect to a type definition the appropriate case among the following must be true:
266
// 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).
267
if (type.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) {
268             dv = (XSSimpleType)type;
269         }
270
271         // 2 If the type definition is a complex type definition, then all of the following must be true:
272
else {
273             // 2.1 its {content type} must be a simple type definition or mixed.
274
XSComplexTypeDecl ctype = (XSComplexTypeDecl)type;
275             // 2.2 The appropriate case among the following must be true:
276
// 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).
277
if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) {
278                 dv = ctype.fXSSimpleType;
279             }
280             // 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).
281
else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_MIXED) {
282                 if (!((XSParticleDecl)ctype.getParticle()).emptiable())
283                     return null;
284             }
285             else {
286                 return null;
287             }
288         }
289
290         // get the simple type declaration, and validate
291
Object JavaDoc actualValue = null;
292         if (dv == null) {
293             // complex type with mixed. to make sure that we store correct
294
// information in vinfo and return the correct value, we use
295
// "string" type for validation
296
dv = STRING_TYPE;
297         }
298         try {
299             // validate the original lexical rep, and set the actual value
300
actualValue = dv.validate(value, context, vinfo);
301             // validate the canonical lexical rep
302
if (vinfo != null)
303                 actualValue = dv.validate(vinfo.stringValue(), context, vinfo);
304         } catch (InvalidDatatypeValueException ide) {
305             return null;
306         }
307
308         return actualValue;
309     }
310
311     static void reportSchemaError(XMLErrorReporter errorReporter,
312                                   SimpleLocator loc,
313                                   String JavaDoc key, Object JavaDoc[] args) {
314         if (loc != null) {
315             errorReporter.reportError(loc, XSMessageFormatter.SCHEMA_DOMAIN,
316                                       key, args, XMLErrorReporter.SEVERITY_ERROR);
317         }
318         else {
319             errorReporter.reportError(XSMessageFormatter.SCHEMA_DOMAIN,
320                                       key, args, XMLErrorReporter.SEVERITY_ERROR);
321         }
322     }
323
324     /**
325      * used to check the 3 constraints against each complex type
326      * (should be each model group):
327      * Unique Particle Attribution, Particle Derivation (Restriction),
328      * Element Declrations Consistent.
329      */

330     public static void fullSchemaChecking(XSGrammarBucket grammarBucket,
331                                           SubstitutionGroupHandler SGHandler,
332                                           CMBuilder cmBuilder,
333                                           XMLErrorReporter errorReporter) {
334         // get all grammars, and put all substitution group information
335
// in the substitution group handler
336
SGHandler.reset();
337         SchemaGrammar[] grammars = grammarBucket.getGrammars();
338         for (int i = grammars.length-1; i >= 0; i--) {
339             SGHandler.addSubstitutionGroup(grammars[i].getSubstitutionGroups());
340         }
341
342         XSParticleDecl fakeDerived = new XSParticleDecl();
343         XSParticleDecl fakeBase = new XSParticleDecl();
344         fakeDerived.fType = XSParticleDecl.PARTICLE_MODELGROUP;
345         fakeBase.fType = XSParticleDecl.PARTICLE_MODELGROUP;
346         // before worrying about complexTypes, let's get
347
// groups redefined by restriction out of the way.
348
for (int g = grammars.length-1; g >= 0; g--) {
349             XSGroupDecl [] redefinedGroups = grammars[g].getRedefinedGroupDecls();
350             SimpleLocator [] rgLocators = grammars[g].getRGLocators();
351             for(int i=0; i<redefinedGroups.length; ) {
352                 XSGroupDecl derivedGrp = redefinedGroups[i++];
353                 XSModelGroupImpl derivedMG = derivedGrp.fModelGroup;
354                 XSGroupDecl baseGrp = redefinedGroups[i++];
355                 XSModelGroupImpl baseMG = baseGrp.fModelGroup;
356                 if(baseMG == null) {
357                     if(derivedMG != null) { // can't be a restriction!
358
reportSchemaError(errorReporter, rgLocators[i/2-1],
359                                           "src-redefine.6.2.2",
360                                           new Object JavaDoc[]{derivedGrp.fName, "rcase-Recurse.2"});
361                     }
362                 } else {
363                     fakeDerived.fValue = derivedMG;
364                     fakeBase.fValue = baseMG;
365                     try {
366                         particleValidRestriction(fakeDerived, SGHandler, fakeBase, SGHandler);
367                     } catch (XMLSchemaException e) {
368                         String JavaDoc key = e.getKey();
369                         reportSchemaError(errorReporter, rgLocators[i/2-1],
370                                           key,
371                                           e.getArgs());
372                         reportSchemaError(errorReporter, rgLocators[i/2-1],
373                                           "src-redefine.6.2.2",
374                                           new Object JavaDoc[]{derivedGrp.fName, key});
375                     }
376                 }
377             }
378         }
379
380         // for each complex type, check the 3 constraints.
381
// types need to be checked
382
XSComplexTypeDecl[] types;
383         SimpleLocator [] ctLocators;
384         // to hold the errors
385
// REVISIT: do we want to report all errors? or just one?
386
//XMLSchemaError1D errors = new XMLSchemaError1D();
387
// whether need to check this type again;
388
// whether only do UPA checking
389
boolean further, fullChecked;
390         // if do all checkings, how many need to be checked again.
391
int keepType;
392         // i: grammar; j: type; k: error
393
// for all grammars
394
SymbolHash elemTable = new SymbolHash();
395         for (int i = grammars.length-1, j, k; i >= 0; i--) {
396             // get whether to skip EDC, and types need to be checked
397
keepType = 0;
398             fullChecked = grammars[i].fFullChecked;
399             types = grammars[i].getUncheckedComplexTypeDecls();
400             ctLocators = grammars[i].getUncheckedCTLocators();
401             // for each type
402
for (j = types.length-1; j >= 0; j--) {
403                 // if we've already full-checked this grammar, then
404
// skip the EDC constraint
405
if (!fullChecked) {
406                 // 1. Element Decl Consistent
407
if (types[j].fParticle!=null) {
408                     elemTable.clear();
409                     try {
410                       checkElementDeclsConsistent(types[j], types[j].fParticle,
411                                                   elemTable, SGHandler);
412                     }
413                     catch (XMLSchemaException e) {
414                       reportSchemaError(errorReporter, ctLocators[j],
415                                         e.getKey(),
416                                         e.getArgs());
417                     }
418                   }
419                 }
420
421                 // 2. Particle Derivation
422

423                 if (types[j].fBaseType != null &&
424                     types[j].fBaseType != SchemaGrammar.fAnyType &&
425                     types[j].fDerivedBy == XSConstants.DERIVATION_RESTRICTION &&
426                     (types[j].fBaseType instanceof XSComplexTypeDecl)) {
427
428                   XSParticleDecl derivedParticle=types[j].fParticle;
429                   XSParticleDecl baseParticle=
430                     ((XSComplexTypeDecl)(types[j].fBaseType)).fParticle;
431                   if (derivedParticle==null && (!(baseParticle==null ||
432                                                baseParticle.emptiable()))) {
433                     reportSchemaError(errorReporter,ctLocators[j],
434                                       "derivation-ok-restriction.5.3.2",
435                                       new Object JavaDoc[]{types[j].fName, types[j].fBaseType.getName()});
436                   }
437                   else if (derivedParticle!=null &&
438                            baseParticle!=null)
439
440                     try {
441                       particleValidRestriction(types[j].fParticle,
442                                                SGHandler,
443                                                ((XSComplexTypeDecl)(types[j].fBaseType)).fParticle,
444                                                SGHandler);
445                     } catch (XMLSchemaException e) {
446                       reportSchemaError(errorReporter, ctLocators[j],
447                                         e.getKey(),
448                                         e.getArgs());
449                       reportSchemaError(errorReporter, ctLocators[j],
450                                         "derivation-ok-restriction.5.4.2",
451                                         new Object JavaDoc[]{types[j].fName});
452                     }
453                 }
454
455                 // 3. UPA
456
// get the content model and check UPA
457
XSCMValidator cm = types[j].getContentModel(cmBuilder);
458                 further = false;
459                 if (cm != null) {
460                     try {
461                         further = cm.checkUniqueParticleAttribution(SGHandler);
462                     } catch (XMLSchemaException e) {
463                         reportSchemaError(errorReporter, ctLocators[j],
464                                           e.getKey(),
465                                           e.getArgs());
466                     }
467                 }
468                 // now report all errors
469
// REVISIT: do we want to report all errors? or just one?
470
/*for (k = errors.getErrorCodeNum()-1; k >= 0; k--) {
471                     reportSchemaError(errorReporter, ctLocators[j],
472                                       errors.getErrorCode(k),
473                                       errors.getArgs(k));
474                 }*/

475
476                 // if we are doing all checkings, and this one needs further
477
// checking, store it in the type array.
478
if (!fullChecked && further)
479                     types[keepType++] = types[j];
480
481                 // clear errors for the next type.
482
// REVISIT: do we want to report all errors? or just one?
483
//errors.clear();
484
}
485             // we've done with the types in this grammar. if we are checking
486
// all constraints, need to trim type array to a proper size:
487
// only contain those need further checking.
488
// and mark this grammar that it only needs UPA checking.
489
if (!fullChecked) {
490                 grammars[i].setUncheckedTypeNum(keepType);
491                 grammars[i].fFullChecked = true;
492             }
493         }
494     }
495
496     /*
497        Check that a given particle is a valid restriction of a base particle.
498     */

499
500     public static void checkElementDeclsConsistent(XSComplexTypeDecl type,
501                                      XSParticleDecl particle,
502                                      SymbolHash elemDeclHash,
503                                      SubstitutionGroupHandler sgHandler)
504                                      throws XMLSchemaException {
505
506        // check for elements in the tree with the same name and namespace
507

508        int pType = particle.fType;
509
510        if (pType == XSParticleDecl.PARTICLE_WILDCARD)
511           return;
512
513        if (pType == XSParticleDecl.PARTICLE_ELEMENT) {
514           XSElementDecl elem = (XSElementDecl)(particle.fValue);
515           findElemInTable(type, elem, elemDeclHash);
516
517           if (elem.fScope == XSConstants.SCOPE_GLOBAL) {
518              // Check for subsitution groups.
519
XSElementDecl[] subGroup = sgHandler.getSubstitutionGroup(elem);
520              for (int i = 0; i < subGroup.length; i++) {
521                findElemInTable(type, subGroup[i], elemDeclHash);
522              }
523           }
524           return;
525        }
526
527        XSModelGroupImpl group = (XSModelGroupImpl)particle.fValue;
528        for (int i = 0; i < group.fParticleCount; i++)
529            checkElementDeclsConsistent(type, group.fParticles[i], elemDeclHash, sgHandler);
530     }
531
532     public static void findElemInTable(XSComplexTypeDecl type, XSElementDecl elem,
533                                        SymbolHash elemDeclHash)
534                                        throws XMLSchemaException {
535
536         // How can we avoid this concat? LM.
537
String JavaDoc name = elem.fName + "," + elem.fTargetNamespace;
538
539         XSElementDecl existingElem = null;
540         if ((existingElem = (XSElementDecl)(elemDeclHash.get(name))) == null) {
541           // just add it in
542
elemDeclHash.put(name, elem);
543         }
544         else {
545           // If this is the same check element, we're O.K.
546
if (elem == existingElem)
547             return;
548
549           if (elem.fType != existingElem.fType) {
550             // Types are not the same
551
throw new XMLSchemaException("cos-element-consistent",
552                       new Object JavaDoc[] {type.fName, elem.fName});
553
554           }
555         }
556     }
557
558     /*
559        Check that a given particle is a valid restriction of a base particle.
560     */

561     private static void particleValidRestriction(XSParticleDecl dParticle,
562                                      SubstitutionGroupHandler dSGHandler,
563                                      XSParticleDecl bParticle,
564                                      SubstitutionGroupHandler bSGHandler)
565                                      throws XMLSchemaException {
566        particleValidRestriction(dParticle, dSGHandler, bParticle, bSGHandler, true);
567     }
568
569     private static void particleValidRestriction(XSParticleDecl dParticle,
570                                      SubstitutionGroupHandler dSGHandler,
571                                      XSParticleDecl bParticle,
572                                      SubstitutionGroupHandler bSGHandler,
573                                      boolean checkWCOccurrence)
574                                      throws XMLSchemaException {
575
576        Vector JavaDoc dChildren = null;
577        Vector JavaDoc bChildren = null;
578        int dMinEffectiveTotalRange=OCCURRENCE_UNKNOWN;
579        int dMaxEffectiveTotalRange=OCCURRENCE_UNKNOWN;
580
581
582        // Check for empty particles. If either base or derived particle is empty,
583
// (and the other isn't) it's an error.
584
if (dParticle.isEmpty() && !bParticle.emptiable()) {
585          throw new XMLSchemaException("cos-particle-restrict.a", null);
586        }
587        else if (!dParticle.isEmpty() && bParticle.isEmpty()) {
588          throw new XMLSchemaException("cos-particle-restrict.b", null);
589        }
590
591        //
592
// Do setup prior to invoking the Particle (Restriction) cases.
593
// This involves:
594
// - removing pointless occurrences for groups, and retrieving a vector of
595
// non-pointless children
596
// - turning top-level elements with substitution groups into CHOICE groups.
597
//
598

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

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

1350      // Here is an example of a valid restriction:
1351
// <choice minOccurs="2">
1352
// <a/>
1353
// <b/>
1354
// <c/>
1355
// </choice>
1356
//
1357
// <sequence>
1358
// <b/>
1359
// <a/>
1360
// </sequence>
1361

1362      // check Occurrence ranges
1363
if (!checkOccurrenceRange(min1,max1,min2,max2)) {
1364        throw new XMLSchemaException("rcase-MapAndSum.2",
1365                                     new Object JavaDoc[]{Integer.toString(min1),
1366                                        max1==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max1),
1367                                        Integer.toString(min2),
1368                                        max2==SchemaSymbols.OCCURRENCE_UNBOUNDED?"unbounded":Integer.toString(max2)});
1369      }
1370
1371      int count1 = dChildren.size();
1372      int count2 = bChildren.size();
1373
1374      label: for (int i = 0; i<count1; i++) {
1375
1376        XSParticleDecl particle1 = (XSParticleDecl)dChildren.elementAt(i);
1377        for (int j = 0; j<count2; j++) {
1378           XSParticleDecl particle2 = (XSParticleDecl)bChildren.elementAt(j);
1379           try {
1380             particleValidRestriction(particle1, dSGHandler, particle2, bSGHandler);
1381             continue label;
1382           }
1383           catch (XMLSchemaException e) {
1384           }
1385        }
1386        // didn't find a match. Detect an error
1387
throw new XMLSchemaException("rcase-MapAndSum.1", null);
1388      }
1389    }
1390    // to check whether two element overlap, as defined in constraint UPA
1391
public static boolean overlapUPA(XSElementDecl element1,
1392                                     XSElementDecl element2,
1393                                     SubstitutionGroupHandler sgHandler) {
1394        // if the two element have the same name and namespace,
1395
if (element1.fName == element2.fName &&
1396            element1.fTargetNamespace == element2.fTargetNamespace) {
1397            return true;
1398        }
1399
1400        // or if there is an element decl in element1's substitution group,
1401
// who has the same name/namespace with element2
1402
XSElementDecl[] subGroup = sgHandler.getSubstitutionGroup(element1);
1403        for (int i = subGroup.length-1; i >= 0; i--) {
1404            if (subGroup[i].fName == element2.fName &&
1405                subGroup[i].fTargetNamespace == element2.fTargetNamespace) {
1406                return true;
1407            }
1408        }
1409
1410        // or if there is an element decl in element2's substitution group,
1411
// who has the same name/namespace with element1
1412
subGroup = sgHandler.getSubstitutionGroup(element2);
1413        for (int i = subGroup.length-1; i >= 0; i--) {
1414            if (subGroup[i].fName == element1.fName &&
1415                subGroup[i].fTargetNamespace == element1.fTargetNamespace) {
1416                return true;
1417            }
1418        }
1419
1420        return false;
1421    }
1422
1423    // to check whether an element overlaps with a wildcard,
1424
// as defined in constraint UPA
1425
public static boolean overlapUPA(XSElementDecl element,
1426                                     XSWildcardDecl wildcard,
1427                                     SubstitutionGroupHandler sgHandler) {
1428        // if the wildcard allows the element
1429
if (wildcard.allowNamespace(element.fTargetNamespace))
1430            return true;
1431
1432        // or if the wildcard allows any element in the substitution group
1433
XSElementDecl[] subGroup = sgHandler.getSubstitutionGroup(element);
1434        for (int i = subGroup.length-1; i >= 0; i--) {
1435            if (wildcard.allowNamespace(subGroup[i].fTargetNamespace))
1436                return true;
1437        }
1438
1439        return false;
1440    }
1441
1442    public static boolean overlapUPA(XSWildcardDecl wildcard1,
1443                                     XSWildcardDecl wildcard2) {
1444        // if the intersection of the two wildcard is not empty list
1445
XSWildcardDecl intersect = wildcard1.performIntersectionWith(wildcard2, wildcard1.fProcessContents);
1446        if (intersect == null ||
1447            intersect.fType != XSWildcardDecl.NSCONSTRAINT_LIST ||
1448            intersect.fNamespaceList.length != 0) {
1449            return true;
1450        }
1451
1452        return false;
1453    }
1454
1455    // call one of the above methods according to the type of decls
1456
public static boolean overlapUPA(Object JavaDoc decl1, Object JavaDoc decl2,
1457                                     SubstitutionGroupHandler sgHandler) {
1458        if (decl1 instanceof XSElementDecl) {
1459            if (decl2 instanceof XSElementDecl) {
1460                return overlapUPA((XSElementDecl)decl1,
1461                                  (XSElementDecl)decl2,
1462                                  sgHandler);
1463            } else {
1464                return overlapUPA((XSElementDecl)decl1,
1465                                  (XSWildcardDecl)decl2,
1466                                  sgHandler);
1467            }
1468        } else {
1469            if (decl2 instanceof XSElementDecl) {
1470                return overlapUPA((XSElementDecl)decl2,
1471                                  (XSWildcardDecl)decl1,
1472                                  sgHandler);
1473            } else {
1474                return overlapUPA((XSWildcardDecl)decl1,
1475                                  (XSWildcardDecl)decl2);
1476            }
1477        }
1478    }
1479
1480} // class XSContraints
1481
Popular Tags