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