View Javadoc
1   /**
2    * Redistribution and use of this software and associated documentation
3    * ("Software"), with or without modification, are permitted provided
4    * that the following conditions are met:
5    *
6    * 1. Redistributions of source code must retain copyright
7    *    statements and notices.  Redistributions must also contain a
8    *    copy of this document.
9    *
10   * 2. Redistributions in binary form must reproduce the
11   *    above copyright notice, this list of conditions and the
12   *    following disclaimer in the documentation and/or other
13   *    materials provided with the distribution.
14   *
15   * 3. The name "Exolab" must not be used to endorse or promote
16   *    products derived from this Software without prior written
17   *    permission of Intalio, Inc.  For written permission,
18   *    please contact info@exolab.org.
19   *
20   * 4. Products derived from this Software may not be called "Exolab"
21   *    nor may "Exolab" appear in their names without prior written
22   *    permission of Intalio, Inc. Exolab is a registered
23   *    trademark of Intalio, Inc.
24   *
25   * 5. Due credit should be given to the Exolab Project
26   *    (http://www.exolab.org/).
27   *
28   * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
29   * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
32   * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39   * OF THE POSSIBILITY OF SUCH DAMAGE.
40   *
41   * Copyright 2001-2002 (C) Intalio Inc. All Rights Reserved.
42   *
43   * $Id$
44   */
45  
46  package org.exolab.castor.xml.schema.reader;
47  
48  //-- imported classes and packages
49  import java.util.StringTokenizer;
50  
51  import org.exolab.castor.xml.AttributeSet;
52  import org.exolab.castor.xml.Namespaces;
53  import org.exolab.castor.xml.XMLException;
54  import org.exolab.castor.xml.schema.Annotation;
55  import org.exolab.castor.xml.schema.Schema;
56  import org.exolab.castor.xml.schema.SchemaContext;
57  import org.exolab.castor.xml.schema.SchemaNames;
58  import org.exolab.castor.xml.schema.SimpleType;
59  import org.exolab.castor.xml.schema.Union;
60  
61  /**
62   * A class for Unmarshalling XML Schema Union types
63   *
64   * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
65   * @version $Revision$ $Date: 2003-03-03 00:05:44 -0700 (Mon, 03 Mar 2003) $
66  **/
67  public class UnionUnmarshaller extends ComponentReader {
68  
69        //--------------------/
70       //- Member Variables -/
71      //--------------------/
72  
73      /**
74       * The current ComponentReader
75      **/
76      private ComponentReader _unmarshaller;
77  
78      /**
79       * The current branch depth
80      **/
81      private int _depth = 0;
82  
83      /**
84       * The Union we are unmarshalling
85      **/
86      private Union _union = null;
87  
88      /**
89       * The parent Schema for the Union
90      **/
91      private Schema _schema = null;
92      
93      private boolean _foundAnnotation   = false;
94      private boolean _foundSimpleType   = false;
95      
96        //----------------/
97       //- Constructors -/
98      //----------------/
99  
100     /**
101      * Creates a new IdentityConstraintUnmarshaller
102      *
103      * @param schemaContext the {@link SchemaContext} to get some configuration settings from
104      * @param atts the AttributeList
105     **/
106     public UnionUnmarshaller(
107             final SchemaContext schemaContext,
108             final Schema schema,
109             final AttributeSet atts)
110     throws XMLException {
111         super(schemaContext);
112         
113         if (schema == null) {
114             String err = "'schema' must not be null.";
115             throw new IllegalStateException(err);
116         }
117         _schema = schema;
118         
119         _union = new Union(_schema);
120         _union.setId(atts.getValue(SchemaNames.ID_ATTR));
121         
122         String memberTypes = atts.getValue(SchemaNames.MEMBER_TYPES_ATTR);
123         processMemberTypes(memberTypes);
124         
125     } //-- UnionUnmarshaller
126 
127       //-----------/
128      //- Methods -/
129     //-----------/
130 
131     /**
132      * Returns the name of the element that this ComponentReader
133      * handles
134      * @return the name of the element that this ComponentReader
135      * handles
136     **/
137     public String elementName() {
138         return SchemaNames.UNION;
139     } //-- elementName
140 
141     /**
142      * Returns the Object created by this ComponentReader
143      *
144      * @return the Object created by this ComponentReader
145     **/
146     public Object getObject() {
147         return _union;
148     } //-- getObject
149 
150     public void finish() 
151         throws XMLException 
152     {
153         //-- do nothing
154     } //-- finish
155 
156     /**
157      * Signals the start of an element with the given name.
158      *
159      * @param name the NCName of the element. It is an error
160      * if the name is a QName (ie. contains a prefix).
161      * @param namespace the namespace of the element. This may be null.
162      * Note: A null namespace is not the same as the default namespace unless
163      * the default namespace is also null.
164      * @param atts the AttributeSet containing the attributes associated
165      * with the element.
166      * @param nsDecls the namespace declarations being declared for this 
167      * element. This may be null.
168     **/
169     public void startElement(String name, String namespace, AttributeSet atts,
170         Namespaces nsDecls)
171         throws XMLException
172     {
173         //-- Do delagation if necessary
174         if (_unmarshaller != null) {
175             _unmarshaller.startElement(name, namespace, atts, nsDecls);
176             ++_depth;
177             return;
178         }
179 
180         if (SchemaNames.ANNOTATION.equals(name)) {
181 
182             if (_foundAnnotation)
183                 error("Only one (1) annotation may appear as a child of '" +
184                     elementName() + "'.");
185 
186             if (_foundSimpleType)
187                 error("An annotation may only appear as the first child of '"+
188                     elementName() + "'.");
189 
190             _foundAnnotation = true;
191             _unmarshaller = new AnnotationUnmarshaller(getSchemaContext(), atts);
192         }
193         else if (SchemaNames.SIMPLE_TYPE.equals(name)) {
194             _foundSimpleType = true;
195             _unmarshaller = new SimpleTypeUnmarshaller(getSchemaContext(), _schema, atts);
196         }
197         else illegalElement(name);
198 
199     } //-- startElement
200 
201     /**
202      * Signals to end of the element with the given name.
203      *
204      * @param name the NCName of the element. It is an error
205      * if the name is a QName (ie. contains a prefix).
206      * @param namespace the namespace of the element.
207     **/
208     public void endElement(String name, String namespace)
209         throws XMLException
210     {
211 
212         //-- Do delagation if necessary
213         if ((_unmarshaller != null) && (_depth > 0)) {
214             _unmarshaller.endElement(name, namespace);
215             --_depth;
216             return;
217         }
218 
219         //-- have unmarshaller perform any necessary clean up
220         _unmarshaller.finish();
221 
222         if (SchemaNames.ANNOTATION.equals(name)) {
223             _union.setLocalAnnotation((Annotation)_unmarshaller.getObject());
224         }
225         else if (SchemaNames.SIMPLE_TYPE.equals(name)) {
226             
227             SimpleType simpleType = 
228                 (SimpleType)_unmarshaller.getObject();
229                 
230             //-- make sure type is not another Union
231             if (simpleType instanceof Union) {
232                 String err = "A 'union' may only contain SimpleTypes of "+
233                     "the atomic or list variety.";
234                 error(err);
235             }
236             //-- make sure type is atomic or list
237             // XXXX to be added later
238             
239             _union.addMemberType(simpleType);
240         }
241         
242 
243         _unmarshaller = null;
244     } //-- endElement
245 
246     public void characters(char[] ch, int start, int length)
247         throws XMLException
248     {
249         //-- Do delagation if necessary
250         if (_unmarshaller != null) {
251             _unmarshaller.characters(ch, start, length);
252         }
253     } //-- characters
254 
255 
256     /**
257      * Processes the given string into the referenced simpleTypes
258      * for the Union being unmarshalled.
259      *
260      * @param memberTypes the memberTypes list.
261     **/
262     private void processMemberTypes(String memberTypes) {
263         if ((memberTypes == null) || (memberTypes.length() == 0))
264             return;
265             
266         StringTokenizer st = new StringTokenizer(memberTypes);
267         while (st.hasMoreTokens()) {
268             String typeName = st.nextToken();
269             SimpleType simpleType = _schema.getSimpleType(typeName);
270             if (simpleType != null) {
271                 _union.addMemberType(simpleType);
272             }
273             else {
274                 _union.addMemberType(typeName);
275             }
276             
277         }
278     } //-- processMemberTypes
279     
280 } //-- UnionUnmarshaller