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-2003 (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.Form;
54 import org.exolab.castor.xml.schema.SchemaContext;
55 import org.exolab.castor.xml.schema.Schema;
56 import org.exolab.castor.xml.schema.SchemaNames;
57 import org.exolab.castor.xml.schema.SimpleType;
58
59 /**
60 * The Unmarshaller for Attribute declarations
61 *
62 * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
63 * @version $Revision$ $Date: 2006-04-25 15:08:23 -0600 (Tue, 25 Apr 2006) $
64 **/
65 public class AttributeUnmarshaller extends ComponentReader {
66
67
68 //--------------------/
69 //- Member Variables -/
70 //--------------------/
71
72 /**
73 * The current ComponentReader
74 **/
75 private ComponentReader unmarshaller;
76
77 /**
78 * The current branch depth
79 **/
80 private int depth = 0;
81
82 /**
83 * The Attribute reference for the Attribute we are constructing
84 **/
85 private AttributeDecl _attribute = null;
86
87 private Schema _schema = null;
88
89 private boolean foundAnnotation = false;
90 private boolean foundSimpleType = false;
91
92
93 //----------------/
94 //- Constructors -/
95 //----------------/
96
97 public AttributeUnmarshaller(
98 final SchemaContext schemaContext,
99 final Schema schema,
100 final AttributeSet atts)
101 {
102 super(schemaContext);
103 this._schema = schema;
104
105 _attribute = new AttributeDecl(schema);
106
107 //--@ref
108 String attValue = atts.getValue(SchemaNames.REF_ATTR);
109 if (attValue != null) {
110 _attribute.setReference(attValue);
111 }
112
113 //-- @name
114 attValue = atts.getValue(SchemaNames.NAME_ATTR);
115 if (attValue != null) {
116 if (_attribute.isReference()) {
117 String err = "An attribute cannot have a 'name' attribute and a 'ref' attribute at the same time.";
118 throw new IllegalStateException(err);
119 }
120 _attribute.setName(attValue);
121 }
122
123 //-- @default
124 attValue = atts.getValue(SchemaNames.DEFAULT_ATTR);
125 if (attValue != null) {
126 _attribute.setDefaultValue(attValue);
127 }
128
129 //-- @id
130 _attribute.setId(atts.getValue(SchemaNames.ID_ATTR));
131
132 //-- @fixed
133 attValue = atts.getValue(SchemaNames.FIXED_ATTR);
134 if (attValue != null) {
135 _attribute.setFixedValue(attValue);
136 }
137
138 //-- @form
139 attValue = atts.getValue(SchemaNames.FORM);
140 if (attValue != null) {
141 if (_attribute.isReference()) {
142 String err = "An attribute reference cannot have a 'form' attribute.";
143 throw new IllegalArgumentException(err);
144 }
145 _attribute.setForm(Form.valueOf(attValue));
146 }
147
148 //-- @type
149 attValue = atts.getValue(SchemaNames.TYPE_ATTR);
150 if (attValue != null) {
151 if (_attribute.isReference()) {
152 String err = "An attribute reference cannot have a 'type' attribute.";
153 throw new IllegalArgumentException(err);
154 }
155 _attribute.setSimpleTypeReference(attValue);
156 }
157
158 //-- @use
159 attValue = atts.getValue(SchemaNames.USE_ATTR);
160 if (attValue != null) {
161 if (_attribute.isDefault() && (!attValue.equals(AttributeDecl.USE_OPTIONAL)) )
162 throw new IllegalArgumentException("When 'default' is present, the 'use' attribute must have the value 'optional'.");
163 _attribute.setUse(attValue);
164 }
165
166 } //-- AttributeUnmarshaller
167
168 //-----------/
169 //- Methods -/
170 //-----------/
171
172
173 /**
174 * Returns the name of the element that this ComponentReader
175 * handles
176 * @return the name of the element that this ComponentReader
177 * handles
178 **/
179 public String elementName() {
180 return SchemaNames.ATTRIBUTE;
181 } //-- elementName
182
183 /**
184 *
185 **/
186 public AttributeDecl getAttribute() {
187 return _attribute;
188 } //-- getAttribute
189
190 /**
191 * Returns the Object created by this ComponentReader
192 * @return the Object created by this ComponentReader
193 **/
194 public Object getObject() {
195 return getAttribute();
196 } //-- getObject
197
198 /**
199 * Signals the start of an element with the given name.
200 *
201 * @param name the NCName of the element. It is an error
202 * if the name is a QName (ie. contains a prefix).
203 * @param namespace the namespace of the element. This may be null.
204 * Note: A null namespace is not the same as the default namespace unless
205 * the default namespace is also null.
206 * @param atts the AttributeSet containing the attributes associated
207 * with the element.
208 * @param nsDecls the namespace declarations being declared for this
209 * element. This may be null.
210 **/
211 public void startElement(String name, String namespace, AttributeSet atts,
212 Namespaces nsDecls)
213 throws XMLException
214 {
215 //-- Do delagation if necessary
216 if (unmarshaller != null) {
217 unmarshaller.startElement(name, namespace, atts, nsDecls);
218 ++depth;
219 return;
220 }
221
222 if (SchemaNames.ANNOTATION.equals(name)) {
223
224 if (foundAnnotation)
225 error("Only one (1) annotation is allowed as a child of " +
226 "an attribute declaration.");
227
228 if (foundSimpleType)
229 error("An annotation may only appear as the first child of "+
230 "an attribute declaration.");
231
232 foundAnnotation = true;
233 unmarshaller = new AnnotationUnmarshaller(getSchemaContext(), atts);
234 }
235 else if (SchemaNames.SIMPLE_TYPE.equals(name)) {
236 if (foundSimpleType)
237 error("Only one (1) simpleType is allowed as a child of " +
238 "an attribute declaration.");
239
240 foundSimpleType = true;
241 unmarshaller = new SimpleTypeUnmarshaller(getSchemaContext(), _schema, atts);
242 }
243 else {
244 illegalElement(name);
245 }
246
247 } //-- startElement
248
249 /**
250 * Signals to end of the element with the given name.
251 *
252 * @param name the NCName of the element. It is an error
253 * if the name is a QName (ie. contains a prefix).
254 * @param namespace the namespace of the element.
255 **/
256 public void endElement(String name, String namespace)
257 throws XMLException
258 {
259
260 //-- Do delagation if necessary
261 if ((unmarshaller != null) && (depth > 0)) {
262 unmarshaller.endElement(name, namespace);
263 --depth;
264 return;
265 }
266
267 //-- call unmarshaller finish to perform any necessary cleanup
268 unmarshaller.finish();
269
270 if (SchemaNames.ANNOTATION.equals(name)) {
271 Annotation ann = (Annotation) unmarshaller.getObject();
272 _attribute.addAnnotation(ann);
273 }
274 else if (SchemaNames.SIMPLE_TYPE.equals(name)) {
275 SimpleType simpleType =
276 ((SimpleTypeUnmarshaller)unmarshaller).getSimpleType();
277 _attribute.setSimpleType(simpleType);
278 }
279
280 unmarshaller = null;
281
282 } //-- endElement
283
284 public void characters(char[] ch, int start, int length)
285 throws XMLException
286 {
287 //-- Do delagation if necessary
288 if (unmarshaller != null) {
289 unmarshaller.characters(ch, start, length);
290 }
291 } //-- characters
292
293 } //-- AttributeUnmarshaller