KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xquark > schema > Particle


1 /*
2  * This file belongs to the XQuark distribution.
3  * Copyright (C) 2003 Universite de Versailles Saint-Quentin.
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307.
18  * You can also get it at http://www.gnu.org/licenses/lgpl.html
19  *
20  * For more information on this software, see http://www.xquark.org.
21  */

22
23 package org.xquark.schema;
24
25 import java.util.*;
26
27 /**
28  * class for Particle.
29  *
30  * <p>This is the implementation of the Particle.
31  * The following properties are defined:</p>
32  * <p> 1. min occurs : a non-negative integer.</p>
33  * <p> 2. max occurs : either a non-negative integer or unbounded.</p>
34  * <p> 3. term : one of a model group, a wildcard, or an element declaration. </p>
35  *
36  * <p>See XML Schema Part 1: Structures 3.9
37  * W3C Recommendation 2 May 2001</p>
38  *
39  * @see org.xquark.xml.schema.ModelGroup
40  * @see org.xquark.xml.schema.Wildcard
41  * @see org.xquark.xml.schema.ElementDeclaration
42  */

43 public final class Particle implements SchemaVisitable, Cloneable JavaDoc {
44 private static final String JavaDoc RCSRevision = "$Revision: 1.1 $";
45 private static final String JavaDoc RCSName = "$Name: $";
46   
47   private int minOccurs = 1;
48   private int maxOccurs = 1;
49   private Object JavaDoc term;
50
51   private int minExtent = 0;
52   private int maxExtent = 0;
53   private ArrayList firstElements = new ArrayList();
54   private ArrayList firstWildcards = null;
55
56   /**
57    * Create a new Particle.
58    *
59    * @param term The term, one of a model group, a wildcard, or an element declaration.
60    */

61   public Particle(Object JavaDoc term) {
62     this.term = term;
63   }
64
65   public Object JavaDoc clone() throws CloneNotSupportedException JavaDoc{
66     Object JavaDoc result = null;
67     result = super.clone();
68     ((Particle)result).firstElements = new ArrayList();
69     return result;
70   }
71
72   public void accept(SchemaVisitor visitor) throws SchemaException {
73     visitor.visit(this);
74   }
75
76   public String JavaDoc toString() {
77     String JavaDoc result = "#<Particle "+term;
78     Iterator it = firstElements.iterator();
79     if (it.hasNext()) result+=("["+it.next());
80     while (it.hasNext()) result+=(", "+it.next());
81     return result+"]>";
82   }
83   
84   public boolean equals(Particle p) {
85     if ( this == p ) return true;
86     if ( p == null ) return false;
87     if ( this.minOccurs != p.minOccurs || this.maxOccurs != p.maxOccurs ||
88          this.minExtent != p.minExtent || this.maxExtent != p.maxExtent )
89       return false;
90     
91     if ( this.term == p.term ) return true;
92     
93     if ( this.term instanceof ElementDeclaration && p.term instanceof ElementDeclaration )
94     {
95        if ( ((ElementDeclaration)this.term).equals((ElementDeclaration)p.term) ) return true;
96     }
97     
98     if ( this.term instanceof Wildcard && p.term instanceof Wildcard ) {
99        if ( ((Wildcard)this.term).equals((Wildcard)p.term) ) return true;
100     }
101     
102     if ( (this.term instanceof AllModelGroup && p.term instanceof AllModelGroup) ||
103          (this.term instanceof ChoiceModelGroup && p.term instanceof ChoiceModelGroup) ||
104          (this.term instanceof SequenceModelGroup && p.term instanceof SequenceModelGroup) ) {
105       ModelGroup mg1 = (ModelGroup)this.term;
106       ModelGroup mg2 = (ModelGroup)p.term;
107       if ( mg1.size() != mg2.size() ) return false;
108       java.util.Iterator JavaDoc it1 = mg1.iterator();
109       java.util.Iterator JavaDoc it2 = mg2.iterator();
110       while ( it1.hasNext() ) {
111         Particle p1 = (Particle) it1.next();
112         Particle p2 = (Particle) it2.next();
113         if ( p1.equals(p2) == false ) return false;
114       }
115       return true;
116     }
117     
118     return false;
119   }
120   
121   /**
122    * Look up the min occurs
123    *
124    * @return The min occurs, a non-negative integer.
125    */

126   public int getMinOccurs() {
127     return minOccurs;
128   }
129
130   /**
131    * Look up the max occurs
132    * max occurs is a non-negative integer. If max occurs is the maxmum number of integer,
133    * it means that max occurs is unbounded.
134    *
135    * @return The max occurs.
136    */

137   public int getMaxOccurs() {
138     return maxOccurs;
139   }
140
141   public boolean isMaxOccursUnbounded() {
142     return maxOccurs == Integer.MAX_VALUE;
143   }
144
145   /**
146    * Look up the term
147    *
148    * @return The term, one of a model group, a wildcard, or an element declaration.
149    */

150   public Object JavaDoc getTerm() {
151     return term;
152   }
153
154   public int getMinExtent() {
155     return minExtent;
156   }
157
158   public int getMaxExtent() {
159     return maxExtent;
160   }
161
162   public boolean isEmptiable() {
163     return minExtent == 0;
164   }
165
166   public void setMinOccurs(int min) {
167     minOccurs = min;
168   }
169
170   public void setMaxOccurs(int max) {
171     maxOccurs = max;
172   }
173
174   public void setMaxOccursUnbounded() {
175     setMaxOccurs(Integer.MAX_VALUE);
176   }
177   
178   void setTerm(Object JavaDoc term) {
179     this.term = term;
180   }
181   
182   void setMinExtent(int extent) {
183     minExtent = extent;
184   }
185
186   void setMaxExtent(int extent) {
187     maxExtent = extent;
188   }
189
190   void setMaxExtentUnbounded(int extent) {
191     setMaxExtent(Integer.MAX_VALUE);
192   }
193
194   void addFirstElement(ElementDeclaration decl) {
195     firstElements.add(decl);
196   }
197   
198   void addFirstElements(Collection elements) {
199     firstElements.addAll(elements);
200   }
201   
202   void addFirstWildcard(Wildcard w) {
203     if (firstWildcards == null) firstWildcards = new ArrayList();
204     firstWildcards.add(w);
205   }
206   
207   void addFirstWildcards(Collection wildcards) {
208     if (wildcards == null) return;
209     if (firstWildcards == null) firstWildcards = new ArrayList();
210     firstWildcards.addAll(wildcards);
211   }
212   
213   List getFirstElements() {
214     return firstElements;
215   }
216   
217   public List getFirstWildcards() {
218     return firstWildcards;
219   }
220
221   public List firstValidElements() {
222     ArrayList result = new ArrayList();
223     fillFirstValidElements(result);
224     return result;
225   }
226
227   void fillFirstValidElements(List result) {
228     Iterator it = firstElements.iterator();
229     while (it.hasNext()) {
230       ElementDeclaration decl = (ElementDeclaration)it.next();
231       // add the element in firstElements
232
if (!decl.isAbstract()) result.add(decl);
233       // add substitution elements
234
decl.fillAllConcreteSubstitutionElements(result);
235     }
236   }
237
238     // Created
239
// add substitutionGroup treating
240
//
241
public boolean hasNextElement(String JavaDoc namespace, String JavaDoc localName) {
242     Iterator it = firstElements.iterator();
243     while (it.hasNext()) {
244       ElementDeclaration decl = (ElementDeclaration)it.next();
245       if (decl.hasName(namespace, localName)) return true;
246       if (decl.getSubstitutionElement(namespace, localName) != null) return true;
247     }
248     if (firstWildcards != null) {
249       it = firstWildcards.iterator();
250       while (it.hasNext()) {
251         Wildcard w = (Wildcard)it.next();
252         if (w.isAllowed(namespace)) return true;
253       }
254     }
255     
256     return false;
257   }
258   
259   private Particle substitutionTreating() {
260     if ( this.term instanceof Wildcard ) return this;
261     else if ( this.term instanceof ElementDeclaration ) {
262       List subList = ((ElementDeclaration)this.term).getSubstitutionElementList();
263       if ( subList == null || subList.size() == 0 ) return this;
264       ChoiceModelGroup choiceGroup = new ChoiceModelGroup();
265       Particle choiceParticle = new Particle(choiceGroup);
266       choiceParticle.minOccurs = this.minOccurs;
267       choiceParticle.maxOccurs = this.maxOccurs;
268       choiceParticle.minExtent = this.minExtent;
269       choiceParticle.maxExtent = this.maxExtent;
270       Particle newThis = new Particle(this.term);
271       newThis.minOccurs = 1;
272       newThis.maxOccurs = 1;
273       newThis.minExtent = 1;
274       newThis.maxExtent = 1;
275       choiceGroup.add(newThis);
276       Iterator it = subList.iterator();
277       while ( it.hasNext() ) {
278         Particle p = new Particle(it.next());
279         p.minOccurs = 1;
280         p.maxOccurs = 1;
281         p.minExtent = 1;
282         p.maxExtent = 1;
283         choiceGroup.add(p);
284       }
285       return choiceParticle;
286     }
287     else {
288       boolean changed = false;
289       Particle newParticle = new Particle(((ArrayList)this.term).clone());
290       newParticle.minOccurs = this.minOccurs;
291       newParticle.maxOccurs = this.maxOccurs;
292       newParticle.minExtent = this.minExtent;
293       newParticle.maxExtent = this.maxExtent;
294       List it = (List)this.term;
295       for ( int i = 0; i < it.size(); i++ ) {
296         Particle childParticle = (Particle)it.get(i);
297         Particle subPaticle = childParticle.substitutionTreating();
298         if ( subPaticle != childParticle ) {
299           changed = true;
300           ((ArrayList)newParticle.term).set(i, subPaticle);
301         }
302       }
303       if ( changed ) {
304         newParticle.optimizationParticle();
305         return newParticle;
306       }
307       else return this;
308     }
309   }
310   
311   private void optimizationParticle() {
312     if ( this.term instanceof ModelGroup ) {
313       ModelGroup group = (ModelGroup)this.term;
314       java.util.ListIterator JavaDoc it = group.listIterator();
315       while (it.hasNext()) {
316         Particle p = (Particle)it.next();
317         it.set(p);
318         if (p == null) it.remove();
319         else if (p.getTerm() instanceof ModelGroup) {
320           ModelGroup subgroup = (ModelGroup)p.getTerm();
321           if (p.getMinOccurs() == 1 && p.getMaxOccurs() == 1
322               && subgroup.getCompositor() == group.getCompositor()) {
323             //System.err.println("Simplification");
324
it.remove();
325             Iterator it2 = subgroup.iterator();
326             while (it2.hasNext()) it.add(it2.next());
327           }
328         }
329       }
330     }
331   }
332   
333   public void checkParticleValidRestriction(Particle ancestor) throws SchemaException {
334     if ( ancestor == null ) {
335       // Particle can't be restricted from its base particle
336
throw new SchemaException("cos-particle-restrict.2", this);
337     }
338     Particle subThis = this.substitutionTreating();
339     Particle subAncestor = ancestor.substitutionTreating();
340     subThis.checkParticleDerivation(subAncestor);
341   }
342   
343   private void checkParticleDerivation(Particle ancestor) throws SchemaException {
344     // cos-particle-restrict
345
if ( this.equals(ancestor) ) return;
346         
347     if ( this.term instanceof ElementDeclaration )
348       this.checkParticleDerivationOK_Elt(ancestor);
349     else if ( this.term instanceof Wildcard )
350       this.checkParticleDerivationOK_Any(ancestor);
351     else if ( this.term instanceof AllModelGroup )
352       this.checkParticleDerivationOK_All(ancestor);
353     else if ( this.term instanceof ChoiceModelGroup )
354       this.checkParticleDerivationOK_Choice(ancestor);
355     else if ( this.term instanceof SequenceModelGroup )
356       this.checkParticleDerivationOK_Sequence(ancestor);
357   }
358   
359   private void checkParticleDerivationOK_Elt(Particle ancestor) throws SchemaException {
360      if ( ancestor.term instanceof ElementDeclaration )
361       checkEltElt_NameAndTypeOK(ancestor);
362     else if ( ancestor.term instanceof Wildcard )
363       checkEltAny_NSCompat(ancestor);
364     else
365       checkEltAllChoiceSequence_RecursAsIfGroup(ancestor);
366    }
367   
368   private void checkParticleDerivationOK_Any(Particle ancestor) throws SchemaException {
369     // cos-particle-restrict
370
if ( ancestor.term instanceof Wildcard )
371       checkAnyAny_NSSubset(ancestor);
372     else
373       // Particle can't be restricted from its base particle
374
throw new SchemaException("cos-particle-restrict.2", this);
375   }
376   
377   private void checkParticleDerivationOK_All(Particle ancestor) throws SchemaException {
378     // cos-particle-restrict
379
if ( ancestor.term instanceof Wildcard )
380       checkAllChoiceSequenceAny_NSRecurseCheckCardinality(ancestor);
381     else if ( ancestor.term instanceof AllModelGroup )
382       checkAllAllSequenceSequence_Recurse(ancestor);
383     else
384       // Particle can't be restricted from its base particle
385
throw new SchemaException("cos-particle-restrict.2", this);
386   }
387   
388   private void checkParticleDerivationOK_Choice(Particle ancestor) throws SchemaException {
389     // cos-particle-restrict
390
if ( ancestor.term instanceof Wildcard )
391       checkAllChoiceSequenceAny_NSRecurseCheckCardinality(ancestor);
392     else if ( ancestor.term instanceof ChoiceModelGroup )
393       checkChoiceChoice_RecurseLax(ancestor);
394     else
395       // Particle can't be restricted from its base particle
396
throw new SchemaException("cos-particle-restrict.2", this);
397   }
398   
399   private void checkParticleDerivationOK_Sequence(Particle ancestor) throws SchemaException {
400     // cos-particle-restrict
401
if ( ancestor.term instanceof Wildcard )
402       checkAllChoiceSequenceAny_NSRecurseCheckCardinality(ancestor);
403     else if ( ancestor.term instanceof AllModelGroup )
404       checkSequenceAll_RecurseUnordered(ancestor);
405     else if ( ancestor.term instanceof ChoiceModelGroup )
406       checkSequenceChoice_MapAndSum(ancestor);
407     else if ( ancestor.term instanceof SequenceModelGroup )
408       checkAllAllSequenceSequence_Recurse(ancestor);
409     else
410       // Particle can't be restricted from its base particle
411
throw new SchemaException("cos-particle-restrict.2", this);
412
413   }
414   
415   private String JavaDoc checkOccurrenceRangeOK(int min, int max, int minBase, int maxBase) {
416     if ( min < minBase )
417       // Particle's minOccurs must be greater than or equal to its base particle's
418
return "range-ok.1";
419
420     if ( max > maxBase )
421       // Particle's maxOccurs must be less than or equal to its base particle's
422
return "range-ok.2.2";
423     
424     return null;
425   }
426   
427   private void checkEltElt_NameAndTypeOK(Particle ancestor) throws SchemaException {
428     ElementDeclaration elt = (ElementDeclaration)this.getTerm();
429     ElementDeclaration eltBase = (ElementDeclaration)ancestor.getTerm();
430     if ( elt == eltBase ) return;
431     if ( elt.getName().equals(eltBase.getName()) == false )
432       // Element declaration's name and namespace must be the same as its base's
433
throw new SchemaException("rcase-NameAndTypeOK.1", this);
434     else if ( elt.getNamespace() == null && eltBase.getNamespace() != null )
435       throw new SchemaException("rcase-NameAndTypeOK.1", this);
436     else if ( elt.getNamespace() != null && !(elt.getNamespace().equals(eltBase.getNamespace())) )
437       throw new SchemaException("rcase-NameAndTypeOK.1", this);
438     
439     if ( !( elt.isNillable() == false || eltBase.isNillable() ) )
440       // Element declaration's {nillable} must be false, or its base element's {nillable} must true
441
throw new SchemaException("rcase-NameAndTypeOK.2", this);
442     
443     String JavaDoc errCode = checkOccurrenceRangeOK(this.minOccurs, this.maxOccurs, ancestor.minOccurs, ancestor.maxOccurs);
444     if ( errCode != null )
445      // Occurence range is invalid
446
throw new SchemaException("rcase-NameAndTypeOK.3", this, new SchemaException(errCode));
447     
448     if ( !( eltBase.getFixedValue() == null ||
449          eltBase.getFixedValue().equals(elt.getFixedValue()) ) )
450       // If base declaration's {value contraint} is fixed, this declaration's {value constraint} must be fixed with the same value
451
throw new SchemaException("rcase-NameAndTypeOK.4", this);
452     
453     if ( ( (Integer.MAX_VALUE^elt.getBlock()) & eltBase.getBlock()) != 0 ) {
454       // Element declaration's {disallowed substitutions} must be a superset of its base declaration's
455
throw new SchemaException("rcase-NameAndTypeOK.5", this);
456     }
457     
458     errCode = elt.getType().checkTypeDerivationOK(eltBase.getType(), eltBase.getType().getFinal(), false);
459     if ( errCode != null )
460       // Element declaration's type must be valid derived from its base declaration's type
461
throw new SchemaException("rcase-NameAndTypeOK.7", this, new SchemaException(errCode, elt.getType()));
462   }
463   
464   private void checkEltAny_NSCompat(Particle ancestor) throws SchemaException {
465     ElementDeclaration elt = (ElementDeclaration)this.getTerm();
466     Wildcard wild = (Wildcard)ancestor.getTerm();
467     if ( wild.isAllowed(elt.getNamespace()) == false )
468       // Element declaration's {target namespace} must be valid with respect to its base wildcard's {namespace constraint}
469
throw new SchemaException("rcase-NSCompat.1", this);
470     
471     String JavaDoc errCode = checkOccurrenceRangeOK(this.minOccurs, this.maxOccurs, ancestor.minOccurs, ancestor.maxOccurs);
472     if ( errCode != null )
473      // Occurence range is invalid
474
throw new SchemaException("rcase-NSCompat.2", this, new SchemaException(errCode));
475  
476   }
477   
478   private void checkEltAllChoiceSequence_RecursAsIfGroup(Particle ancestor) throws SchemaException {
479     // rcase-RecurseAsIfGroup
480
try {
481       if ( ancestor.getTerm() instanceof SequenceModelGroup ) {
482         SequenceModelGroup sequence = new SequenceModelGroup();
483         sequence.add(this);
484         Particle sequenceParticle = new Particle(sequence);
485         sequenceParticle.checkAllAllSequenceSequence_Recurse(ancestor);
486       }
487       else if ( ancestor.getTerm() instanceof ChoiceModelGroup ) {
488         ChoiceModelGroup choice = new ChoiceModelGroup();
489         choice.add(this);
490         Particle choiceParticle = new Particle(choice);
491         choiceParticle.checkChoiceChoice_RecurseLax(ancestor);
492       }
493       else { // AllModelGroup
494
AllModelGroup all = new AllModelGroup();
495         all.add(this);
496         Particle allParticle = new Particle(all);
497         allParticle.checkAllAllSequenceSequence_Recurse(ancestor);
498       }
499     }
500     catch ( SchemaException se ) {
501       // second strategy
502
Particle eltParticle = new Particle(this.getTerm());
503         if ( ancestor.getTerm() instanceof SequenceModelGroup ) {
504           SequenceModelGroup sequence = new SequenceModelGroup();
505           sequence.add(eltParticle);
506           Particle sequenceParticle = new Particle(sequence);
507           sequenceParticle.minOccurs = this.minOccurs;
508           sequenceParticle.maxOccurs = this.maxOccurs;
509           sequenceParticle.minExtent = this.minExtent;
510           sequenceParticle.maxExtent = this.maxExtent;
511           sequenceParticle.checkAllAllSequenceSequence_Recurse(ancestor);
512         }
513         else if ( ancestor.getTerm() instanceof ChoiceModelGroup ) {
514           ChoiceModelGroup choice = new ChoiceModelGroup();
515           choice.add(eltParticle);
516           Particle choiceParticle = new Particle(choice);
517           choiceParticle.minOccurs = this.minOccurs;
518           choiceParticle.maxOccurs = this.maxOccurs;
519           choiceParticle.minExtent = this.minExtent;
520           choiceParticle.maxExtent = this.maxExtent;
521           choiceParticle.checkChoiceChoice_RecurseLax(ancestor);
522         }
523         else { // AllModelGroup
524
AllModelGroup all = new AllModelGroup();
525           all.add(eltParticle);
526           Particle allParticle = new Particle(all);
527           allParticle.minOccurs = this.minOccurs;
528           allParticle.maxOccurs = this.maxOccurs;
529           allParticle.minExtent = this.minExtent;
530           allParticle.maxExtent = this.maxExtent;
531           allParticle.checkAllAllSequenceSequence_Recurse(ancestor);
532         }
533      }
534   }
535   
536   private void checkAnyAny_NSSubset(Particle ancestor) throws SchemaException {
537     Wildcard wild = (Wildcard)this.getTerm();
538     Wildcard wildBase = (Wildcard)ancestor.getTerm();
539     String JavaDoc errCode = checkOccurrenceRangeOK(this.minOccurs, this.maxOccurs, ancestor.minOccurs, ancestor.maxOccurs);
540     if ( errCode != null )
541      // Occurence range is invalid
542
throw new SchemaException("rcase-NSSubset.1", this, new SchemaException(errCode));
543
544     errCode = wild.validWildcardSubset(wildBase);
545     if ( errCode != null )
546       // Wildcard's {namespace contraint} must be a valid subset of its base wildcard's {namespace contraint}
547
throw new SchemaException("rcase-NSSubset.2", this, new SchemaException(errCode, wild));
548   }
549   
550   private void checkAllChoiceSequenceAny_NSRecurseCheckCardinality(Particle ancestor) throws SchemaException {
551     java.util.Iterator JavaDoc it = ((ModelGroup)this.getTerm()).iterator();
552     while ( it.hasNext() ) {
553       Particle p = (Particle)it.next();
554       try {
555         p.checkParticleDerivation(ancestor);
556       }
557       catch ( SchemaException se ) {
558         // Particle must be a valid restriction of its base wildcard
559
throw new SchemaException("rcase-NSRecurseCheckCardinality.1", p, se);
560       }
561     }
562     
563     String JavaDoc errCode = checkOccurrenceRangeOK(this.minExtent, this.maxExtent, ancestor.minOccurs, ancestor.maxOccurs);
564     if ( errCode != null )
565      // Effective total Occurence range is invalid
566
throw new SchemaException("rcase-NSRecurseCheckCardinality.2", this, new SchemaException(errCode));
567
568   }
569   
570   private void checkAllAllSequenceSequence_Recurse(Particle ancestor) throws SchemaException {
571     String JavaDoc errCode = checkOccurrenceRangeOK(this.minOccurs, this.maxOccurs, ancestor.minOccurs, ancestor.maxOccurs);
572     if ( errCode != null )
573      // Occurence range is invalid
574
throw new SchemaException("rcase-Recurse.1", this, new SchemaException(errCode));
575         
576     java.util.Iterator JavaDoc it = ((ModelGroup)this.getTerm()).iterator();
577     java.util.Iterator JavaDoc itBase = ((ModelGroup)ancestor.getTerm()).iterator();
578     Particle particleBase = null;
579     while ( it.hasNext() ) {
580       Particle p = (Particle)it.next();
581       particleBase = p.findAllAllSequenceSequenceMappedParticle(particleBase, itBase, null);
582     }
583     
584     while ( itBase.hasNext() ) {
585       Particle pBase = (Particle)itBase.next();
586       if ( pBase.isEmptiable() == false )
587         // Un-mapped particle in base particles must be emptible
588
throw new SchemaException("rcase-Recurse.2.2", this);
589     }
590   }
591    
592   private Particle findAllAllSequenceSequenceMappedParticle(
593                     Particle particleBase,
594                     java.util.Iterator JavaDoc itBase,
595                     SchemaException sException)
596   throws SchemaException
597   {
598     if ( particleBase == null ) {
599       if ( itBase.hasNext() == false ) {
600         // Particle must be a valid restriction of its associated base particle
601
if ( sException == null )
602           throw new SchemaException("rcase-Recurse.2.1", this);
603         else
604           throw sException;
605       }
606       particleBase = (Particle)itBase.next();
607     }
608     try {
609       checkParticleDerivation(particleBase);
610       if ( particleBase.getTerm() instanceof ModelGroup )
611         return particleBase;
612       else
613         return null;
614     }
615     catch ( SchemaException se ) {
616       if ( particleBase.isEmptiable() == false ) {
617         // Un-mapped particle in base particles must be emptible
618
throw new SchemaException("rcase-Recurse.2.2", this, se);
619       }
620       return findAllAllSequenceSequenceMappedParticle(null, itBase, se);
621     }
622   }
623      
624   private void checkChoiceChoice_RecurseLax(Particle ancestor) throws SchemaException {
625     // first, verifier if this particle is a sub-particle of ancestor
626
java.util.Iterator JavaDoc it = ((ChoiceModelGroup)ancestor.term).iterator();
627     while ( it.hasNext() ) {
628       if ( this.equals((Particle)it.next()) ) return;
629     }
630    
631     // second, the specification
632
String JavaDoc errCode = checkOccurrenceRangeOK(this.minOccurs, this.maxOccurs, ancestor.minOccurs, ancestor.maxOccurs);
633     if ( errCode != null )
634      // Occurence range is invalid
635
throw new SchemaException("rcase-RecurseLax.1", this, new SchemaException(errCode));
636
637     it = ((ModelGroup)this.getTerm()).iterator();
638     java.util.Iterator JavaDoc itBase = ((ModelGroup)ancestor.getTerm()).iterator();
639     Particle particleBase = null;
640     while ( it.hasNext() ) {
641       Particle p = (Particle)it.next();
642       particleBase = p.findChoiceChoiceMappedParticle(particleBase, itBase, null);
643     }
644   }
645
646   private Particle findChoiceChoiceMappedParticle(
647                         Particle particleBase,
648                         java.util.Iterator JavaDoc itBase,
649                         SchemaException sException)
650   throws SchemaException
651   {
652     if ( particleBase == null ) {
653       if ( itBase.hasNext() == false ) {
654         // Particle must be a valid restriction of its associated base particle
655
if ( sException == null )
656           throw new SchemaException("rcase-RecurseLax.2", this);
657         else
658           throw sException;
659       }
660       particleBase = (Particle)itBase.next();
661     }
662     try {
663       checkParticleDerivation(particleBase);
664       if ( particleBase.getTerm() instanceof ModelGroup )
665         return particleBase;
666       else
667         return null;
668     }
669     catch ( SchemaException se ) {
670       return findChoiceChoiceMappedParticle(null, itBase, se);
671     }
672   }
673   
674   private void checkSequenceAll_RecurseUnordered(Particle ancestor) throws SchemaException {
675     String JavaDoc errCode = checkOccurrenceRangeOK(this.minOccurs, this.maxOccurs, ancestor.minOccurs, ancestor.maxOccurs);
676     if ( errCode != null )
677      // Occurence range is invalid
678
throw new SchemaException("rcase-RecurseUnordered.1", this, new SchemaException(errCode));
679     
680     java.util.Iterator JavaDoc it = ((ModelGroup)this.getTerm()).iterator();
681     java.util.HashSet JavaDoc mappedBaseParticles = new java.util.HashSet JavaDoc();
682     while ( it.hasNext() ) {
683       Particle p = (Particle)it.next();
684       java.util.Iterator JavaDoc itBase = ((ModelGroup)ancestor.getTerm()).iterator();
685       p.findSequenceAllMappedParticle(itBase, mappedBaseParticles);
686     }
687     
688     if ( ((ModelGroup)ancestor.getTerm()).size() > mappedBaseParticles.size() ) {
689       java.util.Iterator JavaDoc itBase = ((ModelGroup)ancestor.getTerm()).iterator();
690       while ( itBase.hasNext() ) {
691         Particle p = (Particle)itBase.next();
692         if ( p.isEmptiable() == false && !mappedBaseParticles.contains(p) )
693         {
694           // Un-mapped particle in base particles must be emptible
695
throw new SchemaException("rcase-RecurseUnordered.2.3", this);
696         }
697       }
698     }
699   }
700   
701   private void findSequenceAllMappedParticle(
702                       java.util.Iterator JavaDoc itBase,
703                       java.util.Set JavaDoc mappedBaseParticles)
704   throws SchemaException
705   {
706     Particle particleBase = (Particle)itBase.next();
707     try {
708       checkParticleDerivation(particleBase);
709       if ( mappedBaseParticles.contains(particleBase) )
710         // Base particle is mapped by more than one particle
711
throw new SchemaException("rcase-RecurseUnordered.2.1", this);
712       else
713         mappedBaseParticles.add(particleBase);
714     }
715     catch ( SchemaException se ) {
716       if ( itBase.hasNext() == false ) {
717         // Particle must be a valid restriction of its associated base particle
718
throw new SchemaException("rcase-RecurseUnordered.2.2", this, se);
719       }
720       findSequenceAllMappedParticle(itBase, mappedBaseParticles);
721     }
722   }
723     
724   private void checkSequenceChoice_MapAndSum(Particle ancestor) throws SchemaException {
725     // first, verifier if this particle is a sub-particle of ancestor
726
java.util.Iterator JavaDoc it = ((ChoiceModelGroup)ancestor.term).iterator();
727     while ( it.hasNext() ) {
728       if ( this.equals((Particle)it.next()) ) return;
729     }
730    
731     // second, the specification
732
int size = ((SequenceModelGroup)this.term).size();
733     int min = this.minOccurs * ((SequenceModelGroup)this.term).size();
734     int max = ( this.maxOccurs == Integer.MAX_VALUE ) ? this.maxOccurs : this.maxOccurs * size;
735     String JavaDoc errCode = checkOccurrenceRangeOK(min, max, ancestor.minOccurs, ancestor.maxOccurs);
736     if ( errCode != null )
737      // Occurence range is invalid
738
throw new SchemaException("rcase-MapAndSum.2", this, new SchemaException(errCode));
739     
740     it = ((ModelGroup)this.getTerm()).iterator();
741     while ( it.hasNext() ) {
742       Particle p = (Particle)it.next();
743       java.util.Iterator JavaDoc itBase = ((ModelGroup)ancestor.getTerm()).iterator();
744       Particle particleBase = p.findSequenceChoiceMappedParticle(itBase);
745     }
746   }
747   
748   private Particle findSequenceChoiceMappedParticle(java.util.Iterator JavaDoc itBase)
749   throws SchemaException
750   {
751     Particle particleBase = (Particle)itBase.next();
752     try {
753       checkParticleDerivation(particleBase);
754       return particleBase;
755     }
756     catch ( SchemaException se ) {
757       if ( itBase.hasNext() == false ) {
758         // Particle must be a valid restriction of its associated base particle
759
throw new SchemaException("rcase-MapAndSum.1", this, se);
760       }
761       return findSequenceChoiceMappedParticle(itBase);
762     }
763   }
764   
765   // check unique particle
766
// return the overLaped particle
767
Particle uniqueParticleAttribution() {
768     if ( this.term instanceof ChoiceModelGroup ||
769          this.term instanceof AllModelGroup ) {
770       ModelGroup group = (ModelGroup)this.term;
771       for ( int i = 0; i < group.size() - 1; i++ ) {
772         Particle p = (Particle)group.get(i);
773         Particle overlappedParticle = p.uniqueParticleAttribution();
774         if ( overlappedParticle != null ) return overlappedParticle;
775         for ( int j = i + 1; j < group.size(); j++ ) {
776           Particle nextParticle = (Particle)group.get(j);
777           if ( nextParticle.term instanceof ModelGroup || p.term instanceof ModelGroup ) {
778                 if ( p.overlapUPAC(nextParticle) )
779                     return p;
780           }
781         }
782       }
783     }
784     else if ( this.term instanceof SequenceModelGroup ) {
785       ModelGroup group = (ModelGroup)this.term;
786       for ( int i = 0; i < group.size(); i++ ) {
787         Particle p = (Particle)group.get(i);
788         Particle overlappedParticle = p.uniqueParticleAttribution();
789         if ( overlappedParticle != null ) return overlappedParticle;
790         if ( p.minOccurs < p.maxOccurs ) {
791           if ( i < group.size() - 1 ) {
792             Particle par = (Particle)group.get(i+1);
793             if ( par.term instanceof SequenceModelGroup ) {
794                 ModelGroup gPar = (ModelGroup)par.term;
795                 Particle firstPar = (Particle)gPar.get(0);
796                 if ( p.term instanceof SequenceModelGroup ) {
797                     ModelGroup gp = (ModelGroup)p.term;
798                     Particle lastP = (Particle)gp.get(gp.size()-1);
799                     if ( lastP.minOccurs < lastP.maxOccurs && firstPar.overlapUPAC(lastP) ) return lastP;
800                 }
801                 else {
802                     if ( p.overlapUPAC(firstPar) ) return firstPar;
803                 }
804             }
805             else if ( par.term instanceof ModelGroup || p.term instanceof ModelGroup ) {
806                 if (p.overlapUPAC(par)) return p;
807             }
808           }
809         }
810       }
811     }
812     
813     return null;
814   }
815   
816   private boolean overlapUPAC(Particle p) {
817     if ( this.term instanceof ElementDeclaration ) {
818       if ( p.term instanceof ModelGroup )
819         return p.overlapUPAC(this);
820       else
821         return ((ElementDeclaration)this.term).overlapUPAC(p.term);
822     }
823     else if ( this.term instanceof Wildcard ) {
824       if ( p.term instanceof ModelGroup )
825         return p.overlapUPAC(this);
826       else
827         return ((Wildcard)this.term).overlapUPAC(p.term);
828     }
829     else if ( this.term instanceof SequenceModelGroup && p.term instanceof SequenceModelGroup ) {
830         ModelGroup group = (ModelGroup)this.term;
831         if ( group.size() > 1 ) {
832             Particle first = (Particle)group.get(0);
833             if ( p.overlapUPAC(first) ) return true;
834             Particle last = (Particle)group.get(group.size()-1);
835             if ( last.minOccurs < last.maxOccurs && p.overlapUPAC(last) ) return true;
836         }
837         else {
838             return p.overlapUPAC((Particle)group.get(0));
839         }
840     }
841     else if ( this.term instanceof SequenceModelGroup && !(p.term instanceof ModelGroup) ) {
842         ModelGroup group = (ModelGroup)this.term;
843         if ( group.size() > 1 ) {
844             Particle first = (Particle)group.get(0);
845             if ( p.overlapUPAC(first) ) return true;
846         }
847     }
848     else {
849       ModelGroup group = (ModelGroup)this.term;
850       java.util.Iterator JavaDoc it = group.iterator();
851       while ( it.hasNext() ) {
852         Particle par = (Particle)it.next();
853         if ( par.overlapUPAC(p) )
854             return true;
855       }
856     }
857     return false;
858   }
859   
860   private boolean overlapUPAC_SingleSingle(Particle p) {
861     if ( this.term instanceof ElementDeclaration )
862       return ((ElementDeclaration)this.term).overlapUPAC(p.term);
863     else
864       return ((Wildcard)this.term).overlapUPAC(p.term);
865   }
866     
867   private boolean overlapUPAC_SingleModelGroup(Particle p) {
868     if ( this.minOccurs == this.minOccurs ) return false;
869
870     java.util.List JavaDoc list = p.firstValidElements();
871     java.util.Iterator JavaDoc it = list.iterator();
872     while ( it.hasNext() ) {
873       Particle par = (Particle)it.next();
874       if ( this.overlapUPAC_SingleSingle(par) ) return true;
875     }
876     
877     list = p.getFirstWildcards();
878     if ( list == null ) return false;
879     it = list.iterator();
880     while ( it.hasNext() ) {
881       Particle par = (Particle)it.next();
882       if ( this.overlapUPAC_SingleSingle(par) ) return true;
883     }
884     
885     return false;
886   }
887     
888 }
889
890
891
892
893
Popular Tags