KickJava   Java API By Example, From Geeks To Geeks.

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


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 java.util.Vector JavaDoc;
20
21 import org.apache.xerces.impl.dv.InvalidDatatypeFacetException;
22 import org.apache.xerces.impl.dv.SchemaDVFactory;
23 import org.apache.xerces.impl.dv.XSSimpleType;
24 import org.apache.xerces.impl.dv.xs.SchemaDVFactoryImpl;
25 import org.apache.xerces.impl.dv.xs.XSSimpleTypeDecl;
26 import org.apache.xerces.impl.xs.SchemaGrammar;
27 import org.apache.xerces.impl.xs.SchemaSymbols;
28 import org.apache.xerces.impl.xs.XSAnnotationImpl;
29 import org.apache.xerces.impl.xs.util.XInt;
30 import org.apache.xerces.impl.xs.util.XSObjectListImpl;
31 import org.apache.xerces.util.DOMUtil;
32 import org.apache.xerces.xni.QName;
33 import org.apache.xerces.xs.XSConstants;
34 import org.apache.xerces.xs.XSObjectList;
35 import org.apache.xerces.xs.XSTypeDefinition;
36 import org.w3c.dom.Element JavaDoc;
37
38 /**
39  * The simple type definition schema component traverser.
40  *
41  * <simpleType
42  * final = (#all | (list | union | restriction))
43  * id = ID
44  * name = NCName
45  * {any attributes with non-schema namespace . . .}>
46  * Content: (annotation?, (restriction | list | union))
47  * </simpleType>
48  *
49  * <restriction
50  * base = QName
51  * id = ID
52  * {any attributes with non-schema namespace . . .}>
53  * Content: (annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*))
54  * </restriction>
55  *
56  * <list
57  * id = ID
58  * itemType = QName
59  * {any attributes with non-schema namespace . . .}>
60  * Content: (annotation?, (simpleType?))
61  * </list>
62  *
63  * <union
64  * id = ID
65  * memberTypes = List of QName
66  * {any attributes with non-schema namespace . . .}>
67  * Content: (annotation?, (simpleType*))
68  * </union>
69  *
70  * @xerces.internal
71  *
72  * @author Elena Litani, IBM
73  * @author Neeraj Bajaj, Sun Microsystems, Inc.
74  * @author Sandy Gao, IBM
75  *
76  * @version $Id: XSDSimpleTypeTraverser.java,v 1.33 2005/05/28 02:03:58 mrglavas Exp $
77  */

78 class XSDSimpleTypeTraverser extends XSDAbstractTraverser {
79     
80     // the factory used to query/create simple types
81
private final SchemaDVFactory schemaFactory = SchemaDVFactory.getInstance();
82     
83     // whether the type being parsed is a S4S built-in type.
84
private boolean fIsBuiltIn = false;
85     
86     XSDSimpleTypeTraverser (XSDHandler handler,
87             XSAttributeChecker gAttrCheck) {
88         super(handler, gAttrCheck);
89         if (schemaFactory instanceof SchemaDVFactoryImpl) {
90             ((SchemaDVFactoryImpl)schemaFactory).setDeclPool(handler.fDeclPool);
91         }
92     }
93     
94     //return qualified name of simpleType or empty string if error occured
95
XSSimpleType traverseGlobal(Element JavaDoc elmNode,
96             XSDocumentInfo schemaDoc,
97             SchemaGrammar grammar) {
98         
99         // General Attribute Checking
100
Object JavaDoc[] attrValues = fAttrChecker.checkAttributes(elmNode, true, schemaDoc);
101         String JavaDoc nameAtt = (String JavaDoc)attrValues[XSAttributeChecker.ATTIDX_NAME];
102         XSSimpleType type = traverseSimpleTypeDecl(elmNode, attrValues, schemaDoc, grammar);
103         fAttrChecker.returnAttrArray(attrValues, schemaDoc);
104         
105         // if it's a global type without a name, return null
106
if (nameAtt == null) {
107             reportSchemaError("s4s-att-must-appear", new Object JavaDoc[]{SchemaSymbols.ELT_SIMPLETYPE, SchemaSymbols.ATT_NAME}, elmNode);
108             type = null;
109         }
110         
111         // don't add global components without name to the grammar
112
if (type != null) {
113             grammar.addGlobalTypeDecl(type);
114         }
115         
116         return type;
117     }
118     
119     XSSimpleType traverseLocal(Element JavaDoc elmNode,
120             XSDocumentInfo schemaDoc,
121             SchemaGrammar grammar) {
122         
123         // General Attribute Checking
124
Object JavaDoc[] attrValues = fAttrChecker.checkAttributes(elmNode, false, schemaDoc);
125         String JavaDoc name = genAnonTypeName(elmNode);
126         XSSimpleType type = getSimpleType (name, elmNode, attrValues, schemaDoc, grammar);
127         if (type instanceof XSSimpleTypeDecl) {
128             ((XSSimpleTypeDecl)type).setAnonymous(true);
129         }
130         fAttrChecker.returnAttrArray(attrValues, schemaDoc);
131         
132         return type;
133     }
134     
135     private XSSimpleType traverseSimpleTypeDecl(Element JavaDoc simpleTypeDecl,
136             Object JavaDoc[] attrValues,
137             XSDocumentInfo schemaDoc,
138             SchemaGrammar grammar) {
139         
140         // get name and final values
141
String JavaDoc name = (String JavaDoc)attrValues[XSAttributeChecker.ATTIDX_NAME];
142         return getSimpleType(name, simpleTypeDecl, attrValues, schemaDoc, grammar);
143     }
144     
145     /*
146      * Generate a name for an anonymous type
147      */

148     private String JavaDoc genAnonTypeName(Element JavaDoc simpleTypeDecl) {
149         
150         // Generate a unique name for the anonymous type by concatenating together the
151
// names of parent nodes
152
// The name is quite good for debugging/error purposes, but we may want to
153
// revisit how this is done for performance reasons (LM).
154
StringBuffer JavaDoc typeName = new StringBuffer JavaDoc("#AnonType_");
155         Element JavaDoc node = DOMUtil.getParent(simpleTypeDecl);
156         while (node != null && (node != DOMUtil.getRoot(DOMUtil.getDocument(node)))) {
157             typeName.append(node.getAttribute(SchemaSymbols.ATT_NAME));
158             node = DOMUtil.getParent(node);
159         }
160         return typeName.toString();
161     }
162
163     /**
164      * @param name
165      * @param simpleTypeDecl
166      * @param attrValues
167      * @param schemaDoc
168      * @param grammar
169      * @return
170      */

171     private XSSimpleType getSimpleType(String JavaDoc name, Element JavaDoc simpleTypeDecl, Object JavaDoc[] attrValues, XSDocumentInfo schemaDoc, SchemaGrammar grammar) {
172         XInt finalAttr = (XInt)attrValues[XSAttributeChecker.ATTIDX_FINAL];
173         int finalProperty = finalAttr == null ? schemaDoc.fFinalDefault : finalAttr.intValue();
174         // annotation?,(list|restriction|union)
175
Element JavaDoc child = DOMUtil.getFirstChildElement(simpleTypeDecl);
176         XSAnnotationImpl [] annotations = null;
177         if (child != null && DOMUtil.getLocalName(child).equals(SchemaSymbols.ELT_ANNOTATION)) {
178             XSAnnotationImpl annotation = traverseAnnotationDecl(child, attrValues, false, schemaDoc);
179             if (annotation != null)
180                 annotations = new XSAnnotationImpl [] {annotation};
181             child = DOMUtil.getNextSiblingElement(child);
182         }
183         else {
184             String JavaDoc text = DOMUtil.getSyntheticAnnotation(simpleTypeDecl);
185             if (text != null) {
186                 XSAnnotationImpl annotation = traverseSyntheticAnnotation(simpleTypeDecl, text, attrValues, false, schemaDoc);
187                 annotations = new XSAnnotationImpl[] {annotation};
188             }
189         }
190         // (list|restriction|union)
191
if (child == null) {
192             reportSchemaError("s4s-elt-must-match.2", new Object JavaDoc[]{SchemaSymbols.ELT_SIMPLETYPE, "(annotation?, (restriction | list | union))"}, simpleTypeDecl);
193             return errorType(name, schemaDoc.fTargetNamespace, XSConstants.DERIVATION_RESTRICTION);
194         }
195         // derivation type: restriction/list/union
196
String JavaDoc varietyProperty = DOMUtil.getLocalName(child);
197         short refType = XSConstants.DERIVATION_RESTRICTION;
198         boolean restriction = false, list = false, union = false;
199         if (varietyProperty.equals(SchemaSymbols.ELT_RESTRICTION)) {
200             refType = XSConstants.DERIVATION_RESTRICTION;
201             restriction = true;
202         }
203         else if (varietyProperty.equals(SchemaSymbols.ELT_LIST)) {
204             refType = XSConstants.DERIVATION_LIST;
205             list = true;
206         }
207         else if (varietyProperty.equals(SchemaSymbols.ELT_UNION)) {
208             refType = XSConstants.DERIVATION_UNION;
209             union = true;
210         }
211         else {
212             reportSchemaError("s4s-elt-must-match.1", new Object JavaDoc[]{SchemaSymbols.ELT_SIMPLETYPE, "(annotation?, (restriction | list | union))", varietyProperty}, simpleTypeDecl);
213             return errorType(name, schemaDoc.fTargetNamespace, XSConstants.DERIVATION_RESTRICTION);
214         }
215         // nothing should follow this element
216
Element JavaDoc nextChild = DOMUtil.getNextSiblingElement(child);
217         if (nextChild != null) {
218             reportSchemaError("s4s-elt-must-match.1", new Object JavaDoc[]{SchemaSymbols.ELT_SIMPLETYPE, "(annotation?, (restriction | list | union))", DOMUtil.getLocalName(nextChild)}, nextChild);
219         }
220         // General Attribute Checking: get base/item/member types
221
Object JavaDoc[] contentAttrs = fAttrChecker.checkAttributes(child, false, schemaDoc);
222         QName baseTypeName = (QName)contentAttrs[restriction ?
223                 XSAttributeChecker.ATTIDX_BASE :
224                     XSAttributeChecker.ATTIDX_ITEMTYPE];
225         Vector JavaDoc memberTypes = (Vector JavaDoc)contentAttrs[XSAttributeChecker.ATTIDX_MEMBERTYPES];
226         //content = {annotation?,simpleType?...}
227
Element JavaDoc content = DOMUtil.getFirstChildElement(child);
228         //check content (annotation?, ...)
229
if (content != null && DOMUtil.getLocalName(content).equals(SchemaSymbols.ELT_ANNOTATION)) {
230             XSAnnotationImpl annotation = traverseAnnotationDecl(content, contentAttrs, false, schemaDoc);
231             if (annotation != null ) {
232                 if(annotations == null) {
233                     annotations = new XSAnnotationImpl [] {annotation};
234                 }
235                 else {
236                     XSAnnotationImpl [] tempArray = new XSAnnotationImpl[2];
237                     tempArray[0] = annotations[0];
238                     annotations = tempArray;
239                     annotations[1] = annotation;
240                 }
241             }
242             content = DOMUtil.getNextSiblingElement(content);
243         }
244         else {
245             String JavaDoc text = DOMUtil.getSyntheticAnnotation(child);
246             if (text != null) {
247                 XSAnnotationImpl annotation = traverseSyntheticAnnotation(child, text, contentAttrs, false, schemaDoc);
248                 if (annotations == null) {
249                     annotations = new XSAnnotationImpl [] {annotation};
250                 }
251                 else {
252                     XSAnnotationImpl [] tempArray = new XSAnnotationImpl[2];
253                     tempArray[0] = annotations[0];
254                     annotations = tempArray;
255                     annotations[1] = annotation;
256                 }
257             }
258         }
259         // get base type from "base" attribute
260
XSSimpleType baseValidator = null;
261         if ((restriction || list) && baseTypeName != null) {
262             baseValidator = findDTValidator(child, name, baseTypeName, refType, schemaDoc);
263             // if its the built-in type, return null from here
264
if (baseValidator == null && fIsBuiltIn) {
265                 fIsBuiltIn = false;
266                 return null;
267             }
268         }
269         // get types from "memberTypes" attribute
270
Vector JavaDoc dTValidators = null;
271         XSSimpleType dv = null;
272         XSObjectList dvs;
273         if (union && memberTypes != null && memberTypes.size() > 0) {
274             int size = memberTypes.size();
275             dTValidators = new Vector JavaDoc(size, 2);
276             // for each qname in the list
277
for (int i = 0; i < size; i++) {
278                 // get the type decl
279
dv = findDTValidator(child, name, (QName)memberTypes.elementAt(i),
280                         XSConstants.DERIVATION_UNION, schemaDoc);
281                 if (dv != null) {
282                     // if it's a union, expand it
283
if (dv.getVariety() == XSSimpleType.VARIETY_UNION) {
284                         dvs = dv.getMemberTypes();
285                         for (int j = 0; j < dvs.getLength(); j++)
286                             dTValidators.addElement(dvs.item(j));
287                     } else {
288                         dTValidators.addElement(dv);
289                     }
290                 }
291             }
292         }
293         // when there is an error finding the base type of a restriction
294
// we use anySimpleType as the base, then we should skip the facets,
295
// because anySimpleType doesn't recognize any facet.
296
boolean skipFacets = false;
297         // check if there is a child "simpleType"
298
if (content != null && DOMUtil.getLocalName(content).equals(SchemaSymbols.ELT_SIMPLETYPE)) {
299             if (restriction || list) {
300                 // it's an error for both "base" and "simpleType" to appear
301
if (baseTypeName != null) {
302                     reportSchemaError(list ? "src-simple-type.3.a" : "src-simple-type.2.a", null, content);
303                 }
304                 else {
305                     // traver this child to get the base type
306
baseValidator = traverseLocal(content, schemaDoc, grammar);
307                 }
308                 // get the next element
309
content = DOMUtil.getNextSiblingElement(content);
310             }
311             else if (union) {
312                 if (dTValidators == null) {
313                     dTValidators = new Vector JavaDoc(2, 2);
314                 }
315                 do {
316                     // traver this child to get the member type
317
dv = traverseLocal(content, schemaDoc, grammar);
318                     if (dv != null) {
319                         // if it's a union, expand it
320
if (dv.getVariety() == XSSimpleType.VARIETY_UNION) {
321                             dvs = dv.getMemberTypes();
322                             for (int j = 0; j < dvs.getLength(); j++)
323                                 dTValidators.addElement(dvs.item(j));
324                         } else {
325                             dTValidators.addElement(dv);
326                         }
327                     }
328                     // get the next element
329
content = DOMUtil.getNextSiblingElement(content);
330                 } while (content != null && DOMUtil.getLocalName(content).equals(SchemaSymbols.ELT_SIMPLETYPE));
331             }
332         }
333         else if ((restriction || list) && baseTypeName == null) {
334             // it's an error if neither "base" nor "simpleType" appears
335
reportSchemaError(list ? "src-simple-type.3.b" : "src-simple-type.2.b", null, child);
336             // base can't be found, skip the facets.
337
skipFacets = true;
338             baseValidator = SchemaGrammar.fAnySimpleType;
339         }
340         else if (union && (memberTypes == null || memberTypes.size() == 0)) {
341             // it's an error if "memberTypes" is empty and no "simpleType" appears
342
reportSchemaError("src-union-memberTypes-or-simpleTypes", null, child);
343             dTValidators = new Vector JavaDoc(1);
344             dTValidators.addElement(SchemaGrammar.fAnySimpleType);
345         }
346         // error finding "base" or error traversing "simpleType".
347
// don't need to report an error, since some error has been reported.
348
if ((restriction || list) && baseValidator == null) {
349             baseValidator = SchemaGrammar.fAnySimpleType;
350         }
351         // error finding "memberTypes" or error traversing "simpleType".
352
// don't need to report an error, since some error has been reported.
353
if (union && (dTValidators == null || dTValidators.size() == 0)) {
354             dTValidators = new Vector JavaDoc(1);
355             dTValidators.addElement(SchemaGrammar.fAnySimpleType);
356         }
357         // item type of list types can't have list content
358
if (list && isListDatatype(baseValidator)) {
359             reportSchemaError("cos-st-restricts.2.1", new Object JavaDoc[]{name, baseValidator.getName()}, child);
360         }
361         // create the simple type based on the "base" type
362
XSSimpleType newDecl = null;
363         if (restriction) {
364             newDecl = schemaFactory.createTypeRestriction(name, schemaDoc.fTargetNamespace, (short)finalProperty, baseValidator,
365                     annotations == null? null : new XSObjectListImpl(annotations, annotations.length));
366         }
367         else if (list) {
368             newDecl = schemaFactory.createTypeList(name, schemaDoc.fTargetNamespace, (short)finalProperty, baseValidator,
369                     annotations == null? null : new XSObjectListImpl(annotations, annotations.length));
370         }
371         else if (union) {
372             XSSimpleType[] memberDecls = new XSSimpleType[dTValidators.size()];
373             for (int i = 0; i < dTValidators.size(); i++)
374                 memberDecls[i] = (XSSimpleType)dTValidators.elementAt(i);
375             newDecl = schemaFactory.createTypeUnion(name, schemaDoc.fTargetNamespace, (short)finalProperty, memberDecls,
376                     annotations == null? null : new XSObjectListImpl(annotations, annotations.length));
377         }
378         // now traverse facets, if it's derived by restriction
379
if (restriction && content != null) {
380             FacetInfo fi = traverseFacets(content, baseValidator, schemaDoc);
381             content = fi.nodeAfterFacets;
382             
383             if (!skipFacets) {
384                 try {
385                     fValidationState.setNamespaceSupport(schemaDoc.fNamespaceSupport);
386                     newDecl.applyFacets(fi.facetdata, fi.fPresentFacets, fi.fFixedFacets, fValidationState);
387                 } catch (InvalidDatatypeFacetException ex) {
388                     reportSchemaError(ex.getKey(), ex.getArgs(), child);
389                 }
390             }
391         }
392         // now element should appear after this point
393
if (content != null) {
394             if (restriction) {
395                 reportSchemaError("s4s-elt-must-match.1", new Object JavaDoc[]{SchemaSymbols.ELT_RESTRICTION, "(annotation?, (simpleType?, (minExclusive | minInclusive | maxExclusive | maxInclusive | totalDigits | fractionDigits | length | minLength | maxLength | enumeration | whiteSpace | pattern)*))", DOMUtil.getLocalName(content)}, content);
396             }
397             else if (list) {
398                 reportSchemaError("s4s-elt-must-match.1", new Object JavaDoc[]{SchemaSymbols.ELT_LIST, "(annotation?, (simpleType?))", DOMUtil.getLocalName(content)}, content);
399             }
400             else if (union) {
401                 reportSchemaError("s4s-elt-must-match.1", new Object JavaDoc[]{SchemaSymbols.ELT_UNION, "(annotation?, (simpleType*))", DOMUtil.getLocalName(content)}, content);
402             }
403         }
404         fAttrChecker.returnAttrArray(contentAttrs, schemaDoc);
405         // return the new type
406
return newDecl;
407     }
408     
409     //@param: elm - top element
410
//@param: baseTypeStr - type (base/itemType/memberTypes)
411
//@param: baseRefContext: whether the caller is using this type as a base for restriction, union or list
412
//return XSSimpleType available for the baseTypeStr, null if not found or disallowed.
413
// also throws an error if the base type won't allow itself to be used in this context.
414
// REVISIT: can this code be re-used?
415
private XSSimpleType findDTValidator(Element JavaDoc elm, String JavaDoc refName,
416             QName baseTypeStr, short baseRefContext,
417             XSDocumentInfo schemaDoc) {
418         if (baseTypeStr == null)
419             return null;
420         
421         XSTypeDefinition baseType = (XSTypeDefinition)fSchemaHandler.getGlobalDecl(schemaDoc, XSDHandler.TYPEDECL_TYPE, baseTypeStr, elm);
422         if (baseType != null) {
423             // if it's a complex type, or if its restriction of anySimpleType
424
if (baseType.getTypeCategory() != XSTypeDefinition.SIMPLE_TYPE ||
425                     baseType == SchemaGrammar.fAnySimpleType &&
426                     baseRefContext == XSConstants.DERIVATION_RESTRICTION) {
427                 // if the base type is anySimpleType and the current type is
428
// a S4S built-in type, return null. (not an error).
429
if (baseType == SchemaGrammar.fAnySimpleType &&
430                         checkBuiltIn(refName, schemaDoc.fTargetNamespace)) {
431                     return null;
432                 }
433                 reportSchemaError("cos-st-restricts.1.1", new Object JavaDoc[]{baseTypeStr.rawname, refName}, elm);
434                 return SchemaGrammar.fAnySimpleType;
435             }
436             if ((baseType.getFinal() & baseRefContext) != 0) {
437                 if (baseRefContext == XSConstants.DERIVATION_RESTRICTION) {
438                     reportSchemaError("st-props-correct.3", new Object JavaDoc[]{refName, baseTypeStr.rawname}, elm);
439                 }
440                 else if (baseRefContext == XSConstants.DERIVATION_LIST) {
441                     reportSchemaError("cos-st-restricts.2.3.1.1", new Object JavaDoc[]{baseTypeStr.rawname, refName}, elm);
442                 }
443                 else if (baseRefContext == XSConstants.DERIVATION_UNION) {
444                     reportSchemaError("cos-st-restricts.3.3.1.1", new Object JavaDoc[]{baseTypeStr.rawname, refName}, elm);
445                 }
446             }
447         }
448         
449         return (XSSimpleType)baseType;
450     }
451     
452     // check whethe the type denoted by the name and namespace is a S4S
453
// built-in type. update fIsBuiltIn at the same time.
454
private final boolean checkBuiltIn(String JavaDoc name, String JavaDoc namespace) {
455         if (namespace != SchemaSymbols.URI_SCHEMAFORSCHEMA)
456             return false;
457         if (SchemaGrammar.SG_SchemaNS.getGlobalTypeDecl(name) != null)
458             fIsBuiltIn = true;
459         return fIsBuiltIn;
460     }
461     
462     // find if a datatype validator is a list or has list datatype member.
463
private boolean isListDatatype(XSSimpleType validator) {
464         if (validator.getVariety() == XSSimpleType.VARIETY_LIST)
465             return true;
466         
467         if (validator.getVariety() == XSSimpleType.VARIETY_UNION) {
468             XSObjectList temp = validator.getMemberTypes();
469             for (int i = 0; i < temp.getLength(); i++) {
470                 if (((XSSimpleType)temp.item(i)).getVariety() == XSSimpleType.VARIETY_LIST) {
471                     return true;
472                 }
473             }
474         }
475         
476         return false;
477     }//isListDatatype(XSSimpleTypeDecl):boolean
478

479     private XSSimpleType errorType(String JavaDoc name, String JavaDoc namespace, short refType) {
480         switch (refType) {
481         case XSConstants.DERIVATION_RESTRICTION:
482             return schemaFactory.createTypeRestriction(name, namespace, (short)0,
483                     SchemaGrammar.fAnySimpleType, null);
484         case XSConstants.DERIVATION_LIST:
485             return schemaFactory.createTypeList(name, namespace, (short)0,
486                     SchemaGrammar.fAnySimpleType, null);
487         case XSConstants.DERIVATION_UNION:
488             return schemaFactory.createTypeUnion(name, namespace, (short)0,
489                     new XSSimpleType[]{SchemaGrammar.fAnySimpleType}, null);
490         }
491         
492         return null;
493     }
494     
495 }//class XSDSimpleTypeTraverser
496
Popular Tags