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 import org.exolab.castor.xml.AttributeSet;
49 import org.exolab.castor.xml.Namespaces;
50 import org.exolab.castor.xml.XMLException;
51 import org.exolab.castor.xml.schema.Annotation;
52 import org.exolab.castor.xml.schema.AttributeDecl;
53 import org.exolab.castor.xml.schema.AttributeGroup;
54 import org.exolab.castor.xml.schema.AttributeGroupDecl;
55 import org.exolab.castor.xml.schema.AttributeGroupReference;
56 import org.exolab.castor.xml.schema.SchemaContext;
57 import org.exolab.castor.xml.schema.Schema;
58 import org.exolab.castor.xml.schema.SchemaException;
59 import org.exolab.castor.xml.schema.SchemaNames;
60 import org.exolab.castor.xml.schema.Wildcard;
61
62 /**
63 * A class for Unmarshalling AttributeGroups
64 * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
65 * @version $Revision$ $Date: 2005-12-13 14:58:48 -0700 (Tue, 13 Dec 2005) $
66 **/
67 public class AttributeGroupUnmarshaller extends ComponentReader {
68
69
70 //--------------------/
71 //- Member Variables -/
72 //--------------------/
73
74 /**
75 * The current ComponentReader
76 **/
77 private ComponentReader unmarshaller;
78
79 /**
80 * The current branch depth
81 **/
82 private int depth = 0;
83
84 /**
85 * The AttributeGroup we are constructing
86 **/
87 private AttributeGroup _attributeGroup = null;
88
89 private boolean allowAnnotation = true;
90 private boolean foundAnyAttribute = false;
91 private boolean isRef = false;
92
93 private Schema _schema = null;
94
95 //----------------/
96 //- Constructors -/
97 //----------------/
98
99 /**
100 * Creates a new AttributeGroupUnmarshaller.
101 * @param schemaContext the schema context to get some configuration settings from
102 * @param schema the Schema to which the AttributeGroup belongs
103 * @param atts the AttributeList
104 **/
105 public AttributeGroupUnmarshaller(
106 final SchemaContext schemaContext,
107 final Schema schema,
108 final AttributeSet atts)
109 throws XMLException {
110 super(schemaContext);
111 this._schema = schema;
112
113
114 String ref = atts.getValue(SchemaNames.REF_ATTR);
115 if (ref != null) {
116 if (ref.length() > 0) {
117 isRef = true;
118 _attributeGroup = new AttributeGroupReference(schema, ref);
119 }
120 else {
121 String err = "The value of the '" + SchemaNames.REF_ATTR +
122 "' attribute for attribute group must contain a " +
123 "valid value.";
124 throw new SchemaException(err);
125 }
126 }
127 else {
128 AttributeGroupDecl attDecl = new AttributeGroupDecl(schema);
129 _attributeGroup = attDecl;
130
131 //-- handle attributes
132 attDecl.setName(atts.getValue(SchemaNames.NAME_ATTR));
133 attDecl.setId(atts.getValue(SchemaNames.ID_ATTR));
134 }
135
136
137
138 } //-- AttributeGroupUnmarshaller
139
140 //-----------/
141 //- Methods -/
142 //-----------/
143
144 /**
145 * Returns the name of the element that this ComponentReader
146 * handles
147 * @return the name of the element that this ComponentReader
148 * handles
149 **/
150 public String elementName() {
151 return SchemaNames.ATTRIBUTE_GROUP;
152 } //-- elementName
153
154 /**
155 * Returns the AttributeGroup created by this
156 * AttributeGroupUnmarshaller
157 *
158 * @return the AttributeGroup created by this
159 * AttributeGroupUnmarshaller
160 **/
161 public AttributeGroup getAttributeGroup() {
162 return _attributeGroup;
163 } //-- getAttributeGroup
164
165 /**
166 * Returns the Object created by this ComponentReader
167 * @return the Object created by this ComponentReader
168 **/
169 public Object getObject() {
170 return getAttributeGroup();
171 } //-- getObject
172
173 /**
174 * Signals the start of an element with the given name.
175 *
176 * @param name the NCName of the element. It is an error
177 * if the name is a QName (ie. contains a prefix).
178 * @param namespace the namespace of the element. This may be null.
179 * Note: A null namespace is not the same as the default namespace unless
180 * the default namespace is also null.
181 * @param atts the AttributeSet containing the attributes associated
182 * with the element.
183 * @param nsDecls the namespace declarations being declared for this
184 * element. This may be null.
185 **/
186 public void startElement(String name, String namespace, AttributeSet atts,
187 Namespaces nsDecls)
188 throws XMLException
189 {
190 //-- Do delagation if necessary
191 if (unmarshaller != null) {
192 unmarshaller.startElement(name, namespace, atts, nsDecls);
193 ++depth;
194 return;
195 }
196
197 //-- <anyAttribute>
198 if (SchemaNames.ANY_ATTRIBUTE.equals(name)) {
199 if (foundAnyAttribute)
200 error("an anyAttribute element can appear only once as a child "+
201 "of an 'AttributeGroup'.");
202 foundAnyAttribute = true;
203 allowAnnotation = true;
204 unmarshaller
205 = new WildcardUnmarshaller(getSchemaContext(), _attributeGroup, _schema, name, atts);
206 }
207 //-- attribute declarations
208 else if (SchemaNames.ATTRIBUTE.equals(name)) {
209 allowAnnotation = false;
210
211 if (isRef)
212 error("AttributeGroup references may not have children.");
213
214 unmarshaller
215 = new AttributeUnmarshaller(getSchemaContext(), _schema, atts);
216 }
217 //-- element declarations
218 else if (SchemaNames.ATTRIBUTE_GROUP.equals(name)) {
219 allowAnnotation = false;
220 if (isRef)
221 error("AttributeGroup references may not have children.");
222 unmarshaller
223 = new AttributeGroupUnmarshaller(getSchemaContext(), _schema, atts);
224 }
225 else if (name.equals(SchemaNames.ANNOTATION)) {
226 if (!allowAnnotation) outOfOrder(name);
227 unmarshaller = new AnnotationUnmarshaller(getSchemaContext(), atts);
228 }
229 else illegalElement(name);
230
231 } //-- startElement
232
233 /**
234 * Signals to end of the element with the given name.
235 *
236 * @param name the NCName of the element. It is an error
237 * if the name is a QName (ie. contains a prefix).
238 * @param namespace the namespace of the element.
239 **/
240 public void endElement(String name, String namespace)
241 throws XMLException
242 {
243
244 //-- Do delagation if necessary
245 if ((unmarshaller != null) && (depth > 0)) {
246 unmarshaller.endElement(name, namespace);
247 --depth;
248 return;
249 }
250
251 //-- have unmarshaller perform any necessary clean up
252 unmarshaller.finish();
253
254 //-- <anyAttribute>
255 if (SchemaNames.ANY_ATTRIBUTE.equals(name)) {
256 Wildcard wildcard =
257 ((WildcardUnmarshaller)unmarshaller).getWildcard();
258 try {
259 ((AttributeGroupDecl)_attributeGroup).setAnyAttribute(wildcard);
260 } catch (SchemaException e) {
261 throw new IllegalArgumentException(e.getMessage());
262 }
263 }
264
265
266 //-- attribute declarations
267 else if (SchemaNames.ATTRIBUTE.equals(name)) {
268 AttributeDecl attrDecl =
269 ((AttributeUnmarshaller)unmarshaller).getAttribute();
270
271 ((AttributeGroupDecl)_attributeGroup).addAttribute(attrDecl);
272 }
273 //-- attribute group references
274 else if (SchemaNames.ATTRIBUTE_GROUP.equals(name)) {
275
276 Object obj = unmarshaller.getObject();
277
278 try {
279 ((AttributeGroupDecl)_attributeGroup).addReference(
280 (AttributeGroupReference) obj);
281 }
282 catch (ClassCastException ex) {
283 String err = "AttributeGroups cannot contain new " +
284 "AttributeGroup definitions, only references to " +
285 "top-level AttributeGroups are allowed.";
286 error(err);
287 }
288 }
289 //-- annotation
290 else if (SchemaNames.ANNOTATION.equals(name)) {
291 Annotation ann = ((AnnotationUnmarshaller)unmarshaller).getAnnotation();
292 _attributeGroup.addAnnotation(ann);
293 }
294
295 unmarshaller = null;
296 } //-- endElement
297
298 public void characters(char[] ch, int start, int length)
299 throws XMLException
300 {
301 //-- Do delagation if necessary
302 if (unmarshaller != null) {
303 unmarshaller.characters(ch, start, length);
304 }
305 } //-- characters
306
307 } //-- AttributeGroupUnmarshaller