KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xerces > impl > xs > traversers > XSDElementTraverser


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

16
17 package org.apache.xerces.impl.xs.traversers;
18
19 import org.apache.xerces.impl.dv.ValidatedInfo;
20 import org.apache.xerces.impl.dv.XSSimpleType;
21 import org.apache.xerces.impl.xs.SchemaGrammar;
22 import org.apache.xerces.impl.xs.SchemaSymbols;
23 import org.apache.xerces.impl.xs.XSAnnotationImpl;
24 import org.apache.xerces.impl.xs.XSComplexTypeDecl;
25 import org.apache.xerces.impl.xs.XSConstraints;
26 import org.apache.xerces.impl.xs.XSElementDecl;
27 import org.apache.xerces.impl.xs.XSParticleDecl;
28 import org.apache.xerces.xs.XSConstants;
29 import org.apache.xerces.xs.XSObject;
30 import org.apache.xerces.xs.XSTypeDefinition;
31 import org.apache.xerces.impl.xs.util.XInt;
32 import org.apache.xerces.util.DOMUtil;
33 import org.apache.xerces.util.SymbolTable;
34 import org.apache.xerces.xni.QName;
35 import org.w3c.dom.Element JavaDoc;
36 import org.w3c.dom.Attr JavaDoc;
37
38 /**
39  * The element declaration schema component traverser.
40  * <element
41  * abstract = boolean : false
42  * block = (#all | List of (extension | restriction | substitution))
43  * default = string
44  * final = (#all | List of (extension | restriction))
45  * fixed = string
46  * form = (qualified | unqualified)
47  * id = ID
48  * maxOccurs = (nonNegativeInteger | unbounded) : 1
49  * minOccurs = nonNegativeInteger : 1
50  * name = NCName
51  * nillable = boolean : false
52  * ref = QName
53  * substitutionGroup = QName
54  * type = QName
55  * {any attributes with non-schema namespace . . .}>
56  * Content: (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*))
57  * </element>
58  *
59  * @xerces.internal
60  *
61  * @author Sandy Gao, IBM
62  *
63  * @version $Id: XSDElementTraverser.java,v 1.37 2005/05/30 04:17:12 mrglavas Exp $
64  */

65 class XSDElementTraverser extends XSDAbstractTraverser {
66     
67     protected final XSElementDecl fTempElementDecl = new XSElementDecl();
68     
69     // this controls what happens when a local element is encountered.
70
// We may not encounter all local elements when first parsing.
71
boolean fDeferTraversingLocalElements;
72     
73     XSDElementTraverser (XSDHandler handler,
74             XSAttributeChecker gAttrCheck) {
75         super(handler, gAttrCheck);
76     }
77     
78     /**
79      * Traverse a locally declared element (or an element reference).
80      *
81      * To handle the recursive cases efficiently, we delay the traversal
82      * and return an empty particle node. We'll fill in this particle node
83      * later after we've done with all the global declarations.
84      * This method causes a number of data structures in the schema handler to be filled in.
85      *
86      * @param elmDecl
87      * @param schemaDoc
88      * @param grammar
89      * @return the particle
90      */

91     XSParticleDecl traverseLocal(Element JavaDoc elmDecl,
92             XSDocumentInfo schemaDoc,
93             SchemaGrammar grammar,
94             int allContextFlags,
95             XSObject parent) {
96         
97         XSParticleDecl particle = null;
98         if (fSchemaHandler.fDeclPool !=null) {
99             particle = fSchemaHandler.fDeclPool.getParticleDecl();
100         } else {
101             particle = new XSParticleDecl();
102         }
103         if(fDeferTraversingLocalElements) {
104             // The only thing we care about now is whether this element has
105
// minOccurs=0. This affects (if the element appears in a complex
106
// type) whether a type has emptiable content.
107
particle.fType = XSParticleDecl.PARTICLE_ELEMENT;
108             Attr JavaDoc attr = elmDecl.getAttributeNode(SchemaSymbols.ATT_MINOCCURS);
109             if (attr != null) {
110                 String JavaDoc min = attr.getValue();
111                 try {
112                     int m = Integer.parseInt(min.trim());
113                     if (m >= 0)
114                         particle.fMinOccurs = m;
115                 }
116                 catch (NumberFormatException JavaDoc ex) {
117                 }
118             }
119             fSchemaHandler.fillInLocalElemInfo(elmDecl, schemaDoc, allContextFlags, parent, particle);
120         } else {
121             traverseLocal(particle, elmDecl, schemaDoc, grammar, allContextFlags, parent, null);
122             // If it's an empty particle, return null.
123
if (particle.fType == XSParticleDecl.PARTICLE_EMPTY)
124                 particle = null;
125         }
126         
127         return particle;
128     }
129     
130     /**
131      * Traverse a locally declared element (or an element reference).
132      *
133      * This is the real traversal method. It's called after we've done with
134      * all the global declarations.
135      *
136      * @param index
137      */

138     protected void traverseLocal(XSParticleDecl particle,
139             Element JavaDoc elmDecl,
140             XSDocumentInfo schemaDoc,
141             SchemaGrammar grammar,
142             int allContextFlags,
143             XSObject parent,
144             String JavaDoc[] localNSDecls) {
145         
146         if (localNSDecls != null) {
147             schemaDoc.fNamespaceSupport.setEffectiveContext(localNSDecls);
148         }
149         
150         // General Attribute Checking
151
Object JavaDoc[] attrValues = fAttrChecker.checkAttributes(elmDecl, false, schemaDoc);
152         
153         QName refAtt = (QName) attrValues[XSAttributeChecker.ATTIDX_REF];
154         XInt minAtt = (XInt) attrValues[XSAttributeChecker.ATTIDX_MINOCCURS];
155         XInt maxAtt = (XInt) attrValues[XSAttributeChecker.ATTIDX_MAXOCCURS];
156         
157         XSElementDecl element = null;
158         if (elmDecl.getAttributeNode(SchemaSymbols.ATT_REF) != null) {
159             if (refAtt != null) {
160                 element = (XSElementDecl)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.ELEMENT_TYPE, refAtt, elmDecl);
161                 
162                 Element JavaDoc child = DOMUtil.getFirstChildElement(elmDecl);
163                 if (child != null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
164                     // REVISIT: put this somewhere
165
traverseAnnotationDecl(child, attrValues, false, schemaDoc);
166                     child = DOMUtil.getNextSiblingElement(child);
167                 }
168                 // Element Declaration Representation OK
169
// 2 If the item's parent is not <schema>, then all of the following must be true:
170
// 2.1 One of ref or name must be present, but not both.
171
// 2.2 If ref is present, then all of <complexType>, <simpleType>, <key>, <keyref>, <unique>, nillable, default, fixed, form, block and type must be absent, i.e. only minOccurs, maxOccurs, id are allowed in addition to ref, along with <annotation>.
172
if (child != null) {
173                     reportSchemaError("src-element.2.2", new Object JavaDoc[]{refAtt.rawname, DOMUtil.getLocalName(child)}, child);
174                 }
175             } else {
176                 element = null;
177             }
178         } else {
179             element = traverseNamedElement(elmDecl, attrValues, schemaDoc, grammar, false, parent);
180         }
181         
182         particle.fMinOccurs = minAtt.intValue();
183         particle.fMaxOccurs = maxAtt.intValue();
184         if (element != null) {
185             particle.fType = XSParticleDecl.PARTICLE_ELEMENT;
186             particle.fValue = element;
187         }
188         else {
189             particle.fType = XSParticleDecl.PARTICLE_EMPTY;
190         }
191         Long JavaDoc defaultVals = (Long JavaDoc)attrValues[XSAttributeChecker.ATTIDX_FROMDEFAULT];
192         checkOccurrences(particle, SchemaSymbols.ELT_ELEMENT,
193                 (Element JavaDoc)elmDecl.getParentNode(), allContextFlags,
194                 defaultVals.longValue());
195         
196         fAttrChecker.returnAttrArray(attrValues, schemaDoc);
197     }
198     
199     /**
200      * Traverse a globally declared element.
201      *
202      * @param elmDecl
203      * @param schemaDoc
204      * @param grammar
205      * @return the element declaration
206      */

207     XSElementDecl traverseGlobal(Element JavaDoc elmDecl,
208             XSDocumentInfo schemaDoc,
209             SchemaGrammar grammar) {
210         
211         // General Attribute Checking'
212

213         Object JavaDoc[] attrValues = fAttrChecker.checkAttributes(elmDecl, true, schemaDoc);
214         XSElementDecl element = traverseNamedElement(elmDecl, attrValues, schemaDoc, grammar, true, null);
215         fAttrChecker.returnAttrArray(attrValues, schemaDoc);
216         return element;
217         
218     }
219     
220     /**
221      * Traverse a globally declared element.
222      *
223      * @param elmDecl
224      * @param attrValues
225      * @param schemaDoc
226      * @param grammar
227      * @param isGlobal
228      * @return the element declaration
229      */

230     XSElementDecl traverseNamedElement(Element JavaDoc elmDecl,
231             Object JavaDoc[] attrValues,
232             XSDocumentInfo schemaDoc,
233             SchemaGrammar grammar,
234             boolean isGlobal,
235             XSObject parent) {
236         
237         Boolean JavaDoc abstractAtt = (Boolean JavaDoc) attrValues[XSAttributeChecker.ATTIDX_ABSTRACT];
238         XInt blockAtt = (XInt) attrValues[XSAttributeChecker.ATTIDX_BLOCK];
239         String JavaDoc defaultAtt = (String JavaDoc) attrValues[XSAttributeChecker.ATTIDX_DEFAULT];
240         XInt finalAtt = (XInt) attrValues[XSAttributeChecker.ATTIDX_FINAL];
241         String JavaDoc fixedAtt = (String JavaDoc) attrValues[XSAttributeChecker.ATTIDX_FIXED];
242         XInt formAtt = (XInt) attrValues[XSAttributeChecker.ATTIDX_FORM];
243         String JavaDoc nameAtt = (String JavaDoc) attrValues[XSAttributeChecker.ATTIDX_NAME];
244         Boolean JavaDoc nillableAtt = (Boolean JavaDoc) attrValues[XSAttributeChecker.ATTIDX_NILLABLE];
245         QName subGroupAtt = (QName) attrValues[XSAttributeChecker.ATTIDX_SUBSGROUP];
246         QName typeAtt = (QName) attrValues[XSAttributeChecker.ATTIDX_TYPE];
247         
248         // Step 1: get declaration information
249

250         XSElementDecl element = null;
251         if (fSchemaHandler.fDeclPool !=null) {
252             element = fSchemaHandler.fDeclPool.getElementDecl();
253         } else {
254             element = new XSElementDecl();
255         }
256         // get 'name'
257
if (nameAtt != null)
258             element.fName = fSymbolTable.addSymbol(nameAtt);
259         
260         // get 'target namespace'
261
if (isGlobal) {
262             element.fTargetNamespace = schemaDoc.fTargetNamespace;
263             element.setIsGlobal();
264         }
265         else {
266             if (parent instanceof XSComplexTypeDecl)
267                 element.setIsLocal((XSComplexTypeDecl)parent);
268             
269             if (formAtt != null) {
270                 if (formAtt.intValue() == SchemaSymbols.FORM_QUALIFIED)
271                     element.fTargetNamespace = schemaDoc.fTargetNamespace;
272                 else
273                     element.fTargetNamespace = null;
274             } else if (schemaDoc.fAreLocalElementsQualified) {
275                 element.fTargetNamespace = schemaDoc.fTargetNamespace;
276             } else {
277                 element.fTargetNamespace = null;
278             }
279         }
280         
281         // get 'block', 'final', 'nillable', 'abstract'
282
element.fBlock = blockAtt == null ? schemaDoc.fBlockDefault : blockAtt.shortValue();
283         element.fFinal = finalAtt == null ? schemaDoc.fFinalDefault : finalAtt.shortValue();
284         // discard valid Block/Final 'Default' values that are invalid for Block/Final
285
element.fBlock &= (XSConstants.DERIVATION_EXTENSION | XSConstants.DERIVATION_RESTRICTION | XSConstants.DERIVATION_SUBSTITUTION);
286         element.fFinal &= (XSConstants.DERIVATION_EXTENSION | XSConstants.DERIVATION_RESTRICTION);
287         
288         if (nillableAtt.booleanValue())
289             element.setIsNillable();
290         if (abstractAtt != null && abstractAtt.booleanValue())
291             element.setIsAbstract();
292         
293         // get 'value constraint'
294
if (fixedAtt != null) {
295             element.fDefault = new ValidatedInfo();
296             element.fDefault.normalizedValue = fixedAtt;
297             element.setConstraintType(XSConstants.VC_FIXED);
298         } else if (defaultAtt != null) {
299             element.fDefault = new ValidatedInfo();
300             element.fDefault.normalizedValue = defaultAtt;
301             element.setConstraintType(XSConstants.VC_DEFAULT);
302         } else {
303             element.setConstraintType(XSConstants.VC_NONE);
304         }
305         
306         // get 'substitutionGroup affiliation'
307
if (subGroupAtt != null) {
308             element.fSubGroup = (XSElementDecl)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.ELEMENT_TYPE, subGroupAtt, elmDecl);
309         }
310         
311         // get 'annotation'
312
Element JavaDoc child = DOMUtil.getFirstChildElement(elmDecl);
313         XSAnnotationImpl annotation = null;
314         if(child != null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
315             annotation = traverseAnnotationDecl(child, attrValues, false, schemaDoc);
316             child = DOMUtil.getNextSiblingElement(child);
317         }
318         else {
319             String JavaDoc text = DOMUtil.getSyntheticAnnotation(elmDecl);
320             if (text != null) {
321                 annotation = traverseSyntheticAnnotation(elmDecl, text, attrValues, false, schemaDoc);
322             }
323         }
324         element.fAnnotation = annotation;
325         
326         // get 'type definition'
327
XSTypeDefinition elementType = null;
328         boolean haveAnonType = false;
329         
330         // Handle Anonymous type if there is one
331
if (child != null) {
332             String JavaDoc childName = DOMUtil.getLocalName(child);
333             
334             if (childName.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
335                 elementType = fSchemaHandler.fComplexTypeTraverser.traverseLocal(child, schemaDoc, grammar);
336                 haveAnonType = true;
337                 child = DOMUtil.getNextSiblingElement(child);
338             }
339             else if (childName.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
340                 elementType = fSchemaHandler.fSimpleTypeTraverser.traverseLocal(child, schemaDoc, grammar);
341                 haveAnonType = true;
342                 child = DOMUtil.getNextSiblingElement(child);
343             }
344         }
345         
346         // Handler type attribute
347
if (elementType == null && typeAtt != null) {
348             elementType = (XSTypeDefinition)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.TYPEDECL_TYPE, typeAtt, elmDecl);
349         }
350         
351         // Get it from the substitutionGroup declaration
352
if (elementType == null && element.fSubGroup != null) {
353             elementType = element.fSubGroup.fType;
354         }
355         
356         if (elementType == null) {
357             elementType = SchemaGrammar.fAnyType;
358         }
359         
360         element.fType = elementType;
361         
362         // get 'identity constraint'
363

364         // see if there's something here; it had better be key, keyref or unique.
365
if (child != null) {
366             String JavaDoc childName = DOMUtil.getLocalName(child);
367             while (child != null &&
368                     (childName.equals(SchemaSymbols.ELT_KEY) ||
369                             childName.equals(SchemaSymbols.ELT_KEYREF) ||
370                             childName.equals(SchemaSymbols.ELT_UNIQUE))) {
371                 
372                 if (childName.equals(SchemaSymbols.ELT_KEY) ||
373                         childName.equals(SchemaSymbols.ELT_UNIQUE)) {
374                     // need to set <key>/<unique> to hidden before traversing it,
375
// because it has global scope
376
DOMUtil.setHidden(child);
377                     fSchemaHandler.fUniqueOrKeyTraverser.traverse(child, element, schemaDoc, grammar);
378                     if(DOMUtil.getAttrValue(child, SchemaSymbols.ATT_NAME).length() != 0 ) {
379                         fSchemaHandler.checkForDuplicateNames(
380                                 (schemaDoc.fTargetNamespace == null) ? ","+DOMUtil.getAttrValue(child, SchemaSymbols.ATT_NAME)
381                                         : schemaDoc.fTargetNamespace+","+ DOMUtil.getAttrValue(child, SchemaSymbols.ATT_NAME),
382                                         fSchemaHandler.getIDRegistry(), fSchemaHandler.getIDRegistry_sub(),
383                                         child, schemaDoc);
384                     }
385                 } else if (childName.equals(SchemaSymbols.ELT_KEYREF)) {
386                     fSchemaHandler.storeKeyRef(child, schemaDoc, element);
387                 }
388                 child = DOMUtil.getNextSiblingElement(child);
389                 if (child != null) {
390                     childName = DOMUtil.getLocalName(child);
391                 }
392             }
393         }
394         
395         // Step 2: register the element decl to the grammar
396
if (isGlobal && nameAtt != null)
397             grammar.addGlobalElementDecl(element);
398         
399         // Step 3: check against schema for schemas
400

401         // required attributes
402
if (nameAtt == null) {
403             if (isGlobal)
404                 reportSchemaError("s4s-att-must-appear", new Object JavaDoc[]{SchemaSymbols.ELT_ELEMENT, SchemaSymbols.ATT_NAME}, elmDecl);
405             else
406                 reportSchemaError("src-element.2.1", null, elmDecl);
407             nameAtt = NO_NAME;
408         }
409         
410         // element
411
if (child != null) {
412             reportSchemaError("s4s-elt-must-match.1", new Object JavaDoc[]{nameAtt, "(annotation?, (simpleType | complexType)?, (unique | key | keyref)*))", DOMUtil.getLocalName(child)}, child);
413         }
414         
415         // Step 4: check 3.3.3 constraints
416

417         // src-element
418

419         // 1 default and fixed must not both be present.
420
if (defaultAtt != null && fixedAtt != null) {
421             reportSchemaError("src-element.1", new Object JavaDoc[]{nameAtt}, elmDecl);
422         }
423         
424         // 2 If the item's parent is not <schema>, then all of the following must be true:
425
// 2.1 One of ref or name must be present, but not both.
426
// This is checked in XSAttributeChecker
427

428         // 2.2 If ref is present, then all of <complexType>, <simpleType>, <key>, <keyref>, <unique>, nillable, default, fixed, form, block and type must be absent, i.e. only minOccurs, maxOccurs, id are allowed in addition to ref, along with <annotation>.
429
// Attributes are checked in XSAttributeChecker, elements are checked in "traverse" method
430

431         // 3 type and either <simpleType> or <complexType> are mutually exclusive.
432
if (haveAnonType && (typeAtt != null)) {
433             reportSchemaError("src-element.3", new Object JavaDoc[]{nameAtt}, elmDecl);
434         }
435         
436         // Step 5: check 3.3.6 constraints
437
// check for NOTATION type
438
checkNotationType(nameAtt, elementType, elmDecl);
439         
440         // e-props-correct
441

442         // 2 If there is a {value constraint}, the canonical lexical representation of its value must be valid with respect to the {type definition} as defined in Element Default Valid (Immediate) (3.3.6).
443
if (element.fDefault != null) {
444             fValidationState.setNamespaceSupport(schemaDoc.fNamespaceSupport);
445             if (XSConstraints.ElementDefaultValidImmediate(element.fType, element.fDefault.normalizedValue, fValidationState, element.fDefault) == null) {
446                 reportSchemaError ("e-props-correct.2", new Object JavaDoc[]{nameAtt, element.fDefault.normalizedValue}, elmDecl);
447                 element.setConstraintType(XSConstants.VC_NONE);
448             }
449         }
450         
451         // 4 If there is an {substitution group affiliation}, the {type definition} of the element declaration must be validly derived from the {type definition} of the {substitution group affiliation}, given the value of the {substitution group exclusions} of the {substitution group affiliation}, as defined in Type Derivation OK (Complex) (3.4.6) (if the {type definition} is complex) or as defined in Type Derivation OK (Simple) (3.14.6) (if the {type definition} is simple).
452
if (element.fSubGroup != null) {
453             if (!XSConstraints.checkTypeDerivationOk(element.fType, element.fSubGroup.fType, element.fSubGroup.fFinal)) {
454                 reportSchemaError ("e-props-correct.4", new Object JavaDoc[]{nameAtt, subGroupAtt.prefix+":"+subGroupAtt.localpart}, elmDecl);
455             }
456         }
457         
458         // 5 If the {type definition} or {type definition}'s {content type} is or is derived from ID then there must not be a {value constraint}.
459
if (element.fDefault != null) {
460             if ((elementType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE &&
461                     ((XSSimpleType)elementType).isIDType()) ||
462                     (elementType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE &&
463                             ((XSComplexTypeDecl)elementType).containsTypeID())) {
464                 reportSchemaError ("e-props-correct.5", new Object JavaDoc[]{element.fName}, elmDecl);
465             }
466         }
467         
468         // Element without a name. Return null.
469
if (element.fName == null)
470             return null;
471         
472         return element;
473     }
474     
475     void reset(SymbolTable symbolTable, boolean validateAnnotations) {
476         super.reset(symbolTable, validateAnnotations);
477         fDeferTraversingLocalElements = true;
478     } // reset()
479

480 }
481
Popular Tags