View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright 2001-2004 The Apache Software Foundation.
7    *
8    * Licensed under the Apache License, Version 2.0 (the "License");
9    * you may not use this file except in compliance with the License.
10   * You may obtain a copy of the License at
11   *
12   *      http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  
21  package com.sun.org.apache.xerces.internal.impl.xs.traversers;
22  
23  import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar;
24  import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols;
25  import com.sun.org.apache.xerces.internal.impl.xs.XSAnnotationImpl;
26  import com.sun.org.apache.xerces.internal.impl.xs.XSModelGroupImpl;
27  import com.sun.org.apache.xerces.internal.impl.xs.XSParticleDecl;
28  import com.sun.org.apache.xerces.internal.impl.xs.util.XInt;
29  import com.sun.org.apache.xerces.internal.impl.xs.util.XSObjectListImpl;
30  import com.sun.org.apache.xerces.internal.util.DOMUtil;
31  import com.sun.org.apache.xerces.internal.xs.XSObject;
32  import com.sun.org.apache.xerces.internal.xs.XSObjectList;
33  import org.w3c.dom.Element;
34  
35  /**
36   * @xerces.internal
37   *
38   * @author Elena Litani, IBM
39   * @author Sandy Gao, IBM
40   * @version $Id: XSDAbstractParticleTraverser.java,v 1.7 2010-11-01 04:40:02 joehw Exp $
41   */
42  abstract class XSDAbstractParticleTraverser extends XSDAbstractTraverser {
43  
44      XSDAbstractParticleTraverser (XSDHandler handler,
45              XSAttributeChecker gAttrCheck) {
46          super(handler, gAttrCheck);
47      }
48  
49      /**
50       *
51       * Traverse the "All" declaration
52       *
53       * <all
54       *   id = ID
55       *   maxOccurs = 1 : 1
56       *   minOccurs = (0 | 1) : 1>
57       *   Content: (annotation? , element*)
58       * </all>
59       **/
60      XSParticleDecl traverseAll(Element allDecl,
61              XSDocumentInfo schemaDoc,
62              SchemaGrammar grammar,
63              int allContextFlags,
64              XSObject parent) {
65  
66          // General Attribute Checking
67  
68          Object[] attrValues = fAttrChecker.checkAttributes(allDecl, false, schemaDoc);
69  
70          Element child = DOMUtil.getFirstChildElement(allDecl);
71  
72          XSAnnotationImpl annotation = null;
73          if (child !=null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
74              annotation = traverseAnnotationDecl(child, attrValues, false, schemaDoc);
75              child = DOMUtil.getNextSiblingElement(child);
76          }
77          else {
78              String text = DOMUtil.getSyntheticAnnotation(allDecl);
79              if (text != null) {
80                  annotation = traverseSyntheticAnnotation(allDecl, text, attrValues, false, schemaDoc);
81              }
82          }
83          String childName = null;
84          XSParticleDecl particle;
85          fPArray.pushContext();
86  
87          for (; child != null; child = DOMUtil.getNextSiblingElement(child)) {
88  
89              particle = null;
90              childName = DOMUtil.getLocalName(child);
91  
92              // Only elements are allowed in <all>
93              if (childName.equals(SchemaSymbols.ELT_ELEMENT)) {
94                  particle = fSchemaHandler.fElementTraverser.traverseLocal(child, schemaDoc, grammar, PROCESSING_ALL_EL, parent);
95              }
96              else {
97                  Object[] args = {"all", "(annotation?, element*)", DOMUtil.getLocalName(child)};
98                  reportSchemaError("s4s-elt-must-match.1", args, child);
99              }
100 
101             if (particle != null)
102                 fPArray.addParticle(particle);
103         }
104 
105         particle = null;
106         XInt minAtt = (XInt)attrValues[XSAttributeChecker.ATTIDX_MINOCCURS];
107         XInt maxAtt = (XInt)attrValues[XSAttributeChecker.ATTIDX_MAXOCCURS];
108         Long defaultVals = (Long)attrValues[XSAttributeChecker.ATTIDX_FROMDEFAULT];
109 
110         XSModelGroupImpl group = new XSModelGroupImpl();
111         group.fCompositor = XSModelGroupImpl.MODELGROUP_ALL;
112         group.fParticleCount = fPArray.getParticleCount();
113         group.fParticles = fPArray.popContext();
114         XSObjectList annotations;
115         if (annotation != null) {
116             annotations = new XSObjectListImpl();
117             ((XSObjectListImpl)annotations).addXSObject (annotation);
118         } else {
119             annotations = XSObjectListImpl.EMPTY_LIST;
120         }
121         group.fAnnotations = annotations;
122         particle = new XSParticleDecl();
123         particle.fType = XSParticleDecl.PARTICLE_MODELGROUP;
124         particle.fMinOccurs = minAtt.intValue();
125         particle.fMaxOccurs = maxAtt.intValue();
126         particle.fValue = group;
127         particle.fAnnotations = annotations;
128 
129         particle = checkOccurrences(particle,
130                 SchemaSymbols.ELT_ALL,
131                 (Element)allDecl.getParentNode(),
132                 allContextFlags,
133                 defaultVals.longValue());
134         fAttrChecker.returnAttrArray(attrValues, schemaDoc);
135 
136         return particle;
137     }
138 
139     /**
140      * Traverse the Sequence declaration
141      *
142      * <sequence
143      *   id = ID
144      *   maxOccurs = string
145      *   minOccurs = nonNegativeInteger>
146      *   Content: (annotation? , (element | group | choice | sequence | any)*)
147      * </sequence>
148      *
149      * @param seqDecl
150      * @param schemaDoc
151      * @param grammar
152      * @return
153      */
154     XSParticleDecl traverseSequence(Element seqDecl,
155             XSDocumentInfo schemaDoc,
156             SchemaGrammar grammar,
157             int allContextFlags,
158             XSObject parent) {
159 
160         return traverseSeqChoice(seqDecl, schemaDoc, grammar, allContextFlags, false, parent);
161     }
162 
163     /**
164      * Traverse the Choice declaration
165      *
166      * <choice
167      *   id = ID
168      *   maxOccurs = string
169      *   minOccurs = nonNegativeInteger>
170      *   Content: (annotation? , (element | group | choice | sequence | any)*)
171      * </choice>
172      *
173      * @param choiceDecl
174      * @param schemaDoc
175      * @param grammar
176      * @return
177      */
178     XSParticleDecl traverseChoice(Element choiceDecl,
179             XSDocumentInfo schemaDoc,
180             SchemaGrammar grammar,
181             int allContextFlags,
182             XSObject parent) {
183 
184         return traverseSeqChoice (choiceDecl, schemaDoc, grammar, allContextFlags, true, parent);
185     }
186 
187     /**
188      * Common traversal for <choice> and <sequence>
189      *
190      * @param decl
191      * @param schemaDoc
192      * @param grammar
193      * @param choice    If traversing <choice> this parameter is true.
194      * @return
195      */
196     private XSParticleDecl traverseSeqChoice(Element decl,
197             XSDocumentInfo schemaDoc,
198             SchemaGrammar grammar,
199             int allContextFlags,
200             boolean choice,
201             XSObject parent) {
202 
203         // General Attribute Checking
204         Object[] attrValues = fAttrChecker.checkAttributes(decl, false, schemaDoc);
205 
206         Element child = DOMUtil.getFirstChildElement(decl);
207         XSAnnotationImpl annotation = null;
208         if (child !=null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
209             annotation = traverseAnnotationDecl(child, attrValues, false, schemaDoc);
210             child = DOMUtil.getNextSiblingElement(child);
211         }
212         else {
213             String text = DOMUtil.getSyntheticAnnotation(decl);
214             if (text != null) {
215                 annotation = traverseSyntheticAnnotation(decl, text, attrValues, false, schemaDoc);
216             }
217         }
218 
219         String childName = null;
220         XSParticleDecl particle;
221         fPArray.pushContext();
222 
223         for (;child != null;child = DOMUtil.getNextSiblingElement(child)) {
224 
225             particle = null;
226 
227             childName = DOMUtil.getLocalName(child);
228             if (childName.equals(SchemaSymbols.ELT_ELEMENT)) {
229                 particle = fSchemaHandler.fElementTraverser.traverseLocal(child, schemaDoc, grammar, NOT_ALL_CONTEXT, parent);
230             }
231             else if (childName.equals(SchemaSymbols.ELT_GROUP)) {
232                 particle = fSchemaHandler.fGroupTraverser.traverseLocal(child, schemaDoc, grammar);
233 
234                 // A content type of all can only appear
235                 // as the content type of a complex type definition.
236                 if (hasAllContent(particle)) {
237                     // don't insert the "all" particle, otherwise we won't be
238                     // able to create DFA from this content model
239                     particle = null;
240                     reportSchemaError("cos-all-limited.1.2", null, child);
241                 }
242 
243             }
244             else if (childName.equals(SchemaSymbols.ELT_CHOICE)) {
245                 particle = traverseChoice(child, schemaDoc, grammar, NOT_ALL_CONTEXT, parent);
246             }
247             else if (childName.equals(SchemaSymbols.ELT_SEQUENCE)) {
248                 particle = traverseSequence(child, schemaDoc, grammar, NOT_ALL_CONTEXT, parent);
249             }
250             else if (childName.equals(SchemaSymbols.ELT_ANY)) {
251                 particle = fSchemaHandler.fWildCardTraverser.traverseAny(child, schemaDoc, grammar);
252             }
253             else {
254                 Object [] args;
255                 if (choice) {
256                     args = new Object[]{"choice", "(annotation?, (element | group | choice | sequence | any)*)", DOMUtil.getLocalName(child)};
257                 }
258                 else {
259                     args = new Object[]{"sequence", "(annotation?, (element | group | choice | sequence | any)*)", DOMUtil.getLocalName(child)};
260                 }
261                 reportSchemaError("s4s-elt-must-match.1", args, child);
262             }
263 
264             if (particle != null)
265                 fPArray.addParticle(particle);
266         }
267 
268         particle = null;
269 
270         XInt minAtt = (XInt)attrValues[XSAttributeChecker.ATTIDX_MINOCCURS];
271         XInt maxAtt = (XInt)attrValues[XSAttributeChecker.ATTIDX_MAXOCCURS];
272         Long defaultVals = (Long)attrValues[XSAttributeChecker.ATTIDX_FROMDEFAULT];
273 
274         XSModelGroupImpl group = new XSModelGroupImpl();
275         group.fCompositor = choice ? XSModelGroupImpl.MODELGROUP_CHOICE : XSModelGroupImpl.MODELGROUP_SEQUENCE;
276         group.fParticleCount = fPArray.getParticleCount();
277         group.fParticles = fPArray.popContext();
278         XSObjectList annotations;
279         if (annotation != null) {
280             annotations = new XSObjectListImpl();
281             ((XSObjectListImpl)annotations).addXSObject (annotation);
282         } else {
283             annotations = XSObjectListImpl.EMPTY_LIST;
284         }
285         group.fAnnotations = annotations;
286         particle = new XSParticleDecl();
287         particle.fType = XSParticleDecl.PARTICLE_MODELGROUP;
288         particle.fMinOccurs = minAtt.intValue();
289         particle.fMaxOccurs = maxAtt.intValue();
290         particle.fValue = group;
291         particle.fAnnotations = annotations;
292 
293         particle = checkOccurrences(particle,
294                 choice ? SchemaSymbols.ELT_CHOICE : SchemaSymbols.ELT_SEQUENCE,
295                         (Element)decl.getParentNode(),
296                         allContextFlags,
297                         defaultVals.longValue());
298         fAttrChecker.returnAttrArray(attrValues, schemaDoc);
299 
300         return particle;
301     }
302 
303     // Determines whether a content spec tree represents an "all" content model
304     protected boolean hasAllContent(XSParticleDecl particle) {
305         // If the content is not empty, is the top node ALL?
306         if (particle != null && particle.fType == XSParticleDecl.PARTICLE_MODELGROUP) {
307             return ((XSModelGroupImpl)particle.fValue).fCompositor == XSModelGroupImpl.MODELGROUP_ALL;
308         }
309 
310         return false;
311     }
312 
313     // the inner class: used to store particles for model groups
314     // to avoid creating a new Vector in each model group, or when traversing
315     // each model group, we use this one big array to store all particles
316     // for model groups. when the traversal finishes, this class returns an
317     // XSParticleDecl[] containing all particles for the current model group.
318     // it's possible that we need to traverse another model group while
319     // traversing one (one inside another one; referring to a global group,
320     // etc.), so we have push/pos context methods to save the same of the
321     // current traversal before starting the traversal of another model group.
322     protected static class ParticleArray {
323         // big array to contain all particles
324         XSParticleDecl[] fParticles = new XSParticleDecl[10];
325         // the ending position of particles in the array for each context
326         // index 0 is reserved, with value 0. index 1 is used for the fist
327         // context. so that the number of particles for context 'i' can be
328         // computed simply by fPos[i] - fPos[i-1].
329         int[] fPos = new int[5];
330         // number of contexts
331         int fContextCount = 0;
332 
333         // start a new context (start traversing a new model group)
334         void pushContext() {
335             fContextCount++;
336             // resize position array if necessary
337             if (fContextCount == fPos.length) {
338                 int newSize = fContextCount * 2;
339                 int[] newArray = new int[newSize];
340                 System.arraycopy(fPos, 0, newArray, 0, fContextCount);
341                 fPos = newArray;
342             }
343             // the initial ending position of the current context is the
344             // ending position of the previsous context. which means there is
345             // no particle for the current context yet.
346             fPos[fContextCount] = fPos[fContextCount-1];
347         }
348 
349         // get the number of particles of this context (model group)
350         int getParticleCount() {
351             return fPos[fContextCount] - fPos[fContextCount-1];
352         }
353 
354         // add a particle to the current context
355         void addParticle(XSParticleDecl particle) {
356             // resize the particle array if necessary
357             if (fPos[fContextCount] == fParticles.length) {
358                 int newSize = fPos[fContextCount] * 2;
359                 XSParticleDecl[] newArray = new XSParticleDecl[newSize];
360                 System.arraycopy(fParticles, 0, newArray, 0, fPos[fContextCount]);
361                 fParticles = newArray;
362             }
363             fParticles[fPos[fContextCount]++] = particle;
364         }
365 
366         // end the current context, and return an array of particles
367         XSParticleDecl[] popContext() {
368             int count = fPos[fContextCount] - fPos[fContextCount-1];
369             XSParticleDecl[] array = null;
370             if (count != 0) {
371                 array = new XSParticleDecl[count];
372                 System.arraycopy(fParticles, fPos[fContextCount-1], array, 0, count);
373                 // clear the particle array, to release memory
374                 for (int i = fPos[fContextCount-1]; i < fPos[fContextCount]; i++)
375                     fParticles[i] = null;
376             }
377             fContextCount--;
378             return array;
379         }
380 
381     }
382 
383     // the big particle array to hold all particles in model groups
384     ParticleArray fPArray = new ParticleArray();
385 }