001: /**
002: * Redistribution and use of this software and associated documentation
003: * ("Software"), with or without modification, are permitted provided
004: * that the following conditions are met:
005: *
006: * 1. Redistributions of source code must retain copyright
007: * statements and notices. Redistributions must also contain a
008: * copy of this document.
009: *
010: * 2. Redistributions in binary form must reproduce the
011: * above copyright notice, this list of conditions and the
012: * following disclaimer in the documentation and/or other
013: * materials provided with the distribution.
014: *
015: * 3. The name "Exolab" must not be used to endorse or promote
016: * products derived from this Software without prior written
017: * permission of Intalio, Inc. For written permission,
018: * please contact info@exolab.org.
019: *
020: * 4. Products derived from this Software may not be called "Exolab"
021: * nor may "Exolab" appear in their names without prior written
022: * permission of Intalio, Inc. Exolab is a registered
023: * trademark of Intalio, Inc.
024: *
025: * 5. Due credit should be given to the Exolab Project
026: * (http://www.exolab.org/).
027: *
028: * THIS SOFTWARE IS PROVIDED BY INTALIO, INC. AND CONTRIBUTORS
029: * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
030: * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
031: * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
032: * INTALIO, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
033: * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
034: * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
035: * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
036: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
037: * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
038: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
039: * OF THE POSSIBILITY OF SUCH DAMAGE.
040: *
041: * Copyright 1999-2002 (C) Intalio, Inc. All Rights Reserved.
042: *
043: * $Id: WildcardUnmarshaller.java 5951 2006-05-30 22:18:48Z bsnyder $
044: */package org.exolab.castor.xml.schema.reader;
045:
046: import org.exolab.castor.xml.AttributeSet;
047: import org.exolab.castor.xml.Namespaces;
048: import org.exolab.castor.xml.XMLException;
049: import org.exolab.castor.xml.schema.Annotation;
050: import org.exolab.castor.xml.schema.AttributeGroup;
051: import org.exolab.castor.xml.schema.ComplexType;
052: import org.exolab.castor.xml.schema.Group;
053: import org.exolab.castor.xml.schema.Resolver;
054: import org.exolab.castor.xml.schema.Schema;
055: import org.exolab.castor.xml.schema.SchemaException;
056: import org.exolab.castor.xml.schema.SchemaNames;
057: import org.exolab.castor.xml.schema.Wildcard;
058:
059: import java.util.StringTokenizer;
060:
061: /**
062: * A class for Unmarshalling WildCard
063: * @author <a href="mailto:blandin@intalio.com">Arnaud Blandin</a>
064: * @version $Revision: 5951 $ $Date: 2003-07-03 15:49:44 -0600 (Thu, 03 Jul 2003) $
065: **/
066: public class WildcardUnmarshaller extends ComponentReader {
067:
068: /**
069: * The value of the maximum occurance wild card
070: */
071: private static final String MAX_OCCURS_WILDCARD = "unbounded";
072:
073: //--------------------/
074: //- Member Variables -/
075: //--------------------/
076:
077: /**
078: * The current ComponentReader
079: **/
080: private ComponentReader unmarshaller;
081:
082: /**
083: * The current branch depth
084: **/
085: private int depth = 0;
086:
087: /**
088: * The wildcard we are constructing
089: */
090: private Wildcard _wildcard = null;
091: /**
092: * The Schema being "unmarshalled"
093: **/
094: private Schema _schema = null;
095:
096: /**
097: * The element name of the Group to be unmarshalled.
098: */
099: private String _element = SchemaNames.ANY;
100:
101: //----------------/
102: //- Constructors -/
103: //----------------/
104: public WildcardUnmarshaller(ComplexType complexType, Schema schema,
105: String element, AttributeSet atts, Resolver resolver) {
106: super ();
107: _wildcard = new Wildcard(complexType);
108: init(schema, element, atts, resolver);
109: }
110:
111: public WildcardUnmarshaller(Group group, Schema schema,
112: String element, AttributeSet atts, Resolver resolver) {
113: super ();
114: _wildcard = new Wildcard(group);
115: init(schema, element, atts, resolver);
116: }
117:
118: public WildcardUnmarshaller(AttributeGroup attGroup, Schema schema,
119: String element, AttributeSet atts, Resolver resolver) {
120: super ();
121: _wildcard = new Wildcard(attGroup);
122: init(schema, element, atts, resolver);
123: }
124:
125: /**
126: * Creates a new WildcardUnmarshaller
127: * @param schema the Schema to which the Wildcard belongs
128: * @param element the name of the element
129: * @param atts the AttributeList
130: * @param resolver the resolver being used for reference resolving
131: **/
132: public void init(Schema schema, String element, AttributeSet atts,
133: Resolver resolver) {
134: setResolver(resolver);
135: this ._schema = schema;
136: this ._element = element;
137:
138: //-- handle attributes
139: String attValue = null;
140:
141: if (SchemaNames.ANY_ATTRIBUTE.equals(element))
142: _wildcard.setAttributeWildcard();
143: _element = element;
144:
145: //--namespace
146: attValue = atts.getValue(SchemaNames.NAMESPACE);
147:
148: if (attValue != null) {
149: // check if there is more than one namespace
150: StringTokenizer tokenizer = new StringTokenizer(attValue);
151: while (tokenizer.hasMoreTokens()) {
152: //need to retrieve all the namespaces
153: String temp = tokenizer.nextToken();
154: //if there is more than one namespace ##any or ##other should not
155: //appear
156: /**@todo optimize the following?*/
157: if (tokenizer.countTokens() > 1)
158: if ((SchemaNames.NAMESPACE_ANY.equals(temp))
159: || (SchemaNames.NAMESPACE_OTHER
160: .equals(temp)))
161: throw new IllegalArgumentException(
162: temp
163: + " is not valid when multiple namespaces are listed.");
164:
165: /**
166: *@todo validation on the value of the attribute
167: * we need a way to check the validity of an URI.
168: * A temporary solution if to assume that the URI are URL.
169: * @see SchemaNames#isNamespaceName()
170: */
171: if (SchemaNames.isNamespaceName(temp))
172: _wildcard.addNamespace(temp);
173: else {
174: String err = "Invalid 'namespace' value: " + temp;
175: throw new IllegalArgumentException(err);
176: }
177: }
178: }//if
179: else
180: _wildcard.addNamespace(SchemaNames.NAMESPACE_ANY);
181:
182: /*
183: * @maxOccurs
184: * If maxOccurs is present, the value is either unbounded
185: * or the int value of the attribute, otherwise maxOccurs
186: * equals the minOccurs value.
187: */
188: attValue = atts.getValue(SchemaNames.MAX_OCCURS_ATTR);
189: if (attValue != null) {
190: if (_wildcard.isAttributeWildcard())
191: throw new IllegalStateException(
192: "'maxOccurs' is prohibited on a <anyAttribute> element.");
193: if (MAX_OCCURS_WILDCARD.equals(attValue))
194: attValue = "-1";
195: int maxOccurs = toInt(attValue);
196: _wildcard.setMaxOccurs(maxOccurs);
197: }
198: //-- minOccurs
199: attValue = atts.getValue("minOccurs");
200: if (attValue != null) {
201: if (_wildcard.isAttributeWildcard())
202: throw new IllegalStateException(
203: "'minOccurs' is prohibited on a <anyAttribute> element.");
204: _wildcard.setMinOccurs(toInt(attValue));
205: }
206: //-- processContents
207: attValue = atts.getValue("processContents");
208:
209: if (attValue != null) {
210: try {
211: _wildcard.setProcessContents(attValue);
212: } catch (SchemaException e) {
213: throw new IllegalArgumentException(e.getMessage());
214: }
215: }
216:
217: //-- id
218: _wildcard.setId(atts.getValue("id"));
219:
220: } //-- WildCardUnmarshaller
221:
222: //-----------/
223: //- Methods -/
224: //-----------/
225:
226: /**
227: * Returns the name of the element that this ComponentReader
228: * handles
229: * @return the name of the element that this ComponentReader
230: * handles
231: **/
232: public String elementName() {
233: return _element;
234: } //-- elementName
235:
236: /**
237: * Returns the Wildcard unmarshalled by this Unmarshaller.
238: * @return the unmarshalled Wildcard
239: */
240: public Wildcard getWildcard() {
241: return _wildcard;
242: }
243:
244: /**
245: * Returns the Object created by this ComponentReader
246: * @return the Object created by this ComponentReader
247: **/
248: public Object getObject() {
249: return getWildcard();
250: } //-- getObject
251:
252: /**
253: * Signals the start of an element with the given name.
254: *
255: * @param name the NCName of the element. It is an error
256: * if the name is a QName (ie. contains a prefix).
257: * @param namespace the namespace of the element. This may be null.
258: * Note: A null namespace is not the same as the default namespace unless
259: * the default namespace is also null.
260: * @param atts the AttributeSet containing the attributes associated
261: * with the element.
262: * @param nsDecls the namespace declarations being declared for this
263: * element. This may be null.
264: **/
265: public void startElement(String name, String namespace,
266: AttributeSet atts, Namespaces nsDecls) throws XMLException {
267: //-- Do delagation if necessary
268: if (unmarshaller != null) {
269: unmarshaller.startElement(name, namespace, atts, nsDecls);
270: ++depth;
271: return;
272: }
273: //-- <annotation>
274: if (SchemaNames.ANNOTATION.equals(name)) {
275: unmarshaller = new AnnotationUnmarshaller(atts);
276: }
277:
278: else {
279: StringBuffer err = new StringBuffer("illegal element <");
280: err.append(name);
281: err.append("> found in <");
282: err.append(_element);
283: err.append(">");
284: throw new SchemaException(err.toString());
285: }
286:
287: } //-- startElement
288:
289: /**
290: * Signals to end of the element with the given name.
291: *
292: * @param name the NCName of the element. It is an error
293: * if the name is a QName (ie. contains a prefix).
294: * @param namespace the namespace of the element.
295: **/
296: public void endElement(String name, String namespace)
297: throws XMLException {
298:
299: //-- Do delagation if necessary
300: if ((unmarshaller != null) && (depth > 0)) {
301: unmarshaller.endElement(name, namespace);
302: --depth;
303: return;
304: }
305:
306: //-- check for name mismatches
307: if (unmarshaller != null) {
308: if (!name.equals(unmarshaller.elementName())) {
309: String err = "missing end element for ";
310: err += unmarshaller.elementName();
311: throw new SchemaException(err);
312: }
313: }
314:
315: //-- have unmarshaller perform any necessary clean up
316: unmarshaller.finish();
317:
318: //-- <annotation>
319: if (name == SchemaNames.ANNOTATION) {
320: _schema
321: .addAnnotation((Annotation) unmarshaller
322: .getObject());
323: }
324: unmarshaller = null;
325: } //-- endElement
326:
327: public void characters(char[] ch, int start, int length)
328: throws XMLException {
329: //-- Do delagation if necessary
330: if (unmarshaller != null) {
331: unmarshaller.characters(ch, start, length);
332: }
333: } //-- characters
334:
335: }
|