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 2001-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.Schema;
44  import org.exolab.castor.xml.schema.SchemaContext;
45  import org.exolab.castor.xml.schema.SchemaNames;
46  import org.exolab.castor.xml.schema.SimpleType;
47  import org.exolab.castor.xml.schema.Structure;
48  import org.exolab.castor.xml.schema.XMLType;
49  import org.exolab.castor.xml.schema.simpletypes.ListType;
50  
51  
52  /**
53   * A class for unmarshalling list elements of a simpleType. Thanks to
54   * <a href="mailto:cdchudasama@yahoo.com">Chetan Chudasama</a> for his help.
55   * 
56   * @author <a href="mailto:blandin@intalio.com">Arnaud Blandin</a>
57   * @author <a href="mailto:kvsico@intalio.com">Keith Visco</a>
58   * @version $Revision$
59   **/
60  public class SimpleTypeListUnmarshaller extends ComponentReader {
61  
62  
63    // --------------------/
64    // - Member Variables -/
65    // --------------------/
66  
67    /**
68     * The current ComponentReader
69     **/
70    private ComponentReader unmarshaller;
71  
72    /**
73     * The current branch depth
74     **/
75    private int depth = 0;
76  
77    /**
78     * The simpleType we are unmarshalling
79     **/
80    private ListType _list = null;
81    private Schema _schema = null;
82    private boolean foundAnnotation = false;
83    private boolean foundSimpleType = false;
84    private boolean foundItemType = false;
85  
86  
87    // ----------------/
88    // - Constructors -/
89    // ----------------/
90  
91    /**
92     * Creates a new ListUnmarshaller.
93     * 
94     * @param schemaContext the {@link SchemaContext} to get some configuration settings from
95     * @param atts the AttributeList
96     **/
97    SimpleTypeListUnmarshaller(final SchemaContext schemaContext, final Schema schema,
98        final AttributeSet atts) throws XMLException {
99      super(schemaContext);
100 
101     _schema = schema;
102     _list = new ListType(schema);
103 
104     // -- itemType
105     String itemTypeName = atts.getValue(SchemaNames.ITEM_TYPE_ATTR);
106     if ((itemTypeName != null) && (itemTypeName.length() > 0)) {
107 
108       foundItemType = true;
109       XMLType itemType = _schema.getType(itemTypeName);
110       if (itemType == null) {
111         _list.setItemType(itemTypeName);
112       } else if (itemType.getStructureType() == Structure.COMPLEX_TYPE) {
113         String err = "The item type of a list cannot " + "be a complexType.";
114         throw new IllegalStateException(err);
115       } else
116         _list.setItemType((SimpleType) itemType);
117     }
118 
119     // -- @id
120     _list.setId(atts.getValue(SchemaNames.ID_ATTR));
121 
122   } // -- SimpleTypeListUnmarshaller
123 
124   // -----------/
125   // - Methods -/
126   // -----------/
127 
128   /**
129    * Returns the name of the element that this ComponentReader handles
130    * 
131    * @return the name of the element that this ComponentReader handles
132    **/
133   public String elementName() {
134     return SchemaNames.LIST;
135   } // -- elementName
136 
137   /**
138    * Called to signal an end of unmarshalling. This method should be overridden to perform any
139    * necessary clean up by an unmarshaller
140    **/
141   public void finish() throws XMLException {
142     if ((!foundItemType) && (!foundSimpleType)) {
143       String err = "Missing sub-component of <list>, either use "
144           + " the 'itemType' attribute, or an anonymous simpleType.";
145       error(err);
146     }
147   } // -- finish
148 
149   /**
150    * Returns the Object created by this ComponentReader
151    * 
152    * @return the Object created by this ComponentReader
153    **/
154   public Object getObject() {
155     if ((!foundItemType) && (!foundSimpleType)) {
156       String err = "Missing sub-component of <list>, either use "
157           + " the 'itemType' attribute, or an anonymous simpleType.";
158       throw new IllegalStateException(err);
159     }
160     return _list;
161   } // -- getObject
162 
163   /**
164    * Signals the start of an element with the given name.
165    *
166    * @param name the NCName of the element. It is an error if the name is a QName (ie. contains a
167    *        prefix).
168    * @param namespace the namespace of the element. This may be null. Note: A null namespace is not
169    *        the same as the default namespace unless the default namespace is also null.
170    * @param atts the AttributeSet containing the attributes associated with the element.
171    * @param nsDecls the namespace declarations being declared for this element. This may be null.
172    **/
173   public void startElement(String name, String namespace, AttributeSet atts, Namespaces nsDecls)
174       throws XMLException {
175     // -- Do delagation if necessary
176     if (unmarshaller != null) {
177       unmarshaller.startElement(name, namespace, atts, nsDecls);
178       ++depth;
179       return;
180     }
181 
182 
183     // -- annotation
184     if (name.equals(SchemaNames.ANNOTATION)) {
185 
186       if (foundSimpleType)
187         error("An annotation must appear as the first child " + "of 'list' elements.");
188 
189       if (foundAnnotation)
190         error("Only one (1) annotation may appear as a child of " + "'list' elements.");
191 
192       foundAnnotation = true;
193       unmarshaller = new AnnotationUnmarshaller(getSchemaContext(), atts);
194     } else if (SchemaNames.SIMPLE_TYPE.equals(name)) {
195       if (foundItemType)
196         error("A 'list' element can have either an 'itemType' or " + " 'simpleType'.");
197 
198       if (foundSimpleType)
199         error("Only one (1) 'simpleType' may appear as a child of " + "'list' elements.");
200 
201       foundSimpleType = true;
202       unmarshaller = new SimpleTypeUnmarshaller(getSchemaContext(), _schema, atts);
203 
204     } else
205       illegalElement(name);
206 
207     unmarshaller.setDocumentLocator(getDocumentLocator());
208   } // -- startElement
209 
210   /**
211    * Signals to end of the element with the given name.
212    *
213    * @param name the NCName of the element. It is an error if the name is a QName (ie. contains a
214    *        prefix).
215    * @param namespace the namespace of the element.
216    **/
217   public void endElement(String name, String namespace) throws XMLException {
218 
219     // -- Do delagation if necessary
220     if ((unmarshaller != null) && (depth > 0)) {
221       unmarshaller.endElement(name, namespace);
222       --depth;
223       return;
224     }
225 
226     // -- have unmarshaller perform any necessary clean up
227     unmarshaller.finish();
228 
229     // -- annotation
230     if (SchemaNames.ANNOTATION.equals(name)) {
231       Annotation ann = ((AnnotationUnmarshaller) unmarshaller).getAnnotation();
232       _list.setLocalAnnotation(ann);
233     } else if (SchemaNames.SIMPLE_TYPE.equals(name)) {
234       SimpleType type = (SimpleType) unmarshaller.getObject();
235       _list.setItemType(type);
236     }
237 
238 
239     unmarshaller = null;
240   } // -- endElement
241 
242   public void characters(char[] ch, int start, int length) throws XMLException {
243     // -- Do delagation if necessary
244     if (unmarshaller != null) {
245       unmarshaller.characters(ch, start, length);
246     }
247   } // -- characters
248 
249 } // -- SimpleTypeListUnmarshaller