KickJava   Java API By Example, From Geeks To Geeks.

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


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 import org.xquark.schema.datatypes.PrimitiveType;
28 import org.xquark.schema.loader.Loader;
29 import org.xquark.schema.validation.*;
30
31 /**
32  * class for Complex Type Definition.
33  *
34  * <p>This is the implementation of the Complex Type Definition.
35  * The following properties are defined:</p>
36  * <p> 1. name : optional, null or a NCName, defined in SchemaComponent.</p>
37  * <p> 2. target namespace : null or a namespace name, defined in SchemaComponent.</p>
38  * <p> 3. base type defintion : either a simple type defintion or a complex type defintion, defined in Type.</p>
39  * <p> 4. derivation method : either extension or restriction. </p>
40  * <p> 5. final : a subset of {extension, restriction}. </p>
41  * <p> 6. abstract : a boolean, defined in Type.</p>
42  * <p> 7. attribue declarations : a set of attribute declarations contained in the complex type. </p>
43  * <p> 8. content model : a content model to define the content type and to contain the particle. </p>
44  * <p> 9. element declarations : a set of element declarations contained in the complex type. </p>
45  *
46  * <p>See XML Schema Part 1: Structures 3.4
47  * W3C Recommendation 2 May 2001</p>
48  *
49  * @see org.xquark.xml.schema.SchemaComponent
50  * @see org.xquark.xml.schema.Type
51  * @see org.xquark.xml.schema.SimpleType
52  */

53 public final class ComplexType extends Type implements SchemaScope {
54     private static final String JavaDoc RCSRevision = "$Revision: 1.1 $";
55     private static final String JavaDoc RCSName = "$Name: $";
56
57     private boolean extension = false;
58     private boolean abs = false;
59     private int block = 0;
60     private ContentModel contentModel = null;
61     private HashMap elementDeclarations = new HashMap();
62     private HashMap attributes = new HashMap();
63     private ArrayList requiredAndDefaultAttributes = null;
64     private Wildcard attributeWildcard = null;
65     private AttributeDeclaration idAttr = null;
66     private AttributeDeclaration notationAttr = null;
67
68     /**
69      * Create a new ComplexType.
70      *
71      * @param schema The schema which contains this attribute declaration.
72      * @param name The complex type name, null or a NCName.
73      * @param baseType The base type definition, null or a simple type.
74      */

75     public ComplexType(Schema schema, String JavaDoc name, Type baseType) {
76         super(schema, name, baseType);
77     }
78
79     public void accept(SchemaVisitor visitor) throws SchemaException {
80         visitor.visit(this);
81     }
82
83     /**
84      * Retrun the complex type's derivation method.
85      *
86      * @return The extention, true, if derivation method is an extension;
87      * false, if derivation method is a restriction
88      */

89     public boolean isExtension() {
90         return extension;
91     }
92
93     /**
94      * Retrun the complex type's derivation method.
95      *
96      * @return The restriction, true, if derivation method is an restriction;
97      * false, if derivation method is a extension
98      */

99     public boolean isRestriction() {
100         return !extension;
101     }
102
103     public int getDerivationMethod() {
104         return extension ? EXTENSION : RESTRICTION;
105     }
106
107     /**
108      * @return null if valid, a string containing the error code otherwise
109      */

110
111     public String JavaDoc checkTypeDerivationOK(Type ancestor, int exclusions, boolean useBlock) {
112         if (this == ancestor)
113             return null;
114         if ((getDerivationMethod() & exclusions) != 0)
115             return "cos-ct-derived-ok.1";
116         Type parent = getBaseType();
117         if (parent == null)
118             return "cos-ct-derived-ok.2.3.1";
119         if (useBlock)
120             exclusions |= parent.getBlock();
121         return parent.checkTypeDerivationOK(ancestor, exclusions, useBlock);
122     }
123
124     public int getBlock() {
125         return block;
126     }
127
128     public String JavaDoc normalizedValue(String JavaDoc value) {
129         switch (getContentType()) {
130             case EMPTY :
131             case ELEMENT_ONLY :
132                 return null;
133             case MIXED :
134                 return value;
135             case TEXT_ONLY :
136             default :
137                 return getValueType().normalizedValue(value);
138         }
139     }
140
141     public StringBuffer JavaDoc normalizedValue(StringBuffer JavaDoc value) {
142         switch (getContentType()) {
143             case EMPTY :
144             case ELEMENT_ONLY :
145                 return null;
146             case MIXED :
147                 return value;
148             case TEXT_ONLY :
149             default :
150                 return getValueType().normalizedValue(value);
151         }
152     }
153
154     public StringBuffer JavaDoc normalizedValue(StringBuffer JavaDoc value, StringBuffer JavaDoc out) {
155         switch (getContentType()) {
156             case EMPTY :
157             case ELEMENT_ONLY :
158                 return null;
159             case MIXED :
160                 if (out == null)
161                     out = new StringBuffer JavaDoc();
162                 out.append(value.toString());
163                 return out;
164             case TEXT_ONLY :
165             default :
166                 return getValueType().normalizedValue(value, out);
167         }
168     }
169
170     public String JavaDoc toXMLString(Object JavaDoc value, ValidationContextProvider context) {
171         switch (getContentType()) {
172             case EMPTY :
173             case ELEMENT_ONLY :
174             case MIXED :
175                 return value.toString();
176             case TEXT_ONLY :
177             default :
178                 return getValueType().toXMLString(value, context);
179         }
180     }
181
182     public ValidationInfo validate(String JavaDoc value, boolean normalize, ValidationContextProvider context)
183         throws SchemaException {
184         switch (getContentType()) {
185             case EMPTY :
186                 throw new SchemaException(
187                     "cvc-complex-type.2.1",
188                     "Empty element cannot contain characters or children");
189             case ELEMENT_ONLY :
190                 boolean bWhitespaceOnly = true;
191                 for (int i = 0; i < value.length(); i++) {
192                     if (!PrimitiveType.isXMLWhitespace(value.charAt(i)))
193                         bWhitespaceOnly = false;
194                 }
195                 if (!bWhitespaceOnly)
196                     throw new SchemaException(
197                         "cvc-complex-type.2.3",
198                         "Illegal non-whitespace characters in element-only content type");
199                 else
200                     return null;
201             case MIXED :
202                 return null;
203             case TEXT_ONLY :
204             default :
205                 return getValueType().validate(value, normalize, context);
206         }
207     }
208
209     public ValidationInfo validate(StringBuffer JavaDoc value, boolean normalize, ValidationContextProvider context)
210         throws SchemaException {
211         switch (getContentType()) {
212             case EMPTY :
213                 throw new SchemaException(
214                     "cvc-complex-type.2.1",
215                     "Empty element cannot contain characters or children");
216             case ELEMENT_ONLY :
217                 boolean bWhitespaceOnly = true;
218                 for (int i = 0; i < value.length(); i++) {
219                     if (!PrimitiveType.isXMLWhitespace(value.charAt(i)))
220                         bWhitespaceOnly = false;
221                 }
222                 if (!bWhitespaceOnly)
223                     throw new SchemaException(
224                         "cvc-complex-type.2.3",
225                         "Illegal non-whitespace characters in element-only content type");
226                 else
227                     return null;
228             case MIXED :
229                 return null;
230             case TEXT_ONLY :
231             default :
232                 return getValueType().validate(value, normalize, context);
233         }
234     }
235
236     public Object JavaDoc convert(String JavaDoc value, boolean normalize, ValidationContextProvider context) throws SchemaException {
237         switch (getContentType()) {
238             case EMPTY :
239                 throw new SchemaException(
240                     "cvc-complex-type.2.1",
241                     "Empty element cannot contain characters or children");
242             case ELEMENT_ONLY :
243                 boolean bWhitespaceOnly = true;
244                 for (int i = 0; i < value.length(); i++) {
245                     if (!PrimitiveType.isXMLWhitespace(value.charAt(i)))
246                         bWhitespaceOnly = false;
247                 }
248                 if (bWhitespaceOnly)
249                     throw new SchemaException(
250                         "cvc-complex-type.2.3",
251                         "Empty element cannot contain characters or children");
252                 else
253                     return "";
254             case MIXED :
255                 return value;
256             case TEXT_ONLY :
257             default :
258                 return getValueType().convert(value, normalize, context);
259         }
260     }
261
262     public Object JavaDoc convert(StringBuffer JavaDoc value, boolean normalize, ValidationContextProvider context)
263         throws SchemaException {
264         switch (getContentType()) {
265             case EMPTY :
266                 throw new SchemaException(
267                     "cvc-complex-type.2.1",
268                     "Empty element cannot contain characters or children");
269             case ELEMENT_ONLY :
270                 boolean bWhitespaceOnly = true;
271                 for (int i = 0; i < value.length(); i++) {
272                     if (!PrimitiveType.isXMLWhitespace(value.charAt(i)))
273                         bWhitespaceOnly = false;
274                 }
275                 if (bWhitespaceOnly)
276                     throw new SchemaException(
277                         "cvc-complex-type.2.3",
278                         "Empty element cannot contain characters or children");
279                 else
280                     return "";
281             case MIXED :
282                 return value;
283             case TEXT_ONLY :
284             default :
285                 return getValueType().convert(value, normalize, context);
286         }
287     }
288
289     public String JavaDoc toCanonicalForm(String JavaDoc value, ValidationContextProvider context) throws SchemaException {
290         switch (getContentType()) {
291             case EMPTY :
292             case ELEMENT_ONLY :
293             case MIXED :
294                 return value;
295             case TEXT_ONLY :
296             default :
297                 return getValueType().toCanonicalForm(value, context);
298         }
299     }
300
301     public String JavaDoc validateDefault(String JavaDoc value, ValidationContextProvider context) throws SchemaException {
302         switch (getContentType()) {
303             case EMPTY :
304             case ELEMENT_ONLY :
305                 throw new SchemaException("cos-valid-default.2.1", this);
306             case MIXED :
307                 if (getContentModel().getModel() != null && !((Particle) getContentModel().getModel()).isEmptiable()) {
308                     throw new SchemaException("cos-valid-default.2.2.2", this);
309                 }
310                 return value;
311             case TEXT_ONLY :
312             default :
313                 try {
314                     return getValueType().toCanonicalForm(value, context);
315                 } catch (SchemaException ex) {
316                     throw new SchemaException("cos-valid-default.2.2.1", this, ex);
317                 }
318         }
319     }
320
321     /**
322      * Return the complex type's content model, if any
323      * the model of a content model can be either a particle or a simple type definition
324      *
325      * @return The content model, or null if there is none
326      * @see org.xquark.xml.schema.ContentModel
327      */

328     public ContentModel getContentModel() {
329         return contentModel;
330     }
331
332     /**
333      * Return the type's abstract, the notion 'abstract' is applied only to
334      * complex type definition
335      *
336      * @return The abstract, ture if type is abstract, false otherwise.
337      */

338     public boolean isAbstract() {
339         return abs;
340     }
341
342     /**
343      * Return the complex type's content type
344      * the content type of a complex type can be : EMPTY, MIXED, TEXT_ONLY or ELEMENT_ONLY
345      *
346      * @return The content type
347      * @see org.xquark.xml.schema.ContentModel
348      */

349     public int getContentType() {
350         return contentModel.getContentType();
351     }
352
353     public SimpleType getValueType() {
354         if (getContentType() == TEXT_ONLY)
355             return (SimpleType) contentModel.getModel();
356         else
357             return null;
358     }
359
360     /**
361      * Look up the attribute wildcard, if any
362      *
363      * @return The ElementDeclaration, or null if there is none.
364      */

365     public Wildcard getAttributeWildcard() {
366         return attributeWildcard;
367     }
368
369     public AttributeDeclaration getIDAttribute() {
370         return idAttr;
371     }
372
373     public AttributeDeclaration getNotationAttribute() {
374         return notationAttr;
375     }
376
377     public ContentIterator childIterator() {
378         switch (getContentType()) {
379             case ELEMENT_ONLY :
380             case MIXED :
381                 Particle particle = (Particle) contentModel.getModel();
382                 if (particle == null)
383                     return null;
384                 return ContentIteratorFactory.createIterator(particle);
385             default :
386                 return null;
387         }
388     }
389
390     public ContentIterator contentIterator() {
391         switch (getContentType()) {
392             case ELEMENT_ONLY :
393             case MIXED :
394                 return new ElementTreeContentIterator(this);
395             default :
396                 return null;
397         }
398     }
399
400     public boolean isGlobalScope() {
401         return false;
402     }
403
404     /**
405      * Giving an element declaration name, look up the local element declaration, if any
406      *
407      * @param name The element name.
408      *
409      * @return The ElementDeclaration, or null if there is none.
410      */

411     public ElementDeclaration getElementDeclaration(String JavaDoc namespace, String JavaDoc name) {
412         if (namespace == null)
413             return (ElementDeclaration) elementDeclarations.get(name);
414         else
415             return (ElementDeclaration) elementDeclarations.get("{" + namespace + "}" + name);
416     }
417
418     /**
419      * Look up all local element declarations, if any
420      *
421      * @return The collection view of all Element Declarations, or null if there is none.
422      */

423     public Collection getElementDeclarations() {
424         return elementDeclarations.values();
425     }
426
427     /**
428      * Giving an attribute declaration name, look up the local attribute declaration.
429      *
430      * @param name The attribute name.
431      *
432      * @return The AttributeDeclaration.
433      */

434     public AttributeDeclaration getAttributeDeclaration(String JavaDoc namespace, String JavaDoc name) {
435         if (namespace == null)
436             return (AttributeDeclaration) attributes.get(name);
437         else
438             return (AttributeDeclaration) attributes.get("{" + namespace + "}" + name);
439     }
440
441     /**
442      * Look up all local attribute declarations.
443      *
444      * @return The collection view of all attribute Declarations.
445      */

446     public Collection getAttributeDeclarations() {
447         return attributes.values();
448     }
449
450     Set getAttributeEntries() {
451         return attributes.entrySet();
452     }
453
454     public List getRequiredAndDefaultAttributes() {
455         return requiredAndDefaultAttributes;
456     }
457
458     public void setExtension(boolean extension) {
459         this.extension = extension;
460     }
461
462     public void setAbstract(boolean abs) {
463         this.abs = abs;
464     }
465
466     public void setBlock(int block) {
467         this.block = block;
468     }
469
470     public void setContentModel(ContentModel contentModel) {
471         this.contentModel = contentModel;
472     }
473
474     void setIDAttribute(AttributeDeclaration decl) {
475         idAttr = decl;
476     }
477
478     void setNotationAttribute(AttributeDeclaration decl) {
479         notationAttr = decl;
480     }
481
482     public int[] getDeclarationOccurrence(String JavaDoc namespace, String JavaDoc name) {
483         if (getContentType() == EMPTY || getContentType() == TEXT_ONLY || getContentModel().getModel() == null)
484             return null;
485         ComplexType.OccurrenceVisitor visitor = new ComplexType.OccurrenceVisitor();
486         return visitor.getOccurrenceCount((Particle)getContentModel().getModel(), namespace, name);
487     }
488
489     public void register(SchemaComponent decl) throws SchemaException {
490         if (decl instanceof ElementDeclaration)
491             register((ElementDeclaration) decl);
492         else if (decl instanceof AttributeDeclaration)
493             register((AttributeDeclaration) decl);
494         else {
495             // AttributeGroups are stored with themselves as key
496
// until initialization replaces them by their content
497
attributes.put(decl, decl);
498         }
499     }
500
501     private Object JavaDoc buildDeclarationKey(SchemaComponent comp) {
502         if (comp.getNamespace() == null)
503             return comp.getName();
504         else
505             return "{" + comp.getNamespace() + "}" + comp.getName();
506     }
507
508     public void register(AttributeDeclaration decl) throws SchemaException {
509         Object JavaDoc nsName = buildDeclarationKey(decl);
510         if (attributes.put(nsName, decl) != null) {
511             // "Two distinct attribute declarations should not have identical names : " + nsName;
512
throw new SchemaException("ct-props-correct.4", decl);
513         }
514     }
515
516     public void register(ElementDeclaration decl) throws SchemaException {
517         Object JavaDoc nsName = buildDeclarationKey(decl);
518         ElementDeclaration prev = (ElementDeclaration) elementDeclarations.put(nsName, decl);
519         // The spec requires consistent declarations to have the same named type
520
// This is not respected in the Schema for Schemas
521
// if (prev != null && !decl.getType().hasName(prev.getType().getNamespace(), prev.getType().getName())) {
522
if (prev != null && decl.getType() != prev.getType()) {
523             // "Element declaration '" + nsName + "' must have the same type as the existing element declaration";
524
throw new SchemaException("cos-element-consistent.2", decl);
525         }
526         List substitutionList = decl.getSubstitutionElementList();
527         if (substitutionList != null) {
528             Iterator it = substitutionList.iterator();
529             while (it.hasNext()) {
530                 ElementDeclaration d = (ElementDeclaration) it.next();
531                 ElementDeclaration existing = getElementDeclaration(d.getNamespace(), d.getName());
532                 // if (existing != null && !d.getType().hasName(existing.getType().getNamespace(), existing.getType().getName())) {
533
if (existing != null && d.getType() != existing.getType()) {
534                     // "Element declaration '" + nsName + "' must have the same type as the existing element declaration";
535
throw new SchemaException("cos-element-consistent.2", d);
536                 }
537             }
538         }
539     }
540
541     public void setAttributeWildcard(Wildcard wildcard) {
542         attributeWildcard = wildcard;
543     }
544
545     public void setRequiredAndDefaultAttributes(ArrayList list) {
546         requiredAndDefaultAttributes = list;
547     }
548
549     // TYPING STUFF
550
public boolean isSimpleType() {
551         return false;
552     }
553
554     void checkUniqueParticleAttribution() throws SchemaException {
555         if (this.getContentType() == EMPTY)
556             return;
557         if (this.getContentModel().getModel() instanceof SimpleType)
558             return;
559         Particle p = (Particle) this.getContentModel().getModel();
560         if (p == null)
561             return;
562         Particle overLapParticle = p.uniqueParticleAttribution();
563         if (overLapParticle == null)
564             return;
565         // Unique Particle Attribute Violation
566
throw new SchemaException("cos-nonambig", overLapParticle);
567     }
568
569     void checkDerivationValidRestriction(Loader loader) throws SchemaException {
570         Type baseType = this.getBaseType();
571         if (this.isExtension() || baseType == null || baseType.isSimpleType())
572             return; // it's not restriction
573
ComplexType base = (ComplexType) baseType;
574
575         if ((base.getFinal() & RESTRICTION) != 0) {
576             // "Base type final must not contain restriction";
577
throw new SchemaException("derivation-ok-restriction.1", this);
578         }
579
580         Iterator it = this.getAttributeDeclarations().iterator();
581         while (it.hasNext()) {
582             AttributeDeclaration decl = (AttributeDeclaration) it.next();
583             AttributeDeclaration baseDecl = base.getAttributeDeclaration(decl.getNamespace(), decl.getName());
584             if (baseDecl != null) {
585                 if (!(baseDecl.getUse() != REQUIRED || decl.getUse() == REQUIRED)) {
586                     // "Attribute <use> isn't reqired, but attribute <use> in base type is required.";
587
throw new SchemaException("derivation-ok-restriction.2.1.1", decl);
588                 }
589                 String JavaDoc errCode02 =
590                     decl.getType().checkTypeDerivationOK(baseDecl.getType(), baseDecl.getType().getFinal(), false);
591                 if (errCode02 != null) {
592                     // "Attribute's type definition must be validly derivded from that of the base type's attribute declaration.";
593
throw new SchemaException(
594                         "derivation-ok-restriction.2.1.2",
595                         decl,
596                         new SchemaException(errCode02, decl));
597                 }
598                 if (!(baseDecl.getFixedValue() == null || baseDecl.getFixedValue().equals(decl.getFixedValue()))) {
599                     // "Attribute declaration's effective value constraint doesn't match with that of base type's attribute declaration.";
600
throw new SchemaException("derivation-ok-restriction.2.1.3", decl);
601                 }
602             } else if (
603                 base.getAttributeWildcard() == null
604                     || base.getAttributeWildcard().isAllowed(decl.getNamespace()) == false) {
605                 // "Attribute declaration, or a valid attribute wildcard, must be defined in base type.";
606
throw new SchemaException("derivation-ok-restriction.2.2", decl);
607             }
608         }
609
610         // schema of schema doesn't respect the following rule
611
it = base.getAttributeDeclarations().iterator();
612         while (it.hasNext()) {
613             AttributeDeclaration baseDecl = (AttributeDeclaration) it.next();
614             if (baseDecl.getUse() == REQUIRED) {
615                 AttributeDeclaration decl = this.getAttributeDeclaration(baseDecl.getNamespace(), baseDecl.getName());
616                 if (decl == null || decl.getUse() != REQUIRED) {
617                     // "Attribute declaration's attribute <use> must be required.";
618
Object JavaDoc obj = decl;
619                     if (obj == null)
620                         obj = this;
621                     throw new SchemaException("derivation-ok-restriction.3", obj);
622                 }
623             }
624         }
625
626         Wildcard w = this.getAttributeWildcard();
627         if (w != null) {
628             Wildcard baseW = base.getAttributeWildcard();
629             if (baseW == null) {
630                 // "Base type must have an attribute wildcard.";
631
throw new SchemaException("derivation-ok-restriction.4.1", this);
632             } else {
633                 String JavaDoc errCode02 = w.validWildcardSubset(baseW);
634                 if (errCode02 != null) {
635                     // "Attribute wildcard must be a valid subset of base type's.";
636
throw new SchemaException("derivation-ok-restriction.4.2", this, new SchemaException(errCode02, w));
637                 }
638             }
639         }
640
641         switch (this.getContentType()) {
642             case TEXT_ONLY :
643                 switch (base.getContentType()) {
644                     case EMPTY :
645                     case ELEMENT_ONLY :
646                         // "Content type of base type must be mixed or a valid simple type";
647
throw new SchemaException("derivation-ok-restriction.5.1", this);
648                     case TEXT_ONLY :
649                         SimpleType st = (SimpleType) this.getContentModel().getModel();
650                         SimpleType stBase = (SimpleType) base.getContentModel().getModel();
651                         String JavaDoc errCode02 = st.checkTypeDerivationOK(stBase, stBase.getFinal(), false);
652                         if (errCode02 != null) {
653                             // "Base {content type} must be a valid simple type.";
654
throw new SchemaException(
655                                 "derivation-ok-restriction.5.1.1",
656                                 this,
657                                 new SchemaException(errCode02, st));
658                         }
659                         break;
660                     case MIXED :
661                         Particle p = (Particle) base.getContentModel().getModel();
662                         if (p == null || p.isEmptiable() == false) {
663                             // "Base type must have an emptiable particle.";
664
throw new SchemaException("derivation-ok-restriction.5.1.2", this);
665                         }
666                         break;
667                 }
668                 break;
669
670             case EMPTY :
671                 switch (base.getContentType()) {
672                     case EMPTY :
673                         break;
674                     case ELEMENT_ONLY :
675                     case MIXED :
676                         Particle p = (Particle) base.getContentModel().getModel();
677                         if (p == null || p.isEmptiable() == false) {
678                             // "Base {content type} must be elementOnly or mixed, and must have an emptiable particle.";
679
throw new SchemaException("derivation-ok-restriction.5.2.2", this);
680                         }
681                         break;
682                     case TEXT_ONLY :
683                         // "Base {content type} must not be textOnly";
684
throw new SchemaException("derivation-ok-restriction.5.2", this);
685                 }
686                 break;
687
688             case ELEMENT_ONLY :
689                 switch (base.getContentType()) {
690                     case EMPTY :
691                     case TEXT_ONLY :
692                         // "Base {content type} must be elementOnly or mixed,
693
// and the particle must be a valid restrion of base type's particle";
694
throw new SchemaException("derivation-ok-restriction.5.3", this);
695                     case ELEMENT_ONLY :
696                     case MIXED :
697                         Particle p = null;
698                         try {
699                             p = (Particle) this.getContentModel().getModel();
700                             Particle pBase = (Particle) base.getContentModel().getModel();
701                             if (p != null)
702                                 p.checkParticleValidRestriction(pBase);
703                         } catch (SchemaException se) {
704                             if (se.getInvalidObject() != null
705                                 && loader != null
706                                 && loader.getComponentLocaltor(se.getInvalidObject()) != null)
707                                 throw new SchemaException("derivation-ok-restriction.5.3", se.getInvalidObject(), se);
708                             else
709                                 throw new SchemaException("derivation-ok-restriction.5.3", p, se);
710                         }
711                         break;
712                 }
713                 break;
714
715             case MIXED :
716                 switch (base.getContentType()) {
717                     case EMPTY :
718                     case TEXT_ONLY :
719                     case ELEMENT_ONLY :
720                         // "Base {content type} must be elementOnly or mixed";
721
throw new SchemaException("derivation-ok-restriction.5.3", this);
722                     case MIXED :
723                         Particle p = null;
724                         try {
725                             p = (Particle) this.getContentModel().getModel();
726                             Particle pBase = (Particle) base.getContentModel().getModel();
727                             if (p != null)
728                                 p.checkParticleValidRestriction(pBase);
729                         } catch (SchemaException se) {
730                             throw new SchemaException("derivation-ok-restriction.5.3", p, se);
731                         }
732                         break;
733                 }
734                 break;
735         }
736     }
737
738     static class OccurrenceVisitor extends DefaultSchemaVisitor {
739         private static final String JavaDoc RCSRevision = "$Revision: 1.1 $";
740         private static final String JavaDoc RCSName = "$Name: $";
741         private int[] occurs = null;
742         private String JavaDoc namespace = null;
743         private String JavaDoc name = null;
744
745         public int[] getOccurrenceCount(Particle particle, String JavaDoc namespace, String JavaDoc name) {
746             occurs = new int[2];
747             occurs[0] = occurs[1] = 0;
748             this.namespace = namespace;
749             this.name = name;
750             try {
751                 particle.accept(this);
752             } catch (SchemaException ex) {
753                 // Should not occur
754
}
755             return occurs;
756         }
757
758         private void setValues(long min, long max) {
759             if (max > Integer.MAX_VALUE)
760                 max = Integer.MAX_VALUE;
761             occurs[0] = (int) min;
762             occurs[1] = (int) max;
763         }
764
765         public void visit(Particle particle) throws SchemaException {
766             ((SchemaVisitable) particle.getTerm()).accept(this);
767             long min = occurs[0] * particle.getMinOccurs();
768             long max = occurs[1] * particle.getMaxOccurs();
769             setValues(min, max);
770         }
771
772         public void visit(ModelGroup group) throws SchemaException {
773             long min = 0;
774             long max = 0;
775             Iterator it = group.iterator();
776             while (it.hasNext()) {
777                 occurs[0] = occurs[1] = 0;
778                 ((SchemaVisitable) it.next()).accept(this);
779                 min += occurs[0];
780                 max += occurs[1];
781             }
782             setValues(min, max);
783         }
784
785         public void visit(ChoiceModelGroup group) throws SchemaException {
786             long min = Integer.MAX_VALUE;
787             long max = 0;
788             Iterator it = group.iterator();
789             while (it.hasNext()) {
790                 occurs[0] = occurs[1] = 0;
791                 ((SchemaVisitable) it.next()).accept(this);
792                 if (occurs[0] < min)
793                     min = occurs[0];
794                 if (occurs[1] > max)
795                     max = occurs[1];
796             }
797             setValues(min, max);
798         }
799
800         public void visit(ElementDeclaration decl) throws SchemaException {
801             if (decl.hasName(namespace, name) || decl.getSubstitutionElement(namespace, name) != null)
802                 occurs[0] = occurs[1] = 1;
803         }
804
805         public void visit(Wildcard wildcard) throws SchemaException {
806             if (wildcard.isAllowed(namespace)) {
807                 occurs[0] = occurs[1] = 1;
808             }
809         }
810
811     }
812
813 }
814
Popular Tags