View Javadoc
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.net.URIResolver;
49  import org.exolab.castor.xml.AttributeSet;
50  import org.exolab.castor.xml.Namespaces;
51  import org.exolab.castor.xml.Unmarshaller;
52  import org.exolab.castor.xml.XMLException;
53  import org.exolab.castor.xml.schema.SchemaContext;
54  import org.exolab.castor.xml.schema.Resolver;
55  import org.xml.sax.Locator;
56  
57  /**
58   * The base class for separate component unmarshallers for reading an XML Schema
59   * component.
60   * 
61   * @author <a href="mailto:kvisco@intalio.com">Keith Visco</a>
62   * @version $Revision$ $Date: 2006-04-14 04:14:43 -0600 (Fri, 14 Apr
63   *          2006) $
64   **/
65  public abstract class ComponentReader {
66  
67     /** The Castor XML context to use. */
68     private SchemaContext _schemaContext;
69  
70     private Locator _documentLocator;
71  
72     /**
73      * The resolver to be used for resolving hrefs.
74      */
75     private URIResolver _uriResolver;
76  
77     private ComponentReader() {
78        super();
79     }
80  
81     /**
82      * To hand down a couple of configuration items to all {@link Unmarshaller} classes.
83      * 
84      * @param schemaContext
85      *           the {@link SchemaContext} to use
86      */
87     protected ComponentReader(final SchemaContext schemaContext) {
88        this();
89        _schemaContext = schemaContext;
90     }
91  
92     /**
93      * Returns the name of the element that this ComponentReader handles
94      * 
95      * @return the name of the element that this ComponentReader handles
96      **/
97     public abstract String elementName();
98  
99     /**
100     * Returns the Object created by this {@link Unmarshaller}
101     * 
102     * @return the Object created by this {@link Unmarshaller}
103     **/
104    public abstract Object getObject();
105 
106    /**
107     * Called to signal an end of unmarshalling. This method should be overridden
108     * to perform any necessary clean up by an {@link Unmarshaller}
109     **/
110    public void finish() throws XMLException {
111    }
112 
113    /**
114     * Returns the resolver used for resolving id references.
115     * 
116     * @return the resolver used for resolving id references.
117     **/
118    public Resolver getResolver() {
119       return _schemaContext.getSchemaResolver();
120    }
121 
122    /**
123     * Returns the URIresolver used for resolving hrefs.
124     * 
125     * @return the URIresolver used for resolving hrefs.
126     **/
127    public URIResolver getURIResolver() {
128       return _uriResolver;
129    }
130 
131    /**
132     * Sets the Resolver to be used for resolving id references
133     * 
134     * @param resolver
135     *           the Resolver to be used for resolving id references
136     **/
137    public void setResolver(Resolver resolver) {
138       _schemaContext.setSchemaResolver(resolver);
139    }
140 
141    /**
142     * Sets the URIResolver to be used for resolving hrefs.
143     * 
144     * @param uriResolver
145     *           the URIResolver to be used for resolving hrefs.
146     **/
147    public void setURIResolver(URIResolver uriResolver) {
148       _uriResolver = uriResolver;
149    }
150 
151    /**
152     * Determines if the given sequence of characters consists of whitespace
153     * characters
154     * 
155     * @param chars
156     *           an array of characters to check for whitespace
157     * @param start
158     *           the start index into the character array
159     * @param length
160     *           the number of characters to check
161     * @return true if the characters specficied consist only of whitespace
162     *         characters
163     **/
164    public static boolean isWhiteSpace(char[] chars, int start, int length) {
165       int max = start + length;
166       for (int i = start; i < max; i++) {
167          char ch = chars[i];
168          switch (ch) {
169          case ' ':
170          case '\n':
171          case '\t':
172          case '\r':
173             break;
174          default:
175             return false;
176          }
177       }
178       return true;
179    }
180 
181    /**
182     * This method is called for a general error.
183     * 
184     * @param err
185     *           the error message to report
186     **/
187    public void error(String err) throws XMLException {
188       if (getDocumentLocator() != null) {
189          err += "\n   line: " + getDocumentLocator().getLineNumber();
190       }
191 
192       throw new XMLException(err);
193    }
194 
195    /**
196     * This method is called for a general error.
197     * 
198     * @param ex
199     *           the Exception that caused the error.
200     */
201    public void error(Exception ex) throws XMLException {
202       if (getDocumentLocator() != null) {
203          String err = "An error occured at line: " + getDocumentLocator().getLineNumber();
204          throw new XMLException(err, ex);
205       }
206       throw new XMLException(ex);
207    }
208 
209    /**
210     * This method is called when an illegal Attribute is encountered.
211     * 
212     * @param attName
213     *           the name of the illegal attribute.
214     **/
215    public void illegalAttribute(String attName) throws XMLException {
216       String err = "Illegal attribute '" + attName + "' found on element <" + elementName() + ">.";
217 
218       if (getDocumentLocator() != null) {
219          err += "\n   line: " + getDocumentLocator().getLineNumber();
220       }
221 
222       throw new XMLException(err);
223    }
224 
225    /**
226     * This method is called when an illegal Element is encountered.
227     * 
228     * @param name
229     *           the name of the illegal element
230     **/
231    public void illegalElement(String name) throws XMLException {
232       String err = "Illegal element '" + name + "' found as child of <" + elementName() + ">.";
233 
234       if (getDocumentLocator() != null) {
235          err += "\n   line: " + getDocumentLocator().getLineNumber();
236       }
237 
238       throw new XMLException(err);
239    }
240 
241    /**
242     * This method is called when an element which may only be defined once, is
243     * redefined.
244     * 
245     * @param name
246     *           the name of the element
247     **/
248    public void redefinedElement(String name) throws XMLException {
249       redefinedElement(name, null);
250    }
251 
252    /**
253     * This method is called when an element which may only be defined once, is
254     * redefined.
255     * 
256     * @param name
257     *           the name of the element
258     **/
259    public void redefinedElement(String name, String xtraInfo) throws XMLException {
260       String err = "redefintion of element '" + name + "' within element <" + elementName() + ">.";
261 
262       if (getDocumentLocator() != null) {
263          err += "\n   line: " + getDocumentLocator().getLineNumber();
264       }
265 
266       if (xtraInfo != null) {
267          err += "\n   " + xtraInfo;
268       }
269 
270       throw new XMLException(err + "\n");
271    }
272 
273    /**
274     * This method is called when an out of order element is encountered
275     **/
276    public void outOfOrder(String name) throws XMLException {
277       StringBuffer err = new StringBuffer("out of order element <");
278       err.append(name);
279       err.append("> found in <");
280       err.append(elementName());
281       err.append(">.");
282       throw new XMLException(err.toString());
283    }
284 
285    /**
286     * Converts the given String to an int
287     * 
288     * @param str
289     *           the String to convert to an int
290     * @return the int derived from the given String
291     * @exception IllegalArgumentException
292     *               when the given String does not represent a valid int
293     **/
294    public static int toInt(String str) throws IllegalArgumentException {
295       try {
296          return Integer.parseInt(str);
297       } catch (NumberFormatException nfe) {
298          String err = str + " is not a valid integer. ";
299          throw new IllegalArgumentException(err);
300       }
301    }
302 
303    public Locator getDocumentLocator() {
304       return _documentLocator;
305    }
306 
307    public void setDocumentLocator(Locator documentLocator) {
308       _documentLocator = documentLocator;
309    }
310 
311    /**
312     * Signals to recieve charactes
313     * 
314     * @param chars
315     *           the character array containing the characters
316     * @param start
317     *           the starting index into the character array
318     * @param length
319     *           the number of characters to recieve
320     **/
321    public void characters(char[] chars, int start, int length) throws XMLException {
322       // -- do nothing, this method is overwritten by subclasses
323    }
324 
325    /**
326     * Signals to end of the element with the given name.
327     * 
328     * @param name
329     *           the NCName of the element. It is an error if the name is a QName
330     *           (ie. contains a prefix).
331     * @param namespace
332     *           the namespace of the element.
333     **/
334    public void endElement(String name, String namespace) throws XMLException {
335       // -- do nothing, this method is overwritten by subclasses
336    }
337 
338    /**
339     * Signals the start of an element with the given name.
340     * 
341     * @param name
342     *           the NCName of the element. It is an error if the name is a QName
343     *           (ie. contains a prefix).
344     * @param namespace
345     *           the namespace of the element. This may be null. Note: A null
346     *           namespace is not the same as the default namespace unless the
347     *           default namespace is also null.
348     * @param atts
349     *           the AttributeSet containing the attributes associated with the
350     *           element.
351     * @param nsDecls
352     *           the namespace declarations being declared for this element. This
353     *           may be null.
354     **/
355    public void startElement(String name, String namespace, AttributeSet atts, Namespaces nsDecls) throws XMLException {
356       // -- do nothing, this method is overwritten by subclasses
357    }
358 
359    /**
360     * To set the Castor XML schema context to be used.
361     * 
362     * @param schemaContext
363     *           the Castor XML schema context to be used
364     */
365    public void setSchemaContext(final SchemaContext schemaContext) {
366       _schemaContext = schemaContext;
367    }
368 
369    /**
370     * To get the Castor XML schema context used.
371     * 
372     * @return the Castor XML schema context used
373     */
374    public SchemaContext getSchemaContext() {
375       return _schemaContext;
376    }
377 
378 }