View Javadoc
1   /**
2    * Redistribution and use of this software and associated documentation ("Software"), with or
3    * without modification, are permitted provided that the following conditions are met:
4    *
5    * 1. Redistributions of source code must retain copyright statements and notices. Redistributions
6    * must also contain a copy of this document.
7    *
8    * 2. Redistributions in binary form must reproduce the above copyright notice, this list of
9    * conditions and the following disclaimer in the documentation and/or other materials provided with
10   * the distribution.
11   *
12   * 3. The name "Exolab" must not be used to endorse or promote products derived from this Software
13   * without prior written permission of Intalio, Inc. For written permission, please contact
14   * info@exolab.org.
15   *
16   * 4. Products derived from this Software may not be called "Exolab" nor may "Exolab" appear in
17   * their names without prior written permission of Intalio, Inc. Exolab is a registered trademark of
18   * Intalio, Inc.
19   *
20   * 5. Due credit should be given to the Exolab Project (http://www.exolab.org/).
21   *
22   * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS ``AS IS'' AND ANY EXPRESSED OR
23   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
24   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTALIO, INC. OR ITS
25   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27   * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
29   * WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30   *
31   * Copyright 2000-2002 (C) Intalio Inc. All Rights Reserved.
32   *
33   * $Id$
34   */
35  
36  package org.exolab.castor.xml.schema.reader;
37  
38  import org.exolab.castor.xml.AttributeSet;
39  import org.exolab.castor.xml.Namespaces;
40  import org.exolab.castor.xml.XMLException;
41  import org.exolab.castor.xml.schema.Annotation;
42  import org.exolab.castor.xml.schema.AttributeDecl;
43  import org.exolab.castor.xml.schema.AttributeGroupReference;
44  import org.exolab.castor.xml.schema.ComplexType;
45  import org.exolab.castor.xml.schema.SchemaContext;
46  import org.exolab.castor.xml.schema.Group;
47  import org.exolab.castor.xml.schema.Schema;
48  import org.exolab.castor.xml.schema.SchemaException;
49  import org.exolab.castor.xml.schema.SchemaNames;
50  import org.exolab.castor.xml.schema.Wildcard;
51  import org.exolab.castor.xml.schema.XMLType;
52  
53  /**
54   * A class for unmarshalling restriction elements of a complexContent
55   * 
56   * @author <a href="mailto:blandin@intalio.com">Arnaud Blandin</a>
57   * @version $Revision$ $Date: 2006-04-14 04:14:43 -0600 (Fri, 14 Apr 2006) $ TODO: validation stuff
58   *          about the data TODO: set the flag of restriction for the complexType
59   * 
60   **/
61  public class ComplexContentRestrictionUnmarshaller extends ComponentReader {
62  
63  
64    // --------------------/
65    // - Member Variables -/
66    // --------------------/
67  
68    /**
69     * The current ComponentReader
70     **/
71    private ComponentReader unmarshaller;
72  
73    /**
74     * The current branch depth
75     **/
76    private int depth = 0;
77  
78    /**
79     * The complexType we are unmarshalling
80     **/
81    private ComplexType _complexType = null;
82  
83    private Schema _schema = null;
84    private boolean foundAnnotation = false;
85    private boolean foundAttribute = false;
86    private boolean foundAttributeGroup = false;
87    private boolean foundModelGroup = false;
88  
89    // ----------------/
90    // - Constructors -/
91    // ----------------/
92    /**
93     * Creates a new RestrictionUnmarshaller.
94     * 
95     * @param schemaContext the schema context to get some configuration settings from
96     * @param complexType the complexType being unmarshalled
97     * @param atts the AttributeList
98     */
99    public ComplexContentRestrictionUnmarshaller(final SchemaContext schemaContext,
100       final ComplexType complexType, final AttributeSet atts) throws XMLException {
101     super(schemaContext);
102     _complexType = complexType;
103     _schema = complexType.getSchema();
104 
105     _complexType.setDerivationMethod(SchemaNames.RESTRICTION);
106     _complexType.setRestriction(true);
107 
108     // -- base
109     String base = atts.getValue(SchemaNames.BASE_ATTR);
110     if ((base != null) && (base.length() > 0)) {
111 
112       XMLType baseType = _schema.getType(base);
113       if (baseType == null)
114         _complexType.setBase(base);
115       // the base must not be a simpleType
116       else if (baseType.isSimpleType()) {
117         String err =
118             "complexType: " + (_complexType.getName()) != null ? _complexType.getName() : "\n";
119         err += "A complex type cannot be a restriction" + " of a simpleType.";
120         throw new IllegalStateException(err);
121       } else if (!baseType.isAnyType()) {
122         // We are now sure the base is a complexType
123         // but is it already a restriction? (see PR 5.11->restriction->1.1)
124 
125         // -- KV 2004-03-15
126         // -- Need to valididate this constraint...I couldn't
127         // -- find it in the XML Schema 1.0 Recommendation,
128         // -- commenting out for now.
129         /*
130          * if (((ComplexType)baseType).isRestricted()) { String err="complexType: "
131          * +(_complexType.getName()) != null? _complexType.getName():"\n"; err +=
132          * "A complex type cannot be a restriction"+ " of a restriction."; throw new
133          * IllegalStateException(err); }
134          * 
135          */
136       }
137       _complexType.setBase(base);
138       _complexType.setBaseType(baseType);
139 
140     }
141 
142 
143   } // -- ComplexContentRestrictionUnmarshaller
144 
145   // -----------/
146   // - Methods -/
147   // -----------/
148 
149   /**
150    * Returns the name of the element that this ComponentReader handles
151    * 
152    * @return the name of the element that this ComponentReader handles
153    **/
154   public String elementName() {
155     return SchemaNames.RESTRICTION;
156   } // -- elementName
157 
158   /**
159    * Returns the Object created by this ComponentReader
160    * 
161    * @return the Object created by this ComponentReader
162    **/
163   public Object getObject() {
164     return null;
165   } // -- getObject
166 
167   /**
168    * Signals the start of an element with the given name.
169    *
170    * @param name the NCName of the element. It is an error if the name is a QName (ie. contains a
171    *        prefix).
172    * @param namespace the namespace of the element. This may be null. Note: A null namespace is not
173    *        the same as the default namespace unless the default namespace is also null.
174    * @param atts the AttributeSet containing the attributes associated with the element.
175    * @param nsDecls the namespace declarations being declared for this element. This may be null.
176    **/
177   public void startElement(String name, String namespace, AttributeSet atts, Namespaces nsDecls)
178       throws XMLException {
179     // -- Do delagation if necessary
180     if (unmarshaller != null) {
181       unmarshaller.startElement(name, namespace, atts, nsDecls);
182       ++depth;
183       return;
184     }
185 
186 
187     // -- annotation
188     if (name.equals(SchemaNames.ANNOTATION)) {
189 
190       if (foundModelGroup || foundAttribute || foundAttributeGroup)
191         error("An annotation must appear as the first child " + "of 'restriction' elements.");
192 
193       if (foundAnnotation)
194         error("Only one (1) annotation may appear as a child of " + "'restriction' elements.");
195 
196       foundAnnotation = true;
197       unmarshaller = new AnnotationUnmarshaller(getSchemaContext(), atts);
198     }
199 
200     // -- ModelGroup declarations (choice, all, sequence, group)
201     else if (SchemaNames.isGroupName(name)) {
202 
203       if (foundAttribute || foundAttributeGroup)
204         error("'" + name + "' must appear before any attribute "
205             + "definitions when a child of 'restriction'.");
206       if (foundModelGroup)
207         error("'" + name + "' cannot appear as a child of 'restriction' "
208             + "if another 'all', 'sequence', 'choice' or " + "'group' also exists.");
209 
210       foundModelGroup = true;
211       unmarshaller = new GroupUnmarshaller(getSchemaContext(), _schema, name, atts);
212     }
213 
214     else if (SchemaNames.ATTRIBUTE.equals(name)) {
215       foundAttribute = true;
216       unmarshaller = new AttributeUnmarshaller(getSchemaContext(), _schema, atts);
217     }
218 
219     else if (SchemaNames.ATTRIBUTE_GROUP.equals(name)) {
220 
221       // --In a complexType we only reference attribute group
222       if (atts.getValue(SchemaNames.REF_ATTR) == null) {
223         error("A 'complexType' may contain referring " + "attributeGroups, but not defining ones.");
224       }
225       foundAttributeGroup = true;
226       unmarshaller = new AttributeGroupUnmarshaller(getSchemaContext(), _schema, atts);
227     }
228     // -- <anyAttribute>
229     else if (SchemaNames.ANY_ATTRIBUTE.equals(name)) {
230       unmarshaller =
231           new WildcardUnmarshaller(getSchemaContext(), _complexType, _schema, name, atts);
232     }
233 
234     else
235       illegalElement(name);
236 
237   } // -- startElement
238 
239   /**
240    * Signals to end of the element with the given name.
241    *
242    * @param name the NCName of the element. It is an error if the name is a QName (ie. contains a
243    *        prefix).
244    * @param namespace the namespace of the element.
245    **/
246   public void endElement(String name, String namespace) throws XMLException {
247 
248     // -- Do delagation if necessary
249     if ((unmarshaller != null) && (depth > 0)) {
250       unmarshaller.endElement(name, namespace);
251       --depth;
252       return;
253     }
254 
255     // -- have unmarshaller perform any necessary clean up
256     unmarshaller.finish();
257 
258     // -- annotation
259     if (SchemaNames.ANNOTATION.equals(name)) {
260       Annotation ann = ((AnnotationUnmarshaller) unmarshaller).getAnnotation();
261       _complexType.addAnnotation(ann);
262     }
263     // -- <anyAttribute>
264     else if (SchemaNames.ANY_ATTRIBUTE.equals(name)) {
265       Wildcard wildcard = ((WildcardUnmarshaller) unmarshaller).getWildcard();
266       try {
267         _complexType.setAnyAttribute(wildcard);
268       } catch (SchemaException e) {
269         throw new IllegalArgumentException(e.getMessage());
270       }
271     }
272     // -- attribute
273     else if (SchemaNames.ATTRIBUTE.equals(name)) {
274       AttributeDecl attrDecl = ((AttributeUnmarshaller) unmarshaller).getAttribute();
275 
276       /* TODO: do the validation later */
277       _complexType.addAttributeDecl(attrDecl);
278     }
279     // -- attribute groups
280     else if (SchemaNames.ATTRIBUTE_GROUP.equals(name)) {
281       AttributeGroupReference attrGroupRef = (AttributeGroupReference) unmarshaller.getObject();
282       _complexType.addAttributeGroupReference(attrGroupRef);
283     }
284     // -- group declarations (all, choice, group, sequence)
285     else if (SchemaNames.isGroupName(name)) {
286       Group group = ((GroupUnmarshaller) unmarshaller).getGroup();
287       _complexType.addGroup(group);
288     }
289     unmarshaller = null;
290   } // -- endElement
291 
292   public void characters(char[] ch, int start, int length) throws XMLException {
293     // -- Do delagation if necessary
294     if (unmarshaller != null) {
295       unmarshaller.characters(ch, start, length);
296     }
297   } // -- characters
298 } // -- ComplexContentRestrictionUnmarshaller