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 1999-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 org.exolab.castor.xml.AttributeSet;
50 import org.exolab.castor.xml.Namespaces;
51 import org.exolab.castor.xml.XMLException;
52 import org.exolab.castor.xml.schema.Annotation;
53 import org.exolab.castor.xml.schema.Group;
54 import org.exolab.castor.xml.schema.ModelGroup;
55 import org.exolab.castor.xml.schema.Schema;
56 import org.exolab.castor.xml.schema.SchemaContext;
57 import org.exolab.castor.xml.schema.SchemaException;
58 import org.exolab.castor.xml.schema.SchemaNames;
59
60 /**
61 * A class for Unmarshalling ModelGroups Definition
62 * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
63 * @version $Revisio:$ $Date: 2005-12-13 14:58:48 -0700 (Tue, 13 Dec 2005) $
64 **/
65 public class ModelGroupUnmarshaller extends ComponentReader {
66
67 //--------------------------/
68 //- Static Class Variables -/
69 //--------------------------/
70
71 /**
72 * The value of the maximum occurance wild card
73 */
74 private static final String MAX_OCCURS_WILDCARD = "unbounded";
75
76 //--------------------/
77 //- Member Variables -/
78 //--------------------/
79
80 /**
81 * The current ComponentReader
82 **/
83 private ComponentReader unmarshaller;
84
85 /**
86 * The current branch depth
87 **/
88 private int depth = 0;
89
90 /**
91 * The ModelGroup reference for the ModelGroup we are constructing
92 **/
93 private ModelGroup _group = null;
94
95 /**
96 * The Schema being "unmarshalled"
97 **/
98 private Schema _schema = null;
99
100 /**
101 * Flag to indicate if we have already encounter an {@literal <annotation>}
102 */
103 private boolean foundAnnotation = false;
104 //----------------/
105 //- Constructors -/
106 //----------------/
107
108 /**
109 * Creates a new ModelGroupUnmarshaller.
110 * @param schemaContext the {@link SchemaContext} to get some configuration settings from
111 * @param schema the Schema to which the ModelGroup belongs
112 * @param atts the AttributeList
113 **/
114 public ModelGroupUnmarshaller(
115 final SchemaContext schemaContext,
116 final Schema schema,
117 final AttributeSet atts) {
118 super(schemaContext);
119
120 this._schema = schema;
121
122 _group = new ModelGroup(_schema);
123
124 //-- handle attributes
125 String attValue = null;
126
127
128 //-- set name
129 _group.setName(atts.getValue("name"));
130
131 /*
132 * @maxOccurs
133 * If maxOccurs is present, the value is either unbounded
134 * or the int value of the attribute, otherwise maxOccurs
135 * equals the minOccurs value.
136 */
137 attValue = atts.getValue(SchemaNames.MAX_OCCURS_ATTR);
138 if (attValue != null) {
139 if (_group.getName() != null)
140 throw new IllegalArgumentException("In <group>: "+_group.getName()+"'maxOccurs' cannot appear in a named <group>");
141 if (MAX_OCCURS_WILDCARD.equals(attValue)) attValue = "-1";
142 int maxOccurs = toInt(attValue);
143 _group.setMaxOccurs(maxOccurs);
144 }
145 //-- minOccurs
146 attValue = atts.getValue("minOccurs");
147 if (attValue != null) {
148 if (_group.getName() != null)
149 throw new IllegalArgumentException("In <group>: "+_group.getName()+", 'minOccurs' cannot appear in a named <group>");
150 _group.setMinOccurs(toInt(attValue));
151 }
152
153 //-- @ref
154 attValue = atts.getValue("ref");
155 if (attValue != null) {
156 if (_group.getName() != null)
157 throw new IllegalArgumentException("In <group>: "+_group.getName()+", 'ref' cannot appear in a named <group>");
158 // String name = attValue;
159 // int idx = name.indexOf(':');
160 // String ns = null;
161 // if (idx >= 0) {
162 // String nsPrefix = name.substring(0,idx);
163 // name = name.substring(idx + 1);
164 // ns = (String) schema.getNamespace(nsPrefix);
165 // if (ns == null) {
166 // String err = "in the <group> referring: "+attValue;
167 // err += " The Namespace prefix is not recognized '"+nsPrefix+"'";
168 // throw new IllegalArgumentException(err);
169 // }
170 // }
171 //
172 // if (ns != null) {
173 // Schema tempSchema = schema.getImportedSchema(ns);
174 // if (tempSchema!=null) {
175 // _group.setSchema(tempSchema);
176 // }
177 // tempSchema = null;
178 // }
179
180 _group.setReference(attValue);
181 }
182 //-- id
183 attValue = atts.getValue("id");
184 _group.setId(attValue);
185 //-- not yet supported
186
187
188 } //-- ModelGroupUnmarshaller
189
190 //-----------/
191 //- Methods -/
192 //-----------/
193
194
195
196 /**
197 * Returns the Group that was unmarshalled by this Unmarshaller.
198 * This method should only be called after unmarshalling
199 * has been completed.
200 *
201 * @return the unmarshalled Group
202 **/
203 public ModelGroup getGroup() {
204 return _group;
205 } //-- getGroup
206
207 /**
208 * Returns the Object created by this ComponentReader
209 * @return the Object created by this ComponentReader
210 **/
211 public Object getObject() {
212 return getGroup();
213 } //-- getObject
214
215 /**
216 * Sets the name of the element that this UnknownUnmarshaller handles
217 **/
218 public String elementName() {
219 return SchemaNames.GROUP;
220 } //-- elementName
221
222 /**
223 * Signals the start of an element with the given name.
224 *
225 * @param name the NCName of the element. It is an error
226 * if the name is a QName (ie. contains a prefix).
227 * @param namespace the namespace of the element. This may be null.
228 * Note: A null namespace is not the same as the default namespace unless
229 * the default namespace is also null.
230 * @param atts the AttributeSet containing the attributes associated
231 * with the element.
232 * @param nsDecls the namespace declarations being declared for this
233 * element. This may be null.
234 **/
235 public void startElement(String name, String namespace, AttributeSet atts,
236 Namespaces nsDecls)
237 throws XMLException
238 {
239 //-- Do delagation if necessary
240 if (unmarshaller != null) {
241 unmarshaller.startElement(name, namespace, atts, nsDecls);
242 ++depth;
243 return;
244 }
245
246 if (SchemaNames.ANNOTATION.equals(name)) {
247 if (foundAnnotation)
248 error("Only one (1) 'annotation' is allowed as a child of "+
249 "element definitions.");
250
251 foundAnnotation = true;
252 unmarshaller = new AnnotationUnmarshaller(getSchemaContext(), atts);
253 }
254
255 else if (SchemaNames.isGroupName(name)) {
256 unmarshaller
257 = new GroupUnmarshaller(getSchemaContext(), _schema, name, atts);
258 }
259 else {
260 StringBuffer err = new StringBuffer("illegal element <");
261 err.append(name);
262 err.append("> found in <group>.");
263 throw new SchemaException(err.toString());
264 }
265
266 } //-- startElement
267
268 /**
269 * Signals to end of the element with the given name.
270 *
271 * @param name the NCName of the element. It is an error
272 * if the name is a QName (ie. contains a prefix).
273 * @param namespace the namespace of the element.
274 **/
275 public void endElement(String name, String namespace)
276 throws XMLException
277 {
278
279 //-- Do delagation if necessary
280 if ((unmarshaller != null) && (depth > 0)) {
281 unmarshaller.endElement(name, namespace);
282 --depth;
283 return;
284 }
285
286 //-- check for name mismatches
287 if (unmarshaller != null) {
288 if (!name.equals(unmarshaller.elementName())) {
289 String err = "missing end element for ";
290 err += unmarshaller.elementName();
291 throw new SchemaException(err);
292 }
293 }
294
295 if (SchemaNames.ANNOTATION.equals(name)) {
296 Annotation ann = (Annotation)unmarshaller.getObject();
297 _group.addAnnotation(ann);
298 }
299
300 else if (SchemaNames.isGroupName(name)) {
301 Group group = ((GroupUnmarshaller)unmarshaller).getGroup();
302 _group.addGroup(group);
303 }
304
305 //-- have unmarshaller perform any necessary clean up
306 unmarshaller.finish();
307 unmarshaller = null;
308 } //-- endElement
309
310 public void characters(char[] ch, int start, int length)
311 throws XMLException
312 {
313 //-- Do delagation if necessary
314 if (unmarshaller != null) {
315 unmarshaller.characters(ch, start, length);
316 }
317 } //-- characters
318
319 } //-- ModelGroupUnmarshaller