KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * The Apache Software License, Version 1.1
3  *
4  *
5  * Copyright (c) 2001-2004 The Apache Software Foundation. All rights
6  * reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Apache Software Foundation (http://www.apache.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Xerces" and "Apache Software Foundation" must
28  * not be used to endorse or promote products derived from this
29  * software without prior written permission. For written
30  * permission, please contact apache@apache.org.
31  *
32  * 5. Products derived from this software may not be called "Apache",
33  * nor may "Apache" appear in their name, without prior written
34  * permission of the Apache Software Foundation.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
40  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47  * SUCH DAMAGE.
48  * ====================================================================
49  *
50  * This software consists of voluntary contributions made by many
51  * individuals on behalf of the Apache Software Foundation and was
52  * originally based on software copyright (c) 2001, International
53  * Business Machines, Inc., http://www.apache.org. For more
54  * information on the Apache Software Foundation, please see
55  * <http://www.apache.org/>.
56  */

57
58 package com.sun.org.apache.xerces.internal.impl.xs.traversers;
59
60 import com.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo;
61 import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType;
62 import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar;
63 import com.sun.org.apache.xerces.internal.impl.xs.SchemaSymbols;
64 import com.sun.org.apache.xerces.internal.impl.xs.XSAnnotationImpl;
65 import com.sun.org.apache.xerces.internal.impl.xs.XSComplexTypeDecl;
66 import com.sun.org.apache.xerces.internal.impl.xs.XSConstraints;
67 import com.sun.org.apache.xerces.internal.impl.xs.XSElementDecl;
68 import com.sun.org.apache.xerces.internal.impl.xs.XSParticleDecl;
69 import com.sun.org.apache.xerces.internal.xs.XSConstants;
70 import com.sun.org.apache.xerces.internal.xs.XSObject;
71 import com.sun.org.apache.xerces.internal.xs.XSTypeDefinition;
72 import com.sun.org.apache.xerces.internal.impl.xs.util.XInt;
73 import com.sun.org.apache.xerces.internal.util.DOMUtil;
74 import com.sun.org.apache.xerces.internal.util.SymbolTable;
75 import com.sun.org.apache.xerces.internal.xni.QName;
76 import org.w3c.dom.Element JavaDoc;
77 import org.w3c.dom.Attr JavaDoc;
78
79 /**
80  * The element declaration schema component traverser.
81  * <element
82  * abstract = boolean : false
83  * block = (#all | List of (extension | restriction | substitution))
84  * default = string
85  * final = (#all | List of (extension | restriction))
86  * fixed = string
87  * form = (qualified | unqualified)
88  * id = ID
89  * maxOccurs = (nonNegativeInteger | unbounded) : 1
90  * minOccurs = nonNegativeInteger : 1
91  * name = NCName
92  * nillable = boolean : false
93  * ref = QName
94  * substitutionGroup = QName
95  * type = QName
96  * {any attributes with non-schema namespace . . .}>
97  * Content: (annotation?, ((simpleType | complexType)?, (unique | key | keyref)*))
98  * </element>
99  *
100  * @author Sandy Gao, IBM
101  *
102  * @version $Id: XSDElementTraverser.java,v 1.29 2004/02/03 17:27:45 sandygao Exp $
103  */

104 class XSDElementTraverser extends XSDAbstractTraverser {
105
106     protected final XSElementDecl fTempElementDecl = new XSElementDecl();
107
108     // this controls what happens when a local element is encountered.
109
// We may not encounter all local elements when first parsing.
110
boolean fDeferTraversingLocalElements;
111
112     XSDElementTraverser (XSDHandler handler,
113                          XSAttributeChecker gAttrCheck) {
114         super(handler, gAttrCheck);
115     }
116
117     /**
118      * Traverse a locally declared element (or an element reference).
119      *
120      * To handle the recursive cases efficiently, we delay the traversal
121      * and return an empty particle node. We'll fill in this particle node
122      * later after we've done with all the global declarations.
123      * This method causes a number of data structures in the schema handler to be filled in.
124      *
125      * @param elmDecl
126      * @param schemaDoc
127      * @param grammar
128      * @return the particle
129      */

130     XSParticleDecl traverseLocal(Element JavaDoc elmDecl,
131                                  XSDocumentInfo schemaDoc,
132                                  SchemaGrammar grammar,
133                                  int allContextFlags,
134                                  XSObject parent) {
135
136         XSParticleDecl particle = null;
137         if (fSchemaHandler.fDeclPool !=null) {
138             particle = fSchemaHandler.fDeclPool.getParticleDecl();
139         } else {
140             particle = new XSParticleDecl();
141         }
142         if(fDeferTraversingLocalElements) {
143             // The only thing we care about now is whether this element has
144
// minOccurs=0. This affects (if the element appears in a complex
145
// type) whether a type has emptiable content.
146
particle.fType = XSParticleDecl.PARTICLE_ELEMENT;
147             Attr JavaDoc attr = elmDecl.getAttributeNode(SchemaSymbols.ATT_MINOCCURS);
148             if (attr != null) {
149                 String JavaDoc min = attr.getValue();
150                 try {
151                     int m = Integer.parseInt(min.trim());
152                     if (m >= 0)
153                         particle.fMinOccurs = m;
154                 }
155                 catch (NumberFormatException JavaDoc ex) {
156                 }
157             }
158             fSchemaHandler.fillInLocalElemInfo(elmDecl, schemaDoc, allContextFlags, parent, particle);
159         } else {
160             traverseLocal(particle, elmDecl, schemaDoc, grammar, allContextFlags, parent);
161             // If it's an empty particle, return null.
162
if (particle.fType == XSParticleDecl.PARTICLE_EMPTY)
163                 particle = null;
164         }
165
166         return particle;
167     }
168
169     /**
170      * Traverse a locally declared element (or an element reference).
171      *
172      * This is the real traversal method. It's called after we've done with
173      * all the global declarations.
174      *
175      * @param index
176      */

177     protected void traverseLocal(XSParticleDecl particle,
178                                  Element JavaDoc elmDecl,
179                                  XSDocumentInfo schemaDoc,
180                                  SchemaGrammar grammar,
181                                  int allContextFlags,
182                                  XSObject parent) {
183
184         // General Attribute Checking
185
Object JavaDoc[] attrValues = fAttrChecker.checkAttributes(elmDecl, false, schemaDoc);
186
187         QName refAtt = (QName) attrValues[XSAttributeChecker.ATTIDX_REF];
188         XInt minAtt = (XInt) attrValues[XSAttributeChecker.ATTIDX_MINOCCURS];
189         XInt maxAtt = (XInt) attrValues[XSAttributeChecker.ATTIDX_MAXOCCURS];
190
191         XSElementDecl element = null;
192         if (elmDecl.getAttributeNode(SchemaSymbols.ATT_REF) != null) {
193             if (refAtt != null) {
194                 element = (XSElementDecl)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.ELEMENT_TYPE, refAtt, elmDecl);
195
196                 Element JavaDoc child = DOMUtil.getFirstChildElement(elmDecl);
197                 if (child != null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
198                     // REVISIT: put this somewhere
199
traverseAnnotationDecl(child, attrValues, false, schemaDoc);
200                     child = DOMUtil.getNextSiblingElement(child);
201                 }
202
203                 // Element Declaration Representation OK
204
// 2 If the item's parent is not <schema>, then all of the following must be true:
205
// 2.1 One of ref or name must be present, but not both.
206
// 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>.
207
if (child != null) {
208                     reportSchemaError("src-element.2.2", new Object JavaDoc[]{refAtt.rawname, DOMUtil.getLocalName(child)}, child);
209                 }
210             } else {
211                 element = null;
212             }
213         } else {
214             element = traverseNamedElement(elmDecl, attrValues, schemaDoc, grammar, false, parent);
215         }
216
217         particle.fMinOccurs = minAtt.intValue();
218         particle.fMaxOccurs = maxAtt.intValue();
219         if (element != null) {
220             particle.fType = XSParticleDecl.PARTICLE_ELEMENT;
221             particle.fValue = element;
222         }
223         else {
224             particle.fType = XSParticleDecl.PARTICLE_EMPTY;
225         }
226         Long JavaDoc defaultVals = (Long JavaDoc)attrValues[XSAttributeChecker.ATTIDX_FROMDEFAULT];
227         checkOccurrences(particle, SchemaSymbols.ELT_ELEMENT,
228                          (Element JavaDoc)elmDecl.getParentNode(), allContextFlags,
229                          defaultVals.longValue());
230
231         fAttrChecker.returnAttrArray(attrValues, schemaDoc);
232     }
233
234     /**
235      * Traverse a globally declared element.
236      *
237      * @param elmDecl
238      * @param schemaDoc
239      * @param grammar
240      * @return the element declaration
241      */

242     XSElementDecl traverseGlobal(Element JavaDoc elmDecl,
243                                  XSDocumentInfo schemaDoc,
244                                  SchemaGrammar grammar) {
245
246         // General Attribute Checking
247
Object JavaDoc[] attrValues = fAttrChecker.checkAttributes(elmDecl, true, schemaDoc);
248         XSElementDecl element = traverseNamedElement(elmDecl, attrValues, schemaDoc, grammar, true, null);
249         fAttrChecker.returnAttrArray(attrValues, schemaDoc);
250         return element;
251
252     }
253
254     /**
255      * Traverse a globally declared element.
256      *
257      * @param elmDecl
258      * @param attrValues
259      * @param schemaDoc
260      * @param grammar
261      * @param isGlobal
262      * @return the element declaration
263      */

264     XSElementDecl traverseNamedElement(Element JavaDoc elmDecl,
265                                        Object JavaDoc[] attrValues,
266                                        XSDocumentInfo schemaDoc,
267                                        SchemaGrammar grammar,
268                                        boolean isGlobal,
269                                        XSObject parent) {
270
271         Boolean JavaDoc abstractAtt = (Boolean JavaDoc) attrValues[XSAttributeChecker.ATTIDX_ABSTRACT];
272         XInt blockAtt = (XInt) attrValues[XSAttributeChecker.ATTIDX_BLOCK];
273         String JavaDoc defaultAtt = (String JavaDoc) attrValues[XSAttributeChecker.ATTIDX_DEFAULT];
274         XInt finalAtt = (XInt) attrValues[XSAttributeChecker.ATTIDX_FINAL];
275         String JavaDoc fixedAtt = (String JavaDoc) attrValues[XSAttributeChecker.ATTIDX_FIXED];
276         XInt formAtt = (XInt) attrValues[XSAttributeChecker.ATTIDX_FORM];
277         String JavaDoc nameAtt = (String JavaDoc) attrValues[XSAttributeChecker.ATTIDX_NAME];
278         Boolean JavaDoc nillableAtt = (Boolean JavaDoc) attrValues[XSAttributeChecker.ATTIDX_NILLABLE];
279         QName subGroupAtt = (QName) attrValues[XSAttributeChecker.ATTIDX_SUBSGROUP];
280         QName typeAtt = (QName) attrValues[XSAttributeChecker.ATTIDX_TYPE];
281
282         // Step 1: get declaration information
283

284         XSElementDecl element = null;
285         if (fSchemaHandler.fDeclPool !=null) {
286             element = fSchemaHandler.fDeclPool.getElementDecl();
287         } else {
288             element = new XSElementDecl();
289         }
290         // get 'name'
291
if (nameAtt != null)
292             element.fName = fSymbolTable.addSymbol(nameAtt);
293
294         // get 'target namespace'
295
if (isGlobal) {
296             element.fTargetNamespace = schemaDoc.fTargetNamespace;
297             element.setIsGlobal();
298         }
299         else {
300             if (parent instanceof XSComplexTypeDecl)
301                 element.setIsLocal((XSComplexTypeDecl)parent);
302
303             if (formAtt != null) {
304                 if (formAtt.intValue() == SchemaSymbols.FORM_QUALIFIED)
305                     element.fTargetNamespace = schemaDoc.fTargetNamespace;
306                 else
307                     element.fTargetNamespace = null;
308             } else if (schemaDoc.fAreLocalElementsQualified) {
309                 element.fTargetNamespace = schemaDoc.fTargetNamespace;
310             } else {
311                 element.fTargetNamespace = null;
312             }
313         }
314
315         // get 'block', 'final', 'nillable', 'abstract'
316
element.fBlock = blockAtt == null ? schemaDoc.fBlockDefault : blockAtt.shortValue();
317         element.fFinal = finalAtt == null ? schemaDoc.fFinalDefault : finalAtt.shortValue();
318         // discard valid Block/Final 'Default' values that are invalid for Block/Final
319
element.fBlock &= (XSConstants.DERIVATION_EXTENSION | XSConstants.DERIVATION_RESTRICTION | XSConstants.DERIVATION_SUBSTITUTION);
320         element.fFinal &= (XSConstants.DERIVATION_EXTENSION | XSConstants.DERIVATION_RESTRICTION);
321
322         if (nillableAtt.booleanValue())
323             element.setIsNillable();
324         if (abstractAtt != null && abstractAtt.booleanValue())
325             element.setIsAbstract();
326
327         // get 'value constraint'
328
if (fixedAtt != null) {
329             element.fDefault = new ValidatedInfo();
330             element.fDefault.normalizedValue = fixedAtt;
331             element.setConstraintType(XSConstants.VC_FIXED);
332         } else if (defaultAtt != null) {
333             element.fDefault = new ValidatedInfo();
334             element.fDefault.normalizedValue = defaultAtt;
335             element.setConstraintType(XSConstants.VC_DEFAULT);
336         } else {
337             element.setConstraintType(XSConstants.VC_NONE);
338         }
339
340         // get 'substitutionGroup affiliation'
341
if (subGroupAtt != null) {
342             element.fSubGroup = (XSElementDecl)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.ELEMENT_TYPE, subGroupAtt, elmDecl);
343         }
344
345         // get 'annotation'
346
Element JavaDoc child = DOMUtil.getFirstChildElement(elmDecl);
347         XSAnnotationImpl annotation = null;
348         if(child != null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
349             annotation = traverseAnnotationDecl(child, attrValues, false, schemaDoc);
350             child = DOMUtil.getNextSiblingElement(child);
351         }
352         element.fAnnotation = annotation;
353
354         // get 'type definition'
355
XSTypeDefinition elementType = null;
356         boolean haveAnonType = false;
357
358         // Handle Anonymous type if there is one
359
if (child != null) {
360             String JavaDoc childName = DOMUtil.getLocalName(child);
361
362             if (childName.equals(SchemaSymbols.ELT_COMPLEXTYPE)) {
363                 elementType = fSchemaHandler.fComplexTypeTraverser.traverseLocal(child, schemaDoc, grammar);
364                 haveAnonType = true;
365                 child = DOMUtil.getNextSiblingElement(child);
366             }
367             else if (childName.equals(SchemaSymbols.ELT_SIMPLETYPE)) {
368                 elementType = fSchemaHandler.fSimpleTypeTraverser.traverseLocal(child, schemaDoc, grammar);
369                 haveAnonType = true;
370                 child = DOMUtil.getNextSiblingElement(child);
371             }
372         }
373
374         // Handler type attribute
375
if (elementType == null && typeAtt != null) {
376             elementType = (XSTypeDefinition)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.TYPEDECL_TYPE, typeAtt, elmDecl);
377         }
378
379         // Get it from the substitutionGroup declaration
380
if (elementType == null && element.fSubGroup != null) {
381             elementType = element.fSubGroup.fType;
382         }
383
384         if (elementType == null) {
385             elementType = SchemaGrammar.fAnyType;
386         }
387
388         element.fType = elementType;
389
390         // get 'identity constraint'
391

392         // see if there's something here; it had better be key, keyref or unique.
393
if (child != null) {
394             String JavaDoc childName = DOMUtil.getLocalName(child);
395             while (child != null &&
396                    (childName.equals(SchemaSymbols.ELT_KEY) ||
397                     childName.equals(SchemaSymbols.ELT_KEYREF) ||
398                     childName.equals(SchemaSymbols.ELT_UNIQUE))) {
399
400                 if (childName.equals(SchemaSymbols.ELT_KEY) ||
401                         childName.equals(SchemaSymbols.ELT_UNIQUE)) {
402                     // need to set <key>/<unique> to hidden before traversing it,
403
// because it has global scope
404
DOMUtil.setHidden(child);
405                     fSchemaHandler.fUniqueOrKeyTraverser.traverse(child, element, schemaDoc, grammar);
406                     if(DOMUtil.getAttrValue(child, SchemaSymbols.ATT_NAME).length() != 0 ) {
407                         fSchemaHandler.checkForDuplicateNames(
408                             (schemaDoc.fTargetNamespace == null) ? ","+DOMUtil.getAttrValue(child, SchemaSymbols.ATT_NAME)
409                             : schemaDoc.fTargetNamespace+","+ DOMUtil.getAttrValue(child, SchemaSymbols.ATT_NAME),
410                             fSchemaHandler.getIDRegistry(),
411                             child, schemaDoc);
412                     }
413                 } else if (childName.equals(SchemaSymbols.ELT_KEYREF)) {
414                     fSchemaHandler.storeKeyRef(child, schemaDoc, element);
415                 }
416                 child = DOMUtil.getNextSiblingElement(child);
417                 if (child != null) {
418                     childName = DOMUtil.getLocalName(child);
419                 }
420             }
421         }
422
423         // Step 2: register the element decl to the grammar
424
if (isGlobal && nameAtt != null)
425             grammar.addGlobalElementDecl(element);
426
427         // Step 3: check against schema for schemas
428

429         // required attributes
430
if (nameAtt == null) {
431             if (isGlobal)
432                 reportSchemaError("s4s-att-must-appear", new Object JavaDoc[]{SchemaSymbols.ELT_ELEMENT, SchemaSymbols.ATT_NAME}, elmDecl);
433             else
434                 reportSchemaError("src-element.2.1", null, elmDecl);
435             nameAtt = NO_NAME;
436         }
437
438         // element
439
if (child != null) {
440             reportSchemaError("s4s-elt-must-match.1", new Object JavaDoc[]{nameAtt, "(annotation?, (simpleType | complexType)?, (unique | key | keyref)*))", DOMUtil.getLocalName(child)}, child);
441         }
442
443         // Step 4: check 3.3.3 constraints
444

445         // src-element
446

447         // 1 default and fixed must not both be present.
448
if (defaultAtt != null && fixedAtt != null) {
449             reportSchemaError("src-element.1", new Object JavaDoc[]{nameAtt}, elmDecl);
450         }
451
452         // 2 If the item's parent is not <schema>, then all of the following must be true:
453
// 2.1 One of ref or name must be present, but not both.
454
// This is checked in XSAttributeChecker
455

456         // 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>.
457
// Attributes are checked in XSAttributeChecker, elements are checked in "traverse" method
458

459         // 3 type and either <simpleType> or <complexType> are mutually exclusive.
460
if (haveAnonType && (typeAtt != null)) {
461             reportSchemaError("src-element.3", new Object JavaDoc[]{nameAtt}, elmDecl);
462         }
463
464         // Step 5: check 3.3.6 constraints
465
// check for NOTATION type
466
checkNotationType(nameAtt, elementType, elmDecl);
467
468         // e-props-correct
469

470         // 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).
471
if (element.fDefault != null) {
472             fValidationState.setNamespaceSupport(schemaDoc.fNamespaceSupport);
473             if (XSConstraints.ElementDefaultValidImmediate(element.fType, element.fDefault.normalizedValue, fValidationState, element.fDefault) == null) {
474                 reportSchemaError ("e-props-correct.2", new Object JavaDoc[]{nameAtt, element.fDefault.normalizedValue}, elmDecl);
475                 element.setConstraintType(XSConstants.VC_NONE);
476             }
477         }
478
479         // 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).
480
if (element.fSubGroup != null) {
481            if (!XSConstraints.checkTypeDerivationOk(element.fType, element.fSubGroup.fType, element.fSubGroup.fFinal)) {
482                 reportSchemaError ("e-props-correct.4", new Object JavaDoc[]{nameAtt, subGroupAtt.prefix+":"+subGroupAtt.localpart}, elmDecl);
483            }
484         }
485
486         // 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}.
487
if (element.fDefault != null) {
488             if ((elementType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE &&
489                  ((XSSimpleType)elementType).isIDType()) ||
490                 (elementType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE &&
491                  ((XSComplexTypeDecl)elementType).containsTypeID())) {
492                 reportSchemaError ("e-props-correct.5", new Object JavaDoc[]{element.fName}, elmDecl);
493             }
494         }
495
496         // Element without a name. Return null.
497
if (element.fName == null)
498             return null;
499
500         return element;
501     }
502
503     void reset(SymbolTable symbolTable) {
504         super.reset(symbolTable);
505         fDeferTraversingLocalElements = true;
506     } // reset()
507

508 }
509
Popular Tags