001: /**
002: * Redistribution and use of this software and associated documentation
003: * ("Software"), with or without modification, are permitted provided
004: * that the following conditions are met:
005: *
006: * 1. Redistributions of source code must retain copyright
007: * statements and notices. Redistributions must also contain a
008: * copy of this document.
009: *
010: * 2. Redistributions in binary form must reproduce the
011: * above copyright notice, this list of conditions and the
012: * following disclaimer in the documentation and/or other
013: * materials provided with the distribution.
014: *
015: * 3. The name "Exolab" must not be used to endorse or promote
016: * products derived from this Software without prior written
017: * permission of Intalio, Inc. For written permission,
018: * please contact info@exolab.org.
019: *
020: * 4. Products derived from this Software may not be called "Exolab"
021: * nor may "Exolab" appear in their names without prior written
022: * permission of Intalio, Inc. Exolab is a registered
023: * trademark of Intalio, Inc.
024: *
025: * 5. Due credit should be given to the Exolab Project
026: * (http://www.exolab.org/).
027: *
028: * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
029: * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
030: * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
031: * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
032: * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
033: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
034: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
035: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
036: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
037: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
038: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
039: * OF THE POSSIBILITY OF SUCH DAMAGE.
040: *
041: * Copyright 2000-2002 (C) Intalio Inc. All Rights Reserved.
042: *
043: * $Id: SimpleContentRestrictionUnmarshaller.java 6231 2006-09-20 10:55:10Z wguttmn $
044: */package org.exolab.castor.xml.schema.reader;
045:
046: import org.exolab.castor.xml.AttributeSet;
047: import org.exolab.castor.xml.Namespaces;
048: import org.exolab.castor.xml.XMLException;
049: import org.exolab.castor.xml.schema.Annotation;
050: import org.exolab.castor.xml.schema.AttributeDecl;
051: import org.exolab.castor.xml.schema.AttributeGroupReference;
052: import org.exolab.castor.xml.schema.ComplexType;
053: import org.exolab.castor.xml.schema.ContentType;
054: import org.exolab.castor.xml.schema.Facet;
055: import org.exolab.castor.xml.schema.Resolver;
056: import org.exolab.castor.xml.schema.Schema;
057: import org.exolab.castor.xml.schema.SchemaException;
058: import org.exolab.castor.xml.schema.SchemaNames;
059: import org.exolab.castor.xml.schema.SimpleContent;
060: import org.exolab.castor.xml.schema.SimpleType;
061: import org.exolab.castor.xml.schema.Wildcard;
062: import org.exolab.castor.xml.schema.XMLType;
063:
064: /**
065: * A class for unmarshalling restriction elements of a simpleContent
066: * @author <a href="mailto:blandin@intalio.com">Arnaud Blandin</a>
067: * @version $Revision: 6231 $ $Date: 2006-04-14 04:14:43 -0600 (Fri, 14 Apr 2006) $
068: * TODO: support the correct restriction for facets and attributes
069: **/
070: public class SimpleContentRestrictionUnmarshaller extends
071: ComponentReader {
072:
073: //--------------------/
074: //- Member Variables -/
075: //--------------------/
076:
077: /**
078: * The current ComponentReader
079: **/
080: private ComponentReader unmarshaller;
081:
082: /**
083: * The current branch depth
084: **/
085: private int depth = 0;
086:
087: /**
088: * The complexType we are unmarshalling
089: **/
090: private ComplexType _complexType = null;
091:
092: private Schema _schema = null;
093: private String _id = null;
094: private boolean foundAnnotation = false;
095: private boolean foundSimpleType = false;
096: private boolean foundFacets = false;
097: private boolean foundAttribute = false;
098: private boolean foundAttributeGroup = false;
099:
100: /**
101: * The content type
102: **/
103: private SimpleTypeDefinition _simpleTypeDef = null;
104:
105: //----------------/
106: //- Constructors -/
107: //----------------/
108: /**
109: * Creates a new RestrictionUnmarshaller
110: * @param complexType the complexType being unmarshalled
111: * @param atts the AttributeList
112: */
113: public SimpleContentRestrictionUnmarshaller(
114: ComplexType complexType, AttributeSet atts,
115: Resolver resolver) {
116:
117: super ();
118: setResolver(resolver);
119: _complexType = complexType;
120: _complexType.setDerivationMethod(SchemaNames.RESTRICTION);
121: _complexType.setRestriction(true);
122: _schema = complexType.getSchema();
123: _id = atts.getValue(SchemaNames.ID_ATTR);
124:
125: //-- base
126: String base = atts.getValue(SchemaNames.BASE_ATTR);
127:
128: if ((base != null) && (base.length() > 0)) {
129:
130: XMLType baseType = _schema.getType(base);
131: if (baseType == null) {
132: _complexType.setBase(base);
133: _complexType.setContentType(new SimpleContent(_schema,
134: base));
135: } else if (baseType.isSimpleType()) {
136: String err = "complexType: ";
137: String name = _complexType.getName();
138: if (name != null) {
139: err += name;
140: } else {
141: err += "#anonymous-complexType#";
142: }
143:
144: err += "A complex type cannot be a restriction"
145: + " of a simpleType:";
146: err += baseType.getName();
147: throw new IllegalStateException(err);
148: }
149: //we are now sure that the base is a ComplexType
150: //but is the base of this complexType a simpleType? (see 4.3.3->simpleContent->content type)
151: else {
152: ComplexType temp = (ComplexType) baseType;
153:
154: if (!temp.isSimpleContent()) {
155: // UPO - base type may have complex content if
156: // 1. content model is emptiable
157: // 2. it has mixed content
158: // See bug report http://jira.codehaus.org/browse/CASTOR-1238
159: if ((temp.getContentType().getType() == ContentType.MIXED)
160: && temp.isEmptiable()) {
161: // OK
162: } else {
163: String err = "complexType: ";
164: String name = _complexType.getName();
165: if (name != null) {
166: err += name;
167: } else {
168: err += "#anonymous-complexType#";
169: }
170:
171: err += ": In a simpleContent when using restriction the base type"
172: + " must be a complexType with a simple content model or it must"
173: + " be a complex content model which is mixed and emptiable.";
174: throw new IllegalStateException(err);
175: }
176: } else {
177: //retrieve the base type of this complexType
178: //the base type is the complexType but we have to
179: //work with the simple type of the content type.
180: SimpleContent contentType = (SimpleContent) temp
181: .getContentType();
182: _complexType.setBaseType(temp);
183: _complexType.setBase(temp.getName());
184: _simpleTypeDef = new SimpleTypeDefinition(_schema,
185: temp.getName(), _id);
186: SimpleType simpleType = contentType.getSimpleType();
187: if (simpleType != null) {
188: _simpleTypeDef.setBaseType(simpleType);
189: } else {
190: _simpleTypeDef.setBaseTypeName(contentType
191: .getTypeName());
192: }
193: }
194: }
195: }
196:
197: } //-- SimpleContentRestrictionUnmarshaller
198:
199: //-----------/
200: //- Methods -/
201: //-----------/
202:
203: /**
204: * Returns the name of the element that this ComponentReader
205: * handles
206: * @return the name of the element that this ComponentReader
207: * handles
208: **/
209: public String elementName() {
210: return SchemaNames.RESTRICTION;
211: } //-- elementName
212:
213: /**
214: * Returns the Object created by this ComponentReader
215: * @return the Object created by this ComponentReader
216: **/
217: public Object getObject() {
218: return null;
219: } //-- getObject
220:
221: /**
222: * Signals the start of an element with the given name.
223: *
224: * @param name the NCName of the element. It is an error
225: * if the name is a QName (ie. contains a prefix).
226: * @param namespace the namespace of the element. This may be null.
227: * Note: A null namespace is not the same as the default namespace unless
228: * the default namespace is also null.
229: * @param atts the AttributeSet containing the attributes associated
230: * with the element.
231: * @param nsDecls the namespace declarations being declared for this
232: * element. This may be null.
233: **/
234: public void startElement(String name, String namespace,
235: AttributeSet atts, Namespaces nsDecls) throws XMLException {
236: //-- Do delagation if necessary
237: if (unmarshaller != null) {
238: unmarshaller.startElement(name, namespace, atts, nsDecls);
239: ++depth;
240: return;
241: }
242:
243: //-- annotation
244: if (name.equals(SchemaNames.ANNOTATION)) {
245:
246: if (foundFacets || foundSimpleType || foundAttribute
247: || foundAttributeGroup)
248: error("An annotation must appear as the first child "
249: + "of 'restriction' elements.");
250:
251: if (foundAnnotation)
252: error("Only one (1) annotation may appear as a child of "
253: + "'restriction' elements.");
254:
255: foundAnnotation = true;
256: unmarshaller = new AnnotationUnmarshaller(atts);
257: }
258:
259: else if (SchemaNames.SIMPLE_TYPE.equals(name)) {
260: if (foundSimpleType)
261: error("Only one (1) 'simpleType' may appear as a child of "
262: + "'restriction' elements.");
263:
264: if (foundFacets)
265: error("A 'simpleType', as a child of 'restriction' "
266: + "elements, must appear before any facets.");
267:
268: if (foundAttribute || foundAttributeGroup)
269: error("A 'simpleType', as a child of 'restriction' "
270: + "elements, must appear before any attribute elements.");
271:
272: foundSimpleType = true;
273: unmarshaller = new SimpleTypeUnmarshaller(_schema, atts);
274:
275: } else if (FacetUnmarshaller.isFacet(name)) {
276: foundFacets = true;
277: if (foundAttribute || foundAttributeGroup)
278: error("A 'facet', as a child of 'restriction' "
279: + "elements, must appear before any attribute elements.");
280:
281: unmarshaller = new FacetUnmarshaller(name, atts);
282: if (_simpleTypeDef == null) {
283: SimpleContent content = (SimpleContent) _complexType
284: .getContentType();
285: _simpleTypeDef = new SimpleTypeDefinition(_schema,
286: content.getTypeName(), _id);
287: }
288: } else if (SchemaNames.ATTRIBUTE.equals(name)) {
289: foundAttribute = true;
290: unmarshaller = new AttributeUnmarshaller(_schema, atts,
291: getResolver());
292: } else if (SchemaNames.ATTRIBUTE_GROUP.equals(name)) {
293:
294: //--In a complexType we only reference attribute group
295: if (atts.getValue(SchemaNames.REF_ATTR) == null) {
296: error("A 'complexType' may contain referring "
297: + "attributeGroups, but not defining ones.");
298: }
299: foundAttributeGroup = true;
300: unmarshaller = new AttributeGroupUnmarshaller(_schema, atts);
301: }
302: //-- <anyAttribute>
303: else if (SchemaNames.ANY_ATTRIBUTE.equals(name)) {
304: unmarshaller = new WildcardUnmarshaller(_complexType,
305: _schema, name, atts, getResolver());
306: }
307:
308: else
309: illegalElement(name);
310:
311: unmarshaller.setDocumentLocator(getDocumentLocator());
312: } //-- startElement
313:
314: /**
315: * Signals to end of the element with the given name.
316: *
317: * @param name the NCName of the element. It is an error
318: * if the name is a QName (ie. contains a prefix).
319: * @param namespace the namespace of the element.
320: **/
321: public void endElement(String name, String namespace)
322: throws XMLException {
323:
324: //-- Do delagation if necessary
325: if ((unmarshaller != null) && (depth > 0)) {
326: unmarshaller.endElement(name, namespace);
327: --depth;
328: return;
329: }
330:
331: //-- have unmarshaller perform any necessary clean up
332: unmarshaller.finish();
333:
334: //-- annotation
335: if (SchemaNames.ANNOTATION.equals(name)) {
336: Annotation ann = ((AnnotationUnmarshaller) unmarshaller)
337: .getAnnotation();
338: _complexType.addAnnotation(ann);
339: }
340: //-- <anyAttribute>
341: if (SchemaNames.ANY_ATTRIBUTE.equals(name)) {
342: Wildcard wildcard = ((WildcardUnmarshaller) unmarshaller)
343: .getWildcard();
344: try {
345: _complexType.setAnyAttribute(wildcard);
346: } catch (SchemaException e) {
347: throw new IllegalArgumentException(e.getMessage());
348: }
349: }
350: //Note: the attributes are added to the complexType
351: //since a simpleType does not contain attributes at all
352: //-- attribute
353: else if (SchemaNames.ATTRIBUTE.equals(name)) {
354: AttributeDecl attrDecl = ((AttributeUnmarshaller) unmarshaller)
355: .getAttribute();
356:
357: /* TODO add the validation code later*/
358:
359: /*ComplexType baseType = (ComplexType)_complexType.getBaseType();
360: if ( (baseType.getAttributeDecls() == null) ||
361: (baseType.getAttributeDecl(attrDecl.getName()) == null) )
362: error("The restricted attribute must be present in the"
363: +" base type.");
364: baseType = null;*/
365:
366: _complexType.addAttributeDecl(attrDecl);
367: }
368: //-- attribute groups
369: else if (SchemaNames.ATTRIBUTE_GROUP.equals(name)) {
370: AttributeGroupReference attrGroupRef = (AttributeGroupReference) unmarshaller
371: .getObject();
372: _complexType.addAttributeGroupReference(attrGroupRef);
373: }
374: //-- simpleType
375: else if (SchemaNames.SIMPLE_TYPE.equals(name)) {
376: SimpleType type = (SimpleType) unmarshaller.getObject();
377: _complexType.setContentType(new SimpleContent(type));
378: }
379: //--facet
380: else {
381: _simpleTypeDef.addFacet((Facet) unmarshaller.getObject());
382: foundFacets = true;
383: //set the flag in order to create the new base in
384: //the finish() method
385: }
386:
387: unmarshaller = null;
388: } //-- endElement
389:
390: public void characters(char[] ch, int start, int length)
391: throws XMLException {
392: //-- Do delagation if necessary
393: if (unmarshaller != null) {
394: unmarshaller.characters(ch, start, length);
395: }
396: } //-- characters
397:
398: /**
399: * Terminates the process of this restriction by
400: * setting a proper base.
401: * We set a new base if the base simple type has been restricted
402: * by the use of facets since all other restrictions may concern the
403: * complexType character of the type (i.e attribute for instance is
404: * only related to a complexType...)
405: */
406: public void finish() {
407:
408: if (_simpleTypeDef != null) {
409: SimpleType baseType = _simpleTypeDef.createSimpleType();
410: _complexType.setContentType(new SimpleContent(baseType));
411: }
412: //the restriction was properly handle
413: //we can set the flag
414: _complexType.setRestriction(true);
415: }
416: } //-- SimpleContentRestrictionUnmarshaller
|