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