View Javadoc
1   /**
2    * Redistribution and use of this software and associated documentation ("Software"), with or
3    * without modification, are permitted provided that the following conditions are met:
4    *
5    * 1. Redistributions of source code must retain copyright statements and notices. Redistributions
6    * must also contain a copy of this document.
7    *
8    * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
9    * conditions and the following disclaimer in the documentation and/or other materials provided with
10   * the distribution.
11   *
12   * 3. The name "Exolab" must not be used to endorse or promote products derived from this Software
13   * without prior written permission of Intalio, Inc. For written permission, please contact
14   * info@exolab.org.
15   *
16   * 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in
17   * their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of
18   * Intalio, Inc.
19   *
20   * 5. Due credit should be given to the Exolab Project (http://www.exolab.org/).
21   *
22   * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR
23   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS
25   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
29   * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30   *
31   * Copyright 2000-2002 (C) Intalio Inc. All Rights Reserved.
32   *
33   * $Id$
34   */
35  
36  package org.exolab.castor.xml.schema.reader;
37  
38  // -- imported classes and packages
39  import org.exolab.castor.xml.AttributeSet;
40  import org.exolab.castor.xml.Namespaces;
41  import org.exolab.castor.xml.XMLException;
42  import org.exolab.castor.xml.schema.Annotation;
43  import org.exolab.castor.xml.schema.AttributeDecl;
44  import org.exolab.castor.xml.schema.AttributeGroupReference;
45  import org.exolab.castor.xml.schema.ComplexType;
46  import org.exolab.castor.xml.schema.Group;
47  import org.exolab.castor.xml.schema.ModelGroup;
48  import org.exolab.castor.xml.schema.Schema;
49  import org.exolab.castor.xml.schema.SchemaContext;
50  import org.exolab.castor.xml.schema.SchemaException;
51  import org.exolab.castor.xml.schema.SchemaNames;
52  import org.exolab.castor.xml.schema.SimpleContent;
53  import org.exolab.castor.xml.schema.SimpleType;
54  import org.exolab.castor.xml.schema.Wildcard;
55  import org.exolab.castor.xml.schema.XMLType;
56  
57  /**
58   * A class for Unmarshalling extension elements
59   * 
60   * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
61   * @version $Revision$ $Date: 2005-12-13 14:58:48 -0700 (Tue, 13 Dec 2005) $
62   **/
63  public class ExtensionUnmarshaller extends ComponentReader {
64  
65  
66    // --------------------/
67    // - Member Variables -/
68    // --------------------/
69  
70    /**
71     * The current ComponentReader
72     **/
73    private ComponentReader unmarshaller;
74  
75    /**
76     * The current branch depth
77     **/
78    private int depth = 0;
79  
80    /**
81     * The Attribute reference for the Attribute we are constructing
82     **/
83    private ComplexType _complexType = null;
84    private Schema _schema = null;
85  
86    private boolean foundAnnotation = false;
87    private boolean foundAttributes = false;
88    private boolean foundModelGroup = false;
89  
90  
91    // ----------------/
92    // - Constructors -/
93    // ----------------/
94  
95    /**
96     * Creates a new ExtensionUnmarshaller.
97     * 
98     * @param schemaContext the {@link SchemaContext} to get some configuration settings from
99     * @param complexType the ComplexType being unmarshalled
100    * @param atts the AttributeList
101    **/
102   public ExtensionUnmarshaller(final SchemaContext schemaContext, final ComplexType complexType,
103       final AttributeSet atts) throws XMLException {
104     super(schemaContext);
105 
106     _complexType = complexType;
107     _schema = complexType.getSchema();
108 
109     _complexType.setDerivationMethod(SchemaNames.EXTENSION);
110 
111     // -- base
112     String base = atts.getValue(SchemaNames.BASE_ATTR);
113     if ((base != null) && (base.length() > 0)) {
114 
115       XMLType baseType = _schema.getType(base);
116       if (baseType == null) {
117         _complexType.setBase(base); // the base type has not been read
118         if (_complexType.isSimpleContent()) {
119           _complexType.setContentType(new SimpleContent(_schema, base));
120         }
121       } else {
122         // --we cannot extend a simpleType in <complexContent>
123         if ((baseType.isSimpleType()) && (_complexType.isComplexContent())) {
124           String err = "In a 'complexContent', the base attribute " + "must be a complexType but "
125               + base + " is a simpleType.\n";
126           error(err);
127         }
128         _complexType.setBase(base);
129         _complexType.setBaseType(baseType);
130         if (_complexType.isSimpleContent()) {
131           // --set the content type
132           if (baseType.isSimpleType()) {
133             SimpleType simpleType = (SimpleType) baseType;
134             _complexType.setContentType(new SimpleContent(simpleType));
135           } else {
136             ComplexType temp = (ComplexType) baseType;
137             SimpleContent simpleContent = (SimpleContent) temp.getContentType();
138             _complexType.setContentType(simpleContent.copy());
139           }
140         }
141 
142       }
143 
144     }
145 
146   } // -- ExtensionUnmarshaller
147 
148   // -----------/
149   // - Methods -/
150   // -----------/
151 
152   /**
153    * Returns the name of the element that this ComponentReader handles
154    * 
155    * @return the name of the element that this ComponentReader handles
156    **/
157   public String elementName() {
158     return SchemaNames.EXTENSION;
159   } // -- elementName
160 
161   /**
162    * Returns the Object created by this ComponentReader
163    * 
164    * @return the Object created by this ComponentReader
165    **/
166   public Object getObject() {
167     return null;
168   } // -- getObject
169 
170   /**
171    * Signals the start of an element with the given name.
172    *
173    * @param name the NCName of the element. It is an error if the name is a QName (ie. contains a
174    *        prefix).
175    * @param namespace the namespace of the element. This may be null. Note: A null namespace is not
176    *        the same as the default namespace unless the default namespace is also null.
177    * @param atts the AttributeSet containing the attributes associated with the element.
178    * @param nsDecls the namespace declarations being declared for this element. This may be null.
179    **/
180   public void startElement(String name, String namespace, AttributeSet atts, Namespaces nsDecls)
181       throws XMLException {
182     // -- Do delagation if necessary
183     if (unmarshaller != null) {
184       unmarshaller.startElement(name, namespace, atts, nsDecls);
185       ++depth;
186       return;
187     }
188 
189     // -- <anyAttribute>
190     if (SchemaNames.ANY_ATTRIBUTE.equals(name)) {
191       unmarshaller =
192           new WildcardUnmarshaller(getSchemaContext(), _complexType, _schema, name, atts);
193     }
194 
195     // -- attribute declarations
196     else if (SchemaNames.ATTRIBUTE.equals(name)) {
197       foundAttributes = true;
198       unmarshaller = new AttributeUnmarshaller(getSchemaContext(), _schema, atts);
199     }
200     // -- attribute group declarations
201     else if (SchemaNames.ATTRIBUTE_GROUP.equals(name)) {
202 
203       // -- make sure we have an attribute group
204       // -- reference and not a definition
205 
206       if (atts.getValue(SchemaNames.REF_ATTR) == null) {
207         String err =
208             "A complexType may contain referring " + "attribute groups, but not defining ones.";
209         error(err);
210       }
211 
212       foundAttributes = true;
213       unmarshaller = new AttributeGroupUnmarshaller(getSchemaContext(), _schema, atts);
214     }
215     // --<group>
216     else if (name.equals(SchemaNames.GROUP)) {
217       if (foundAttributes)
218         error("'" + name + "' must appear before any attribute "
219             + "definitions when a child of 'complexType'.");
220       if (foundModelGroup)
221         error("'" + name + "' cannot appear as a child of 'complexType' "
222             + "if another 'all', 'sequence', 'choice' or " + "'group' also exists.");
223 
224       foundModelGroup = true;
225       unmarshaller = new ModelGroupUnmarshaller(getSchemaContext(), _schema, atts);
226     } else if (SchemaNames.isGroupName(name) && (name != SchemaNames.GROUP)) {
227       if (foundAttributes)
228         error("'" + name + "' must appear before attribute "
229             + "definitions in an 'extension' element.");
230 
231       if (foundModelGroup)
232         error("'" + name + "' cannot appear as a child of 'extension' "
233             + "if another 'all', 'sequence', 'choice' or " + "'group' already exists.");
234 
235       if (_complexType.isSimpleContent())
236         error("'" + name + "' may not appear in a 'extension' of " + "'simpleContent'.");
237 
238       foundModelGroup = true;
239       unmarshaller = new GroupUnmarshaller(getSchemaContext(), _schema, name, atts);
240     }
241     // -- element declarations
242     else if (SchemaNames.ANY_ATTRIBUTE.equals(name)) {
243       // -- not yet supported....
244       error("anyAttribute is not yet supported.");
245     } else if (name.equals(SchemaNames.ANNOTATION)) {
246       if (foundAttributes || foundModelGroup)
247         error("An annotation must appear as the first child of an " + "'extension' element.");
248 
249       if (foundAnnotation)
250         error("Only one (1) annotation may appear as the child of " + "an 'extension' element.");
251 
252       foundAnnotation = true;
253       unmarshaller = new AnnotationUnmarshaller(getSchemaContext(), atts);
254     } else
255       illegalElement(name);
256 
257   } // -- startElement
258 
259   /**
260    * Signals to end of the element with the given name.
261    *
262    * @param name the NCName of the element. It is an error if the name is a QName (ie. contains a
263    *        prefix).
264    * @param namespace the namespace of the element.
265    **/
266   public void endElement(String name, String namespace) throws XMLException {
267 
268     // -- Do delagation if necessary
269     if ((unmarshaller != null) && (depth > 0)) {
270       unmarshaller.endElement(name, namespace);
271       --depth;
272       return;
273     }
274 
275     // -- have unmarshaller perform any necessary clean up
276     unmarshaller.finish();
277 
278     // -- <anyAttribute>
279     if (SchemaNames.ANY_ATTRIBUTE.equals(name)) {
280       Wildcard wildcard = ((WildcardUnmarshaller) unmarshaller).getWildcard();
281       try {
282         _complexType.setAnyAttribute(wildcard);
283       } catch (SchemaException e) {
284         throw new IllegalArgumentException(e.getMessage());
285       }
286     }
287 
288     // -- attribute declarations
289     else if (SchemaNames.ATTRIBUTE.equals(name)) {
290       AttributeDecl attrDecl = ((AttributeUnmarshaller) unmarshaller).getAttribute();
291 
292       _complexType.addAttributeDecl(attrDecl);
293     }
294     // -- attribute groups
295     else if (SchemaNames.ATTRIBUTE_GROUP.equals(name)) {
296       AttributeGroupReference attrGroupRef = (AttributeGroupReference) unmarshaller.getObject();
297       _complexType.addAttributeGroupReference(attrGroupRef);
298     }
299     // --group
300     else if (name.equals(SchemaNames.GROUP)) {
301       ModelGroup group = ((ModelGroupUnmarshaller) unmarshaller).getGroup();
302       _complexType.addGroup(group);
303     }
304 
305     // -- group declarations (all, choice, sequence)
306     else if ((SchemaNames.isGroupName(name)) && (name != SchemaNames.GROUP)) {
307       Group group = ((GroupUnmarshaller) unmarshaller).getGroup();
308       _complexType.addGroup(group);
309     }
310     // -- annotation
311     else if (SchemaNames.ANNOTATION.equals(name)) {
312       Annotation ann = ((AnnotationUnmarshaller) unmarshaller).getAnnotation();
313       _complexType.addAnnotation(ann);
314     }
315 
316     unmarshaller = null;
317   } // -- endElement
318 
319   public void characters(char[] ch, int start, int length) throws XMLException {
320     // -- Do delagation if necessary
321     if (unmarshaller != null) {
322       unmarshaller.characters(ch, start, length);
323     }
324   } // -- characters
325 
326 } // -- ExtensionUnmarshaller