KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jibx > runtime > impl > UnmarshallingContext


1 /*
2 Copyright (c) 2002-2005, Dennis M. Sosnoski.
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification,
6 are permitted provided that the following conditions are met:
7
8  * Redistributions of source code must retain the above copyright notice, this
9    list of conditions and the following disclaimer.
10  * Redistributions in binary form must reproduce the above copyright notice,
11    this list of conditions and the following disclaimer in the documentation
12    and/or other materials provided with the distribution.
13  * Neither the name of JiBX nor the names of its contributors may be used
14    to endorse or promote products derived from this software without specific
15    prior written permission.
16
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
24 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */

28
29 package org.jibx.runtime.impl;
30
31 import java.io.*;
32 import java.util.*;
33
34 import org.jibx.runtime.*;
35 import org.jibx.runtime.IUnmarshaller;
36 import org.jibx.runtime.IUnmarshallingContext;
37 import org.jibx.runtime.JiBXException;
38 import org.xmlpull.v1.*;
39
40 /**
41  * XMLPull parser wrapper supplying convenience methods for access. Most of
42  * these methods are designed for use in code generated by the binding
43  * generator.
44  *
45  * @author Dennis M. Sosnoski
46  * @version 1.0
47  */

48
49 public class UnmarshallingContext implements IUnmarshallingContext
50 {
51     //
52
// Event types reported by nextToken() method
53

54     public static final int START_DOCUMENT = 0;
55     public static final int END_DOCUMENT = 1;
56     public static final int START_TAG = 2;
57     public static final int END_TAG = 3;
58     public static final int TEXT = 4;
59     public static final int CDSECT = 5;
60     public static final int ENTITY_REF = 6;
61     public static final int IGNORABLE_WHITESPACE = 7;
62     public static final int PROCESSING_INSTRUCTION = 8;
63     public static final int COMMENT = 9;
64     public static final int DOCDECL = 10;
65
66     /** Default parser factory name when nothing else found. */
67     protected static final String JavaDoc DEFAULT_PARSER_NAME =
68         "org.xmlpull.mxp1.MXParserFactory";
69     
70     /** Starting size for object stack. */
71     protected static final int INITIAL_STACK_SIZE = 20;
72     
73     /** Empty array of strings. */
74     protected static final String JavaDoc[] EMPTY_STRING_ARRAY = new String JavaDoc[0];
75     
76     /** Factory used for constructing parser instances. */
77     protected static XmlPullParserFactory s_factory;
78     
79     /** Wrapper for supplied input stream. */
80     private InputStreamWrapper m_streamWrapper;
81     
82     /** Parser in use. */
83     protected XmlPullParser m_parser;
84     
85     /** Document name (may be <code>null</code>). */
86     protected String JavaDoc m_docName;
87     
88     //
89
// Structures organized by mapping index number. Each unmarshaller in the
90
// binding definition is assigned a unique index number by the binding
91
// compiler. This includes both generated unmarshallers (from non-abstract
92
// <mapping> definitions) and user-defined unmarshallers. Instances of
93
// the unmarshaller classes are created as needed. The indexes for the
94
// unmarshallers corresponding to named mappings always precede those for
95
// internal mappings in the list.
96

97     /** Unmarshaller classes for mapping definition (<code>null</code> for
98      mappings out of context). */

99     protected String JavaDoc[] m_unmarshallerClasses;
100
101     /** Unmarshallers for classes in mapping definition (lazy create of actual
102      unmarshaller instances) */

103     protected IUnmarshaller[] m_unmarshallers;
104     
105     //
106
// Structures organized by mapping
107

108     /** Namespaces for elements associated with class mappings. */
109     protected String JavaDoc[] m_namespaces;
110
111     /** Names for elements associated with class mappings. */
112     protected String JavaDoc[] m_names;
113
114     /** Number of classes with global unmarshallers. */
115     protected int m_globalCount;
116
117     /** ID maps for finding references. */
118     protected HashMap[] m_idMaps;
119
120     /** Class names of referenced types (<code>null</code> unless class-specific
121      IDs used). */

122     protected String JavaDoc[] m_idClasses;
123     
124     /** Current unmarshalling stack depth. */
125     protected int m_stackDepth;
126     
127     /** Stack of objects being unmarshalled. */
128     protected Object JavaDoc[] m_objectStack;
129
130     /** Mapping from element name to class index. If only a single namespace
131      is defined for a particular local name the value for that name in
132      this table is the Integer index of the associated class. If multiple
133      namespaces are defined using the same local name the value is an
134      ArrayList of Integer indexes. This is a high-overhead construct, so
135      lazy construction is used - it's built the first time needed, then kept
136      up to date thereafter. */

137     protected HashMap m_unmarshalMap;
138
139     /** Wrapped index values used with unmarshalling map. */
140     protected Integer JavaDoc[] m_indexes;
141
142     /** Last IDREF value parsed. */
143     protected String JavaDoc m_idref;
144
145     /**
146      * Constructor. Builds the actual parser and initializes internal data
147      * structures.
148      *
149      * @param nmap number of mapping definitions included
150      * @param umcs names of unmarshaller classes for indexes with fixed
151      * unmarshallers (as opposed to mapping slots, which may be overridden;
152      * reference kept, must be constant)
153      * @param nss namespaces for elements of classes with global definitions
154      * @param names names for elements of classes with global definitions
155      * @param idcs array of class names with IDs (<code>null</code> if no IDs or
156      * global IDs)
157      */

158     public UnmarshallingContext(int nmap, String JavaDoc[] umcs, String JavaDoc[] nss,
159         String JavaDoc[] names, String JavaDoc[] idcs) {
160         
161         // initialize internal unmarshaller state
162
m_globalCount = nss.length;
163         m_unmarshallerClasses = new String JavaDoc[nmap];
164         System.arraycopy(umcs, 0, m_unmarshallerClasses, 0, umcs.length);
165         m_unmarshallers = new IUnmarshaller[nmap];
166         m_namespaces = new String JavaDoc[nmap];
167         System.arraycopy(nss, 0, m_namespaces, 0, nss.length);
168         m_names = new String JavaDoc[nmap];
169         System.arraycopy(names, 0, m_names, 0, names.length);
170         m_idClasses = idcs;
171         int size = idcs == null ? 1 : idcs.length;
172         m_idMaps = new HashMap[size];
173         m_objectStack = new Object JavaDoc[INITIAL_STACK_SIZE];
174     }
175
176     /**
177      * Default constructor. This can be used for creating a context outside of
178      * the generated code for special purposes.
179      */

180     public UnmarshallingContext() {
181         this(0, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY,
182             EMPTY_STRING_ARRAY);
183     }
184
185     /**
186      * Create parser if one does not already exist.
187      *
188      * @param nsa enable namespace processing by parser flag
189      * @throws JiBXException if error creating parser
190      */

191     private void createParser(boolean nsa) throws JiBXException {
192         if (m_parser == null) {
193             try {
194                 
195                 // check parser factory needed (threadsafe since no conflict)
196
if (s_factory == null) {
197                     
198                     // first try getting factory defined by property value
199
ClassLoader JavaDoc loader = Thread.currentThread().
200                         getContextClassLoader();
201                     if (loader == null) {
202                         loader = UnmarshallingContext.class.getClassLoader();
203                     }
204                     try {
205                         String JavaDoc name = System.getProperty
206                             (XmlPullParserFactory.PROPERTY_NAME);
207                         if (name != null && (name = name.trim()).length() > 0) {
208                             s_factory = XmlPullParserFactory.newInstance(name,
209                                 loader.getClass());
210                         }
211                     } catch (Exception JavaDoc ex) { /* deliberately empty */ }
212                     
213                     // if no luck that way, try getting it directly
214
if (s_factory == null) {
215                         try {
216                             s_factory = XmlPullParserFactory.newInstance();
217                         } catch (Exception JavaDoc ex) { /* deliberately empty */ }
218                         if (s_factory == null) {
219                             try {
220                                 s_factory = XmlPullParserFactory.newInstance
221                                     (DEFAULT_PARSER_NAME, loader.getClass());
222                             } catch (Exception JavaDoc ex) {
223                                 throw new JiBXException
224                                     ("Unable to create parser", ex);
225                             }
226                         }
227                     }
228                     
229                     // enable namespace handling for parser
230
s_factory.setNamespaceAware(nsa);
231                 }
232                 m_parser = s_factory.newPullParser();
233                 
234             } catch (XmlPullParserException ex) {
235                 throw new JiBXException("Error creating parser", ex);
236             }
237         }
238     }
239
240     /**
241      * Build name with optional namespace. Just returns the appropriate
242      * name format.
243      *
244      * @param ns namespace URI of name
245      * @param name local name part of name
246      * @return formatted name string
247      */

248     public static String JavaDoc buildNameString(String JavaDoc ns, String JavaDoc name) {
249         if (ns == null || "".equals(ns)) {
250             return "\"" + name + "\"";
251         } else {
252             return "\"{" + ns + "}" + name + "\"";
253         }
254     }
255
256     /**
257      * Build current element name, with optional namespace.
258      *
259      * @return formatted name string
260      */

261     public String JavaDoc currentNameString() {
262         return buildNameString(m_parser.getNamespace(), m_parser.getName());
263     }
264
265     /**
266      * Build current parse input position description.
267      *
268      * @return text description of current parse position
269      */

270     public String JavaDoc buildPositionString() {
271         String JavaDoc base = "(line " + m_parser.getLineNumber() + ", col " +
272             m_parser.getColumnNumber();
273         if (m_docName != null) {
274             base += ", in " + m_docName;
275         }
276         return base + ')';
277     }
278
279     /**
280      * Throw exception for expected element start tag not found.
281      *
282      * @param ns namespace URI of name
283      * @param name local name part of name
284      * @exception JiBXException always thrown
285      */

286     public void throwStartTagNameError(String JavaDoc ns, String JavaDoc name)
287         throws JiBXException {
288         throw new JiBXException("Expected " + buildNameString(ns, name) +
289             " start tag, found " + currentNameString() + " start tag " +
290             buildPositionString());
291     }
292
293     /**
294      * Throw exception for expected element end tag not found.
295      *
296      * @param ns namespace URI of name
297      * @param name local name part of name
298      * @exception JiBXException always thrown
299      */

300     public void throwEndTagNameError(String JavaDoc ns, String JavaDoc name)
301         throws JiBXException {
302         throw new JiBXException("Expected " + buildNameString(ns, name) +
303             " end tag, found " + currentNameString() + " end tag " +
304             buildPositionString());
305     }
306
307     /**
308      * Advance to next parse item. This wraps the base parser call in order to
309      * catch and handle exceptions.
310      *
311      * @exception JiBXException on any error (possibly wrapping other exception)
312      */

313     private void advance() throws JiBXException {
314         try {
315             m_parser.nextToken();
316         } catch (IOException ex) {
317             throw new JiBXException("Error accessing document", ex);
318         } catch (XmlPullParserException ex) {
319             throw new JiBXException
320                 ("Error parsing document " + buildPositionString(), ex);
321         }
322     }
323
324     /**
325      * Verify namespace. This is a simple utility method that allows multiple
326      * representations for the empty namespace as a convenience for generated
327      * code.
328      *
329      * @param ns namespace URI expected (may be <code>null</code>
330      * or the empty string for the empty namespace)
331      * @return <code>true</code> if the current namespace matches that
332      * expected, <code>false</code> if not
333      */

334     private boolean verifyNamespace(String JavaDoc ns) {
335         if (ns == null || "".equals(ns)) {
336             return m_parser.getNamespace().length() == 0;
337         } else {
338             return ns.equals(m_parser.getNamespace());
339         }
340     }
341
342     /**
343      * Get attribute value from parser.
344      *
345      * @param ns namespace URI for expected attribute (may be <code>null</code>
346      * or the empty string for the empty namespace)
347      * @param name attribute name expected
348      * @return attribute value text, or <code>null</code> if missing
349      */

350     private String JavaDoc getAttributeValue(String JavaDoc ns, String JavaDoc name) {
351         if (ns == null) {
352             return m_parser.getAttributeValue("", name);
353         } else {
354             return m_parser.getAttributeValue(ns, name);
355         }
356     }
357
358     /**
359      * Set document to be parsed from stream. This call is not part of the
360      * interface definition, but is supplied to allow direct control of the
361      * namespace processing by the compiler. The option of disabling namespaces
362      * should be considered experimental and may not be supported in the future.
363      *
364      * @param ins stream supplying document data
365      * @param enc document input encoding, or <code>null</code> if to be
366      * determined by parser
367      * @param nsa enable namespace processing for parser flag
368      * @throws JiBXException if error creating parser
369      */

370     public void setDocument(InputStream ins, String JavaDoc enc, boolean nsa)
371         throws JiBXException {
372         try {
373             createParser(nsa);
374             if (m_streamWrapper == null) {
375                 m_streamWrapper = new InputStreamWrapper();
376             }
377             m_streamWrapper.setInput(ins, enc);
378             m_parser.setInput(m_streamWrapper.getReader());
379             reset();
380         } catch (XmlPullParserException e) {
381             throw new JiBXException("Error setting document", e);
382         } catch (IOException e) {
383             throw new JiBXException("Error initializing input stream", e);
384         }
385     }
386
387     /**
388      * Set document to be parsed from stream.
389      *
390      * @param ins stream supplying document data
391      * @param enc document input encoding, or <code>null</code> if to be
392      * determined by parser
393      * @throws JiBXException if error creating parser
394      */

395     public void setDocument(InputStream ins, String JavaDoc enc) throws JiBXException {
396         setDocument(ins, enc, true);
397     }
398
399     /**
400      * Set document to be parsed from reader. This call is not part of the
401      * interface definition, but is supplied to allow direct control of the
402      * namespace processing by the compiler. The option of disabling namespaces
403      * should be considered experimental and may not be supported in the future.
404      *
405      * @param rdr reader supplying document data
406      * @param nsa enable namespace processing for parser flag
407      * @throws JiBXException if error creating parser
408      */

409     public void setDocument(Reader rdr, boolean nsa) throws JiBXException {
410         try {
411             createParser(nsa);
412             m_parser.setInput(rdr);
413             reset();
414         } catch (XmlPullParserException ex) {
415             throw new JiBXException("Error setting document", ex);
416         }
417     }
418
419     /**
420      * Set document to be parsed from reader.
421      *
422      * @param rdr reader supplying document data
423      * @throws JiBXException if error creating parser
424      */

425     public void setDocument(Reader rdr) throws JiBXException {
426         setDocument(rdr, true);
427     }
428
429     /**
430      * Set named document to be parsed from stream.
431      *
432      * @param ins stream supplying document data
433      * @param name document name
434      * @param enc document input encoding, or <code>null</code> if to be
435      * determined by parser
436      * @throws JiBXException if error creating parser
437      */

438     public void setDocument(InputStream ins, String JavaDoc name, String JavaDoc enc)
439         throws JiBXException {
440         setDocument(ins, enc);
441         m_docName = name;
442     }
443
444     /**
445      * Set named document to be parsed from reader.
446      *
447      * @param rdr reader supplying document data
448      * @param name document name
449      * @throws JiBXException if error creating parser
450      */

451     public void setDocument(Reader rdr, String JavaDoc name) throws JiBXException {
452         setDocument(rdr);
453         m_docName = name;
454     }
455
456     /**
457      * Initializes the context to use the same parser and document as another
458      * unmarshalling context. This method is designed for use when an initial
459      * context needs to create and invoke a secondary context in the course of
460      * an unmarshalling operation.
461      *
462      * @param parent context supplying parser and document to be unmarshalled
463      */

464     public void setFromContext(UnmarshallingContext parent) {
465         m_parser = parent.m_parser;
466         m_docName = parent.m_docName;
467     }
468
469     /**
470      * Reset unmarshalling information. This releases all references to
471      * unmarshalled objects and prepares the context for potential reuse.
472      * It is automatically called when input is set.
473      */

474     public void reset() {
475         for (int i = 0; i < m_idMaps.length; i++) {
476             m_idMaps[i] = null;
477         }
478         for (int i = m_globalCount; i < m_unmarshallers.length; i++) {
479             m_namespaces[i] = null;
480             m_names[i] = null;
481             m_unmarshallers[i] = null;
482         }
483         m_unmarshalMap = null;
484         m_idref = null;
485         for (int i = 0; i < m_objectStack.length; i++) {
486             m_objectStack[i] = null;
487         }
488         m_stackDepth = 0;
489     }
490
491     /**
492      * Parse to start tag. Ignores character data seen prior to a start tag, but
493      * throws exception if an end tag or the end of the document is seen before
494      * a start tag. Leaves the parser positioned at the start tag.
495      *
496      * @return element name of start tag found
497      * @throws JiBXException on any error (possibly wrapping other exception)
498      */

499     public String JavaDoc toStart() throws JiBXException {
500         try {
501             if (m_parser.getEventType() == XmlPullParser.START_TAG) {
502                 return m_parser.getName();
503             }
504             while (true) {
505                 m_parser.next();
506                 switch (m_parser.getEventType()) {
507
508                     case XmlPullParser.START_TAG:
509                         return m_parser.getName();
510
511                     case XmlPullParser.END_TAG:
512                         throw new JiBXException("Expected start tag, " +
513                             "found end tag " + currentNameString() +
514                             " " + buildPositionString());
515
516                     case XmlPullParser.END_DOCUMENT:
517                         throw new JiBXException("Expected start tag, " +
518                             "found end of document " + buildPositionString());
519
520                 }
521             }
522         } catch (IOException ex) {
523             throw new JiBXException("Error accessing document", ex);
524         } catch (XmlPullParserException ex) {
525             throw new JiBXException
526                 ("Error parsing document " + buildPositionString(), ex);
527         }
528     }
529
530     /**
531      * Parse to end tag. Ignores character data seen prior to an end tag, but
532      * throws exception if a start tag or the end of the document is seen before
533      * an end tag. Leaves the parser positioned at the end tag.
534      *
535      * @return element name of end tag found
536      * @throws JiBXException on any error (possibly wrapping other exception)
537      */

538     public String JavaDoc toEnd() throws JiBXException {
539         try {
540             if (m_parser.getEventType() == XmlPullParser.END_TAG) {
541                 return m_parser.getName();
542             }
543             while (true) {
544                 m_parser.next();
545                 switch (m_parser.getEventType()) {
546
547                     case XmlPullParser.START_TAG:
548                         throw new JiBXException("Expected end tag, " +
549                             "found start tag " + currentNameString() +
550                             " " + buildPositionString());
551
552                     case XmlPullParser.END_TAG:
553                         return m_parser.getName();
554
555                     case XmlPullParser.END_DOCUMENT:
556                         throw new JiBXException("Expected end tag, " +
557                             "found end of document " + buildPositionString());
558
559                 }
560             }
561         } catch (IOException ex) {
562             throw new JiBXException("Error accessing document", ex);
563         } catch (XmlPullParserException ex) {
564             throw new JiBXException
565                 ("Error parsing document " + buildPositionString(), ex);
566         }
567     }
568
569     /**
570      * Parse to start or end tag. If not currently positioned at a start or end
571      * tag this first advances the parse to the next start or end tag.
572      *
573      * @return parser event type for start tag or end tag
574      * @throws JiBXException on any error (possibly wrapping other exception)
575      */

576     public int toTag() throws JiBXException {
577         try {
578             int type = m_parser.getEventType();
579             while (type != XmlPullParser.START_TAG &&
580                 type != XmlPullParser.END_TAG) {
581                 type = m_parser.next();
582             }
583             return m_parser.getEventType();
584         } catch (IOException ex) {
585             throw new JiBXException("Error accessing document", ex);
586         } catch (XmlPullParserException ex) {
587             throw new JiBXException
588                 ("Error parsing document " + buildPositionString(), ex);
589         }
590     }
591
592     /**
593      * Check if next tag is start of element. If not currently positioned at a
594      * start or end tag this first advances the parse to the next start or end
595      * tag.
596      *
597      * @param ns namespace URI for expected element (may be <code>null</code>
598      * or the empty string for the empty namespace)
599      * @param name element name expected
600      * @return <code>true</code> if at start of element with supplied name,
601      * <code>false</code> if not
602      * @throws JiBXException on any error (possibly wrapping other exception)
603      */

604     public boolean isAt(String JavaDoc ns, String JavaDoc name) throws JiBXException {
605         try {
606             int type = m_parser.getEventType();
607             while (type != XmlPullParser.START_TAG &&
608                 type != XmlPullParser.END_TAG) {
609                 type = m_parser.next();
610             }
611             return m_parser.getEventType() == XmlPullParser.START_TAG &&
612                 m_parser.getName().equals(name) && verifyNamespace(ns);
613         } catch (IOException ex) {
614             throw new JiBXException("Error accessing document", ex);
615         } catch (XmlPullParserException ex) {
616             throw new JiBXException
617                 ("Error parsing document " + buildPositionString(), ex);
618         }
619     }
620
621     /**
622      * Check if attribute is present on current start tag. Throws an exception
623      * if not currently positioned on a start tag.
624      *
625      * @param ns namespace URI for expected attribute (may be <code>null</code>
626      * or the empty string for the empty namespace)
627      * @param name attribute name expected
628      * @return <code>true</code> if named attribute is present,
629      * <code>false</code> if not
630      * @throws JiBXException on any error (possibly wrapping other exception)
631      */

632     public boolean hasAttribute(String JavaDoc ns, String JavaDoc name) throws JiBXException {
633         try {
634             if (m_parser.getEventType() == XmlPullParser.START_TAG) {
635                 return getAttributeValue(ns, name) != null;
636             } else {
637                 throw new JiBXException("Error parsing document " +
638                     buildPositionString());
639             }
640         } catch (XmlPullParserException ex) {
641             throw new JiBXException
642                 ("Error parsing document " + buildPositionString(), ex);
643         }
644     }
645
646     /**
647      * Check if any of several attributes is present on current start tag.
648      * Throws an exception if not currently positioned on a start tag.
649      *
650      * @param nss namespace URIs for expected attributes (each may be
651      * <code>null</code> or the empty string for the empty namespace)
652      * @param names attribute names expected
653      * @return <code>true</code> if at least one of the named attributes is
654      * present, <code>false</code> if not
655      * @throws JiBXException on any error (possibly wrapping other exception)
656      */

657     public boolean hasAnyAttribute(String JavaDoc[] nss, String JavaDoc[] names)
658         throws JiBXException {
659         try {
660             if (m_parser.getEventType() == XmlPullParser.START_TAG) {
661                 for (int i = 0; i < names.length; i++) {
662                     if (getAttributeValue(nss[i], names[i]) != null) {
663                         return true;
664                     }
665                 }
666                 return false;
667             } else {
668                 throw new JiBXException("Error parsing document " +
669                     buildPositionString());
670             }
671         } catch (XmlPullParserException ex) {
672             throw new JiBXException
673                 ("Error parsing document " + buildPositionString(), ex);
674         }
675     }
676
677     /**
678      * Check that only allowed attributes are present on current start tag.
679      * Throws an exception if not currently positioned on a start tag, or if
680      * an attribute is present which is not in the list.
681      *
682      * @param nss namespace URIs for allowed attributes (each may be
683      * <code>null</code> or the empty string for the empty namespace)
684      * @param names alphabetical list of attribute names expected (duplicates
685      * names are ordered by namespace URI)
686      * @throws JiBXException on any error (possibly wrapping other exception)
687      */

688     public void checkAllowedAttributes(String JavaDoc[] nss, String JavaDoc[] names)
689         throws JiBXException {
690         try {
691             if (m_parser.getEventType() == XmlPullParser.START_TAG) {
692                 int count = m_parser.getAttributeCount();
693                 loop: for (int i = 0; i < count; i++) {
694                     String JavaDoc name = m_parser.getAttributeName(i);
695                     String JavaDoc ns = m_parser.getAttributeNamespace(i);
696                     int base = 0;
697                     int limit = names.length - 1;
698                     while (base <= limit) {
699                         int cur = (base + limit) >> 1;
700                         int diff = name.compareTo(names[cur]);
701                         if (diff == 0) {
702                             String JavaDoc comp = nss[cur];
703                             if (comp == null) {
704                                 diff = ns.compareTo("");
705                             } else {
706                                 diff = ns.compareTo(comp);
707                             }
708                             if (diff == 0) {
709                                 continue loop;
710                             }
711                         }
712                         if (diff < 0) {
713                             limit = cur - 1;
714                         } else if (diff > 0) {
715                             base = cur + 1;
716                         }
717                     }
718                     throwStartTagException("Illegal attribute " +
719                         buildNameString(ns, name));
720                 }
721             } else {
722                 throw new JiBXException("Error parsing document " +
723                     buildPositionString());
724             }
725         } catch (XmlPullParserException ex) {
726             throw new JiBXException
727                 ("Error parsing document " + buildPositionString(), ex);
728         }
729     }
730
731     /**
732      * Parse to start of element. Ignores
733      * character data to next start or end tag, but throws exception if an
734      * end tag is seen before a start tag, or if the start tag seen does
735      * not match the expected name. Leaves the parse positioned at the
736      * start tag.
737      *
738      * @param ns namespace URI for expected element (may be <code>null</code>
739      * or the empty string for the empty namespace)
740      * @param name element name expected
741      * @throws JiBXException on any error (possibly wrapping other exception)
742      */

743     public void parseToStartTag(String JavaDoc ns, String JavaDoc name) throws JiBXException {
744         if (toStart().equals(name) && verifyNamespace(ns)) {
745             return;
746         } else {
747             throwStartTagNameError(ns, name);
748         }
749     }
750
751     /**
752      * Parse past start of element. Ignores
753      * character data to next start or end tag, but throws exception if an
754      * end tag is seen before a start tag, or if the start tag seen does
755      * not match the expected name. Leaves the parse positioned following
756      * the start tag.
757      *
758      * @param ns namespace URI for expected element (may be <code>null</code>
759      * or the empty string for the empty namespace)
760      * @param name element name expected
761      * @throws JiBXException on any error (possibly wrapping other exception)
762      */

763     public void parsePastStartTag(String JavaDoc ns, String JavaDoc name) throws JiBXException {
764         if (toStart().equals(name) && verifyNamespace(ns)) {
765             advance();
766         } else {
767             throwStartTagNameError(ns, name);
768         }
769     }
770
771     /**
772      * Parse past start of element. Ignores character data to next start or end
773      * tag, but throws exception if an end tag is seen before a start tag, or if
774      * the start tag seen does not match the expected name. Leaves the parse
775      * positioned following the start tag.
776      *
777      * @param ns namespace URI for expected element (may be <code>null</code>
778      * or the empty string for the empty namespace)
779      * @param name element name expected
780      * @throws JiBXException on any error (possibly wrapping other exception)
781      */

782     public boolean parseIfStartTag(String JavaDoc ns, String JavaDoc name)
783         throws JiBXException {
784         if (isAt(ns, name)) {
785             advance();
786             return true;
787         } else {
788             return false;
789         }
790     }
791
792     /**
793      * Parse past end of element. Ignores
794      * character data to next start or end tag, but throws exception if a
795      * start tag is seen before a end tag, or if the end tag seen does
796      * not match the expected name. Leaves the parse positioned following
797      * the end tag.
798      *
799      * @param ns namespace URI for expected element (may be <code>null</code>
800      * or the empty string for the empty namespace)
801      * @param name element name expected
802      * @throws JiBXException on any error (possibly wrapping other exception)
803      */

804     public void parsePastEndTag(String JavaDoc ns, String JavaDoc name) throws JiBXException {
805         if (toEnd().equals(name) && verifyNamespace(ns)) {
806             advance();
807         } else {
808             throwEndTagNameError(ns, name);
809         }
810     }
811
812     /**
813      * Check if next tag is an end tag. If not currently positioned at a
814      * start or end tag this first advances the parse to the next start or
815      * end tag.
816      *
817      * @return <code>true</code> if at end of element, <code>false</code> if
818      * at start
819      * @throws JiBXException on any error (possibly wrapping other exception)
820      */

821     public boolean isEnd() throws JiBXException {
822         try {
823             int type = m_parser.getEventType();
824             while (type != XmlPullParser.START_TAG &&
825                 type != XmlPullParser.END_TAG) {
826                 type = m_parser.next();
827             }
828             return m_parser.getEventType() == XmlPullParser.END_TAG;
829         } catch (IOException ex) {
830             throw new JiBXException("Error accessing document", ex);
831         } catch (XmlPullParserException ex) {
832             throw new JiBXException
833                 ("Error parsing document " + buildPositionString(), ex);
834         }
835     }
836     
837     /**
838      * Accumulate text content. This skips past comments and processing
839      * instructions, and consolidates text and entities to a single string. Any
840      * unexpanded entity references found are treated as errors.
841      *
842      * @return consolidated text string (empty string if no text components)
843      * @exception JiBXException on error in unmarshalling
844      */

845     public String JavaDoc accumulateText() throws JiBXException {
846         try {
847             String JavaDoc text = null;
848             StringBuffer JavaDoc buff = null;
849             loop: while (true) {
850                 switch (m_parser.getEventType()) {
851
852                     case XmlPullParser.ENTITY_REF:
853                         if (m_parser.getText() == null) {
854                             throw new JiBXException
855                                 ("Unexpanded entity reference in text at " +
856                                 buildPositionString());
857                         }
858                         // fall through into text accumulation
859

860                     case XmlPullParser.CDSECT:
861                     case XmlPullParser.TEXT:
862                         if (text == null) {
863                             text = m_parser.getText();
864                         } else {
865                             if (buff == null) {
866                                 buff = new StringBuffer JavaDoc(text);
867                             }
868                             buff.append(m_parser.getText());
869                         }
870                         break;
871
872                     case XmlPullParser.END_TAG:
873                     case XmlPullParser.START_TAG:
874                     case XmlPullParser.END_DOCUMENT:
875                         break loop;
876
877                     default:
878                         break;
879
880                 }
881                 m_parser.nextToken();
882             }
883             if (buff == null) {
884                 return (text == null) ? "" : text;
885             } else {
886                 return buff.toString();
887             }
888         } catch (IOException ex) {
889             throw new JiBXException("Error accessing document", ex);
890         } catch (XmlPullParserException ex) {
891             throw new JiBXException
892                 ("Error parsing document " + buildPositionString(), ex);
893         }
894     }
895
896     /**
897      * Parse required text content. Assumes the parse is already positioned at
898      * the text content, so just returns the text.
899      *
900      * @return content text found
901      * @throws JiBXException on any error (possible wrapping other exception)
902      */

903     public String JavaDoc parseContentText() throws JiBXException {
904         return accumulateText();
905     }
906
907     /**
908      * Parse past end of element, returning optional text content. Assumes
909      * you've already parsed past the start tag of the element, so it just looks
910      * for text content followed by the end tag, and returns with the parser
911      * positioned after the end tag.
912      *
913      * @param ns namespace URI for expected element (may be <code>null</code>
914      * or the empty string for the empty namespace)
915      * @param tag element name expected
916      * @return content text from element
917      * @throws JiBXException on any error (possible wrapping other exception)
918      */

919     public String JavaDoc parseContentText(String JavaDoc ns, String JavaDoc tag)
920         throws JiBXException {
921         try {
922             String JavaDoc text = accumulateText();
923             switch (m_parser.getEventType()) {
924
925                 case XmlPullParser.END_TAG:
926                     if (m_parser.getName().equals(tag) &&
927                         verifyNamespace(ns)) {
928                         m_parser.nextToken();
929                         return text;
930                     } else {
931                         throwEndTagNameError(ns, tag);
932                     }
933
934                 case XmlPullParser.START_TAG:
935                     throw new JiBXException("Expected " +
936                         buildNameString(ns, tag) + " end tag, " +
937                         "found " + currentNameString() + " start tag " +
938                         buildPositionString());
939
940                 case XmlPullParser.END_DOCUMENT:
941                     throw new JiBXException("Expected " +
942                         buildNameString(ns, tag) + " end tag, " +
943                         "found end of document " + buildPositionString());
944
945             }
946             return null;
947         } catch (IOException ex) {
948             throw new JiBXException("Error accessing document", ex);
949         } catch (XmlPullParserException ex) {
950             throw new JiBXException
951                 ("Error parsing document " + buildPositionString(), ex);
952         }
953     }
954
955     /**
956      * Parse past end of element, returning integer value of
957      * content. Assumes you've already parsed past the start tag of the
958      * element, so it just looks for text content followed by the end tag.
959      *
960      * @param ns namespace URI for expected element (may be <code>null</code>
961      * or the empty string for the empty namespace)
962      * @param tag element name expected
963      * @return converted value from element text
964      * @throws JiBXException on any error (possible wrapping other exception)
965      */

966     public int parseContentInt(String JavaDoc ns, String JavaDoc tag) throws JiBXException {
967         String JavaDoc text = parseContentText(ns, tag);
968         try {
969             return Utility.parseInt(text);
970         } catch (JiBXException ex) {
971             throw new JiBXException(ex.getMessage() + ' ' +
972                 buildPositionString(), ex.getRootCause());
973         }
974     }
975
976     /**
977      * Parse entire element, returning text content.
978      * Expects to find the element start tag, text content, and end tag,
979      * in that order, and returns with the parser positioned following
980      * the end tag.
981      *
982      * @param ns namespace URI for expected element (may be <code>null</code>
983      * or the empty string for the empty namespace)
984      * @param tag element name expected
985      * @return content text from element
986      * @throws JiBXException on any error (possible wrapping other exception)
987      */

988     public String JavaDoc parseElementText(String JavaDoc ns, String JavaDoc tag) throws JiBXException {
989         parsePastStartTag(ns, tag);
990         return parseContentText(ns, tag);
991     }
992
993     /**
994      * Parse entire element, returning optional text content.
995      * Expects to find the element start tag, text content, and end tag,
996      * in that order, and returns with the parser positioned following
997      * the end tag. Returns the default text if the element is not found.
998      *
999      * @param ns namespace URI for expected element (may be <code>null</code>
1000     * or the empty string for the empty namespace)
1001     * @param tag element name expected
1002     * @param dflt default text value
1003     * @return content text from element
1004     * @throws JiBXException on any error (possible wrapping other exception)
1005     */

1006    public String JavaDoc parseElementText(String JavaDoc ns, String JavaDoc tag, String JavaDoc dflt)
1007        throws JiBXException {
1008        if (parseIfStartTag(ns, tag)) {
1009            return parseContentText(ns, tag);
1010        } else {
1011            return dflt;
1012        }
1013    }
1014
1015    /**
1016     * Get text value of attribute from current start tag.
1017     * Throws an exception if the attribute value is not found in the start
1018     * tag.
1019     *
1020     * @param ns namespace URI for expected attribute (may be <code>null</code>
1021     * or the empty string for the empty namespace)
1022     * @param name attribute name expected
1023     * @return attribute value text
1024     * @throws JiBXException if attribute not present
1025     */

1026    public String JavaDoc attributeText(String JavaDoc ns, String JavaDoc name) throws JiBXException {
1027        String JavaDoc value = getAttributeValue(ns, name);
1028        if (value == null) {
1029            throw new JiBXException("Missing required attribute " +
1030                buildNameString(ns, name) + " " + buildPositionString());
1031        } else {
1032            return value;
1033        }
1034    }
1035
1036    /**
1037     * Get text value of optional attribute from current start
1038     * tag. If the attribute is not present the supplied default value is
1039     * returned instead.
1040     *
1041     * @param ns namespace URI for expected attribute (may be <code>null</code>
1042     * or the empty string for the empty namespace)
1043     * @param name attribute name expected
1044     * @param dflt value to be returned if attribute is not present
1045     * @return attribute value text
1046     */

1047    public String JavaDoc attributeText(String JavaDoc ns, String JavaDoc name, String JavaDoc dflt) {
1048        String JavaDoc value = getAttributeValue(ns, name);
1049        if (value == null) {
1050            return dflt;
1051        } else {
1052            return value;
1053        }
1054    }
1055
1056    /**
1057     * Find the object corresponding to an ID. This method just handles the
1058     * lookup and checks the object type.
1059     *
1060     * @param id ID text
1061     * @param index expected reference type index
1062     * @return object corresponding to IDREF, or <code>null</code> if not
1063     * yet defined
1064     * @throws JiBXException on any error
1065     */

1066    public Object JavaDoc findID(String JavaDoc id, int index) throws JiBXException {
1067        HashMap map = m_idMaps[index];
1068        if (map != null) {
1069            Object JavaDoc obj = map.get(id);
1070            if (obj == null || obj instanceof BackFillHolder) {
1071                return null;
1072            } else if (m_idClasses == null ||
1073                m_idClasses[index].equals(obj.getClass().getName())) {
1074                return obj;
1075            } else {
1076                throwStartTagException
1077                    ("IDREF element content mapped to wrong type");
1078            }
1079        }
1080        return null;
1081    }
1082
1083    /**
1084     * Find previously defined object corresponding to an ID. This does the
1085     * lookup and checks that the referenced object has been defined.
1086     *
1087     * @param id ID text
1088     * @param index expected reference type index
1089     * @return object corresponding to IDREF
1090     * @throws JiBXException on any error
1091     */

1092    public Object JavaDoc findDefinedID(String JavaDoc id, int index) throws JiBXException {
1093        Object JavaDoc obj = findID(id, index);
1094        if (obj == null) {
1095            throwStartTagException("ID " + id + " not defined");
1096        }
1097        return obj;
1098    }
1099
1100    /**
1101     * Parse entire element, returning object (if defined yet) corresponding
1102     * to content interpreted as IDREF. Expects to find the element start tag,
1103     * text content, and end tag, in that order, and returns with the parser
1104     * positioned following the end tag.
1105     *
1106     * @param ns namespace URI for expected element (may be <code>null</code>
1107     * or the empty string for the empty namespace)
1108     * @param tag attribute name expected
1109     * @param index expected reference type index
1110     * @return object corresponding to IDREF, or <code>null</code> if not
1111     * yet defined
1112     * @throws JiBXException on any error (possibly wrapping other exception)
1113     */

1114    public Object JavaDoc parseElementForwardIDREF(String JavaDoc ns, String JavaDoc tag, int index)
1115        throws JiBXException {
1116        parsePastStartTag(ns, tag);
1117        m_idref = parseContentText(ns, tag);
1118        return findID(m_idref, index);
1119    }
1120
1121    /**
1122     * Get object (if defined yet) corresponding to IDREF attribute from
1123     * current start tag.
1124     *
1125     * @param ns namespace URI for expected attribute (may be <code>null</code>
1126     * or the empty string for the empty namespace)
1127     * @param name attribute name expected
1128     * @param index expected reference type index
1129     * @return object corresponding to IDREF, or <code>null</code> if not
1130     * yet defined
1131     * @throws JiBXException if attribute not present, or ID mapped to a
1132     * different type of object than expected
1133     */

1134    public Object JavaDoc attributeForwardIDREF(String JavaDoc ns, String JavaDoc name, int index)
1135        throws JiBXException {
1136        m_idref = attributeText(ns, name);
1137        return findID(m_idref, index);
1138    }
1139
1140    /**
1141     * Parse entire element, returning previously defined object corresponding
1142     * to content interpreted as IDREF. Expects to find the element start tag,
1143     * text content, and end tag, in that order, and returns with the parser
1144     * positioned following the end tag.
1145     *
1146     * @param ns namespace URI for expected element (may be <code>null</code>
1147     * or the empty string for the empty namespace)
1148     * @param tag attribute name expected
1149     * @param index expected reference type index
1150     * @return object corresponding to IDREF
1151     * @throws JiBXException if attribute not present, ID not defined, or
1152     * mapped to a different type of object than expected
1153     */

1154    public Object JavaDoc parseElementExistingIDREF(String JavaDoc ns, String JavaDoc tag, int index)
1155        throws JiBXException {
1156        parsePastStartTag(ns, tag);
1157        m_idref = parseContentText(ns, tag);
1158        return findDefinedID(m_idref, index);
1159    }
1160
1161    /**
1162     * Get previously defined object corresponding to IDREF attribute from
1163     * current start tag.
1164     *
1165     * @param ns namespace URI for expected attribute (may be <code>null</code>
1166     * or the empty string for the empty namespace)
1167     * @param name attribute name expected
1168     * @param index expected reference type index
1169     * @return object corresponding to IDREF
1170     * @throws JiBXException if attribute not present, ID not defined, or
1171     * mapped to a different type of object than expected
1172     */

1173    public Object JavaDoc attributeExistingIDREF(String JavaDoc ns, String JavaDoc name, int index)
1174        throws JiBXException {
1175        m_idref = attributeText(ns, name);
1176        return findDefinedID(m_idref, index);
1177    }
1178
1179    /**
1180     * Get integer value of attribute from current start tag.
1181     * Throws an exception if the attribute is not found in the start
1182     * tag, or if it is not a valid integer value.
1183     *
1184     * @param ns namespace URI for expected attribute (may be <code>null</code>
1185     * or the empty string for the empty namespace)
1186     * @param name attribute name expected
1187     * @return attribute integer value
1188     * @throws JiBXException if attribute not present or not a valid integer
1189     * value
1190     */

1191    public int attributeInt(String JavaDoc ns, String JavaDoc name) throws JiBXException {
1192        String JavaDoc text = attributeText(ns, name);
1193        try {
1194            return Utility.parseInt(text);
1195        } catch (JiBXException ex) {
1196            throw new JiBXException(ex.getMessage() + ' ' +
1197                buildPositionString(), ex.getRootCause());
1198        }
1199    }
1200
1201    /**
1202     * Get integer value of optional attribute from current
1203     * start tag. If the attribute is not present the supplied default value
1204     * is returned instead.
1205     *
1206     * @param ns namespace URI for expected attribute (may be <code>null</code>
1207     * or the empty string for the empty namespace)
1208     * @param name attribute name expected
1209     * @param dflt value to be returned if attribute is not present
1210     * @return attribute integer value
1211     * @throws JiBXException if attribute value is not a valid integer
1212     */

1213    public int attributeInt(String JavaDoc ns, String JavaDoc name, int dflt)
1214        throws JiBXException {
1215        String JavaDoc value = getAttributeValue(ns, name);
1216        if (value == null) {
1217            return dflt;
1218        } else {
1219            try {
1220                return Utility.parseInt(value);
1221            } catch (JiBXException ex) {
1222                throw new JiBXException(ex.getMessage() + ' ' +
1223                    buildPositionString(), ex.getRootCause());
1224            }
1225        }
1226    }
1227
1228    /**
1229     * Parse entire element, returning integer value of content.
1230     * Expects to find the element start tag, text content, and end tag,
1231     * in that order, and returns with the parser positioned following
1232     * the end tag.
1233     *
1234     * @param ns namespace URI for expected element (may be <code>null</code>
1235     * or the empty string for the empty namespace)
1236     * @param tag element name expected
1237     * @return content text from element
1238     * @throws JiBXException on any error (possibly wrapping other exception)
1239     */

1240    public int parseElementInt(String JavaDoc ns, String JavaDoc tag) throws JiBXException {
1241        parsePastStartTag(ns, tag);
1242        return parseContentInt(ns, tag);
1243    }
1244
1245    /**
1246     * Parse entire optional element, returning integer value of content.
1247     * Expects to find the element start tag, text content, and end tag,
1248     * in that order, and returns with the parser positioned following
1249     * the end tag. Returns the default value if the element is missing or
1250     * has no content.
1251     *
1252     * @param ns namespace URI for expected element (may be <code>null</code>
1253     * or the empty string for the empty namespace)
1254     * @param tag element name expected
1255     * @param dflt default value
1256     * @return content text from element
1257     * @throws JiBXException on any error (possibly wrapping other exception)
1258     */

1259    public int parseElementInt(String JavaDoc ns, String JavaDoc tag, int dflt)
1260        throws JiBXException {
1261        if (parseIfStartTag(ns, tag)) {
1262            return parseContentInt(ns, tag);
1263        } else {
1264            return dflt;
1265        }
1266    }
1267
1268    /**
1269     * Find required text value in enumeration. Looks up and returns the
1270     * enumeration value corresponding to the target text.
1271     *
1272     * @param target text to be found in enumeration
1273     * @param enums ordered array of texts included in enumeration
1274     * @param vals array of values to be returned for corresponding text match
1275     * positions (position returned directly if this is <code>null</code>)
1276     * @return enumeration value for target text
1277     * @throws JiBXException if target text not found in enumeration
1278     */

1279    public int convertEnum(String JavaDoc target, String JavaDoc[] enums, int[] vals)
1280        throws JiBXException {
1281        if (target == null) {
1282            throwStartTagException("Missing required enumeration value");
1283        }
1284        try {
1285            return Utility.enumValue(target, enums, vals);
1286        } catch (JiBXException ex) {
1287            throw new JiBXException(ex.getMessage() + ' ' +
1288                buildPositionString());
1289        }
1290    }
1291
1292    /**
1293     * Find optional text value in enumeration. Looks up and returns the
1294     * enumeration value corresponding to the target text, or the default
1295     * value if the text is <code>null</code>.
1296     *
1297     * @param target text to be found in enumeration (may be <code>null</code>)
1298     * @param enums ordered array of texts included in enumeration
1299     * @param vals array of values to be returned for corresponding text match
1300     * positions (position returned directly if this is <code>null</code>)
1301     * @param dflt default value returned if target text is <code>null</code>
1302     * @return enumeration value for target text
1303     * @throws JiBXException if target text not found in enumeration
1304     */

1305    public int convertEnum(String JavaDoc target, String JavaDoc[] enums, int[] vals, int dflt)
1306        throws JiBXException {
1307        if (target == null) {
1308            return dflt;
1309        }
1310        try {
1311            return Utility.enumValue(target, enums, vals);
1312        } catch (JiBXException ex) {
1313            throw new JiBXException(ex.getMessage() + ' ' +
1314                buildPositionString());
1315        }
1316    }
1317
1318    /**
1319     * Get enumeration attribute value from current start tag.
1320     * Throws an exception if the attribute value is not found in the start
1321     * tag or the text does not match a value defined in the enumeration table.
1322     *
1323     * @param ns namespace URI for expected attribute (may be <code>null</code>
1324     * or the empty string for the empty namespace)
1325     * @param name attribute name expected
1326     * @param enums ordered array of texts included in enumeration
1327     * @param vals array of values to be returned for corresponding text match
1328     * positions (position returned directly if this is <code>null</code>)
1329     * @return enumeration value for target text
1330     * @throws JiBXException if attribute not present or value not found in
1331     * enumeration list
1332     */

1333    public int attributeEnumeration(String JavaDoc ns, String JavaDoc name, String JavaDoc[] enums,
1334        int[] vals) throws JiBXException {
1335        return convertEnum(getAttributeValue(ns, name), enums, vals);
1336    }
1337
1338    /**
1339     * Get optional enumeration attribute value from current start tag.
1340     * Throws an exception if the attribute value is present but does not match
1341     * a value defined in the enumeration table.
1342     *
1343     * @param ns namespace URI for expected attribute (may be <code>null</code>
1344     * or the empty string for the empty namespace)
1345     * @param name attribute name expected
1346     * @param enums ordered array of texts included in enumeration
1347     * @param vals array of values to be returned for corresponding text match
1348     * positions (position returned directly if this is <code>null</code>)
1349     * @param dflt default value returned if attribute is not present
1350     * @return enumeration value for target text
1351     * @throws JiBXException if attribute not present or value not found in
1352     * enumeration list
1353     */

1354    public int attributeEnumeration(String JavaDoc ns, String JavaDoc name, String JavaDoc[] enums,
1355        int[] vals, int dflt) throws JiBXException {
1356        return convertEnum(getAttributeValue(ns, name), enums, vals, dflt);
1357    }
1358
1359    /**
1360     * Parse past end of element, returning enumeration value of content.
1361     * Assumes you've already parsed past the start tag of the element, so it
1362     * just looks for text content followed by the end tag, and returns with the
1363     * parser positioned after the end tag.
1364     *
1365     * @param ns namespace URI for expected element (may be <code>null</code>
1366     * or the empty string for the empty namespace)
1367     * @param tag element name expected
1368     * @param enums ordered array of texts included in enumeration
1369     * @param vals array of values to be returned for corresponding text match
1370     * positions (position returned directly if this is <code>null</code>)
1371     * @return enumeration value for element text
1372     * @throws JiBXException on any error (possible wrapping other exception)
1373     */

1374    public int parseContentEnumeration(String JavaDoc ns, String JavaDoc tag, String JavaDoc[] enums,
1375        int[] vals) throws JiBXException {
1376        return convertEnum(parseContentText(ns, tag), enums, vals);
1377    }
1378
1379    /**
1380     * Parse entire element, returning enumeration value of optional content.
1381     * Expects to find the element start tag, text content, and end tag,
1382     * in that order, and returns with the parser positioned following
1383     * the end tag. Returns the default value if no content is present.
1384     *
1385     * @param ns namespace URI for expected element (may be <code>null</code>
1386     * or the empty string for the empty namespace)
1387     * @param tag element name expected
1388     * @param enums ordered array of texts included in enumeration
1389     * @param vals array of values to be returned for corresponding text match
1390     * positions (position returned directly if this is <code>null</code>)
1391     * @param dflt default value
1392     * @return enumeration value for element text
1393     * @throws JiBXException on any error (possibly wrapping other exception)
1394     */

1395    public int parseElementEnumeration(String JavaDoc ns, String JavaDoc tag, String JavaDoc[] enums,
1396        int[] vals, int dflt) throws JiBXException {
1397        if (parseIfStartTag(ns, tag)) {
1398            String JavaDoc text = parseContentText(ns, tag);
1399            return convertEnum(text, enums, vals, dflt);
1400        } else {
1401            return dflt;
1402        }
1403    }
1404
1405    /**
1406     * Convert byte value with exception wrapper. This internal method is used
1407     * by all the byte unmarshalling calls. It adds position information to
1408     * any exceptions that occur.
1409     *
1410     * @param text text for value to be converted
1411     * @return converted byte value
1412     * @throws JiBXException if not a valid byte value
1413     */

1414    public byte convertByte(String JavaDoc text) throws JiBXException {
1415        try {
1416            return Utility.parseByte(text);
1417        } catch (JiBXException ex) {
1418            throw new JiBXException(ex.getMessage() + ' ' +
1419                buildPositionString(), ex.getRootCause());
1420        }
1421    }
1422
1423    /**
1424     * Get byte value of attribute from current start tag. Throws an exception
1425     * if the attribute is not found in the start tag, or if it is not a valid
1426     * integer value.
1427     *
1428     * @param ns namespace URI for expected attribute (may be <code>null</code>
1429     * or the empty string for the empty namespace)
1430     * @param name attribute name expected
1431     * @return attribute byte value
1432     * @throws JiBXException if attribute not present or not a valid byte value
1433     */

1434    public byte attributeByte(String JavaDoc ns, String JavaDoc name) throws JiBXException {
1435        return convertByte(attributeText(ns, name));
1436    }
1437
1438    /**
1439     * Get byte value of optional attribute from current start tag. If the
1440     * attribute is not present the supplied default value is returned instead.
1441     *
1442     * @param ns namespace URI for expected attribute (may be <code>null</code>
1443     * or the empty string for the empty namespace)
1444     * @param name attribute name expected
1445     * @param dflt value to be returned if attribute is not present
1446     * @return attribute byte value
1447     * @throws JiBXException if attribute value is not a valid byte
1448     */

1449    public byte attributeByte(String JavaDoc ns, String JavaDoc name, byte dflt)
1450        throws JiBXException {
1451        String JavaDoc text = getAttributeValue(ns, name);
1452        if (text == null) {
1453            return dflt;
1454        } else {
1455            return convertByte(text);
1456        }
1457    }
1458
1459    /**
1460     * Parse past end of element, returning byte value of content. Assumes
1461     * you've already parsed past the start tag of the element, so it just looks
1462     * for text content followed by the end tag, and returns with the parser
1463     * positioned after the end tag.
1464     *
1465     * @param ns namespace URI for expected element (may be <code>null</code>
1466     * or the empty string for the empty namespace)
1467     * @param tag element name expected
1468     * @return converted value from element text
1469     * @throws JiBXException on any error (possible wrapping other exception)
1470     */

1471    public byte parseContentByte(String JavaDoc ns, String JavaDoc tag) throws JiBXException {
1472        return convertByte(parseContentText(ns, tag));
1473    }
1474
1475    /**
1476     * Parse entire element, returning byte value of content.
1477     * Expects to find the element start tag, text content, and end tag,
1478     * in that order, and returns with the parser positioned following
1479     * the end tag.
1480     *
1481     * @param ns namespace URI for expected element (may be <code>null</code>
1482     * or the empty string for the empty namespace)
1483     * @param tag element name expected
1484     * @return content text from element
1485     * @throws JiBXException on any error (possibly wrapping other exception)
1486     */

1487    public byte parseElementByte(String JavaDoc ns, String JavaDoc tag) throws JiBXException {
1488        parsePastStartTag(ns, tag);
1489        return parseContentByte(ns, tag);
1490    }
1491
1492    /**
1493     * Parse entire element, returning byte value of optional content.
1494     * Expects to find the element start tag, text content, and end tag,
1495     * in that order, and returns with the parser positioned following
1496     * the end tag. Returns the default value if no content is present.
1497     *
1498     * @param ns namespace URI for expected element (may be <code>null</code>
1499     * or the empty string for the empty namespace)
1500     * @param tag element name expected
1501     * @param dflt default value
1502     * @return content text from element
1503     * @throws JiBXException on any error (possibly wrapping other exception)
1504     */

1505    public byte parseElementByte(String JavaDoc ns, String JavaDoc tag, byte dflt)
1506        throws JiBXException {
1507        if (parseIfStartTag(ns, tag)) {
1508            return convertByte(parseContentText(ns, tag));
1509        } else {
1510            return dflt;
1511        }
1512    }
1513
1514    /**
1515     * Convert short value with exception wrapper. This internal method is used
1516     * by all the short unmarshalling calls. It adds position information to
1517     * any exceptions that occur.
1518     *
1519     * @param text text for value to be converted
1520     * @return converted short value
1521     * @throws JiBXException if not a valid short value
1522     */

1523    public short convertShort(String JavaDoc text) throws JiBXException {
1524        try {
1525            return Utility.parseShort(text);
1526        } catch (JiBXException ex) {
1527            throw new JiBXException(ex.getMessage() + ' ' +
1528                buildPositionString(), ex.getRootCause());
1529        }
1530    }
1531
1532    /**
1533     * Get short value of attribute from current start tag. Throws an exception
1534     * if the attribute is not found in the start tag, or if it is not a valid
1535     * integer value.
1536     *
1537     * @param ns namespace URI for expected attribute (may be <code>null</code>
1538     * or the empty string for the empty namespace)
1539     * @param name attribute name expected
1540     * @return attribute short value
1541     * @throws JiBXException if attribute not present or not a valid short value
1542     */

1543    public short attributeShort(String JavaDoc ns, String JavaDoc name) throws JiBXException {
1544        return convertShort(attributeText(ns, name));
1545    }
1546
1547    /**
1548     * Get short value of optional attribute from current start tag. If the
1549     * attribute is not present the supplied default value is returned instead.
1550     *
1551     * @param ns namespace URI for expected attribute (may be <code>null</code>
1552     * or the empty string for the empty namespace)
1553     * @param name attribute name expected
1554     * @param dflt value to be returned if attribute is not present
1555     * @return attribute short value
1556     * @throws JiBXException if attribute value is not a valid short
1557     */

1558    public short attributeShort(String JavaDoc ns, String JavaDoc name, short dflt)
1559        throws JiBXException {
1560        String JavaDoc text = getAttributeValue(ns, name);
1561        if (text == null) {
1562            return dflt;
1563        } else {
1564            return convertShort(text);
1565        }
1566    }
1567
1568    /**
1569     * Parse past end of element, returning short value of content. Assumes
1570     * you've already parsed past the start tag of the element, so it just looks
1571     * for text content followed by the end tag, and returns with the parser
1572     * positioned after the end tag.
1573     *
1574     * @param ns namespace URI for expected element (may be <code>null</code>
1575     * or the empty string for the empty namespace)
1576     * @param tag element name expected
1577     * @return converted value from element text
1578     * @throws JiBXException on any error (possible wrapping other exception)
1579     */

1580    public short parseContentShort(String JavaDoc ns, String JavaDoc tag) throws JiBXException {
1581        return convertShort(parseContentText(ns, tag));
1582    }
1583
1584    /**
1585     * Parse entire element, returning short value of content.
1586     * Expects to find the element start tag, text content, and end tag,
1587     * in that order, and returns with the parser positioned following
1588     * the end tag.
1589     *
1590     * @param ns namespace URI for expected element (may be <code>null</code>
1591     * or the empty string for the empty namespace)
1592     * @param tag element name expected
1593     * @return content text from element
1594     * @throws JiBXException on any error (possibly wrapping other exception)
1595     */

1596    public short parseElementShort(String JavaDoc ns, String JavaDoc tag) throws JiBXException {
1597        parsePastStartTag(ns, tag);
1598        return parseContentShort(ns, tag);
1599    }
1600
1601    /**
1602     * Parse entire element, returning short value of optional content.
1603     * Expects to find the element start tag, text content, and end tag,
1604     * in that order, and returns with the parser positioned following
1605     * the end tag. Returns the default value if no content is present.
1606     *
1607     * @param ns namespace URI for expected element (may be <code>null</code>
1608     * or the empty string for the empty namespace)
1609     * @param tag element name expected
1610     * @param dflt default value
1611     * @return content text from element
1612     * @throws JiBXException on any error (possibly wrapping other exception)
1613     */

1614    public short parseElementShort(String JavaDoc ns, String JavaDoc tag, short dflt)
1615        throws JiBXException {
1616        if (parseIfStartTag(ns, tag)) {
1617            return convertShort(parseContentText(ns, tag));
1618        } else {
1619            return dflt;
1620        }
1621    }
1622    
1623    /**
1624     * Convert char value with exception wrapper. This internal method is used
1625     * by all the char unmarshalling calls. It adds position information to
1626     * any exceptions that occur.
1627     *
1628     * @param text text for value to be converted
1629     * @return converted char value
1630     * @throws JiBXException if not a valid char value
1631     */

1632    public char convertChar(String JavaDoc text) throws JiBXException {
1633        try {
1634            return Utility.parseChar(text);
1635        } catch (JiBXException ex) {
1636            throw new JiBXException(ex.getMessage() + ' ' +
1637                buildPositionString(), ex.getRootCause());
1638        }
1639    }
1640
1641    /**
1642     * Get char value of attribute from current start tag. Throws an exception
1643     * if the attribute is not found in the start tag, or if it is not a valid
1644     * integer value.
1645     *
1646     * @param ns namespace URI for expected attribute (may be <code>null</code>
1647     * or the empty string for the empty namespace)
1648     * @param name attribute name expected
1649     * @return attribute char value
1650     * @throws JiBXException if attribute not present or not a valid char value
1651     */

1652    public char attributeChar(String JavaDoc ns, String JavaDoc name) throws JiBXException {
1653        return convertChar(attributeText(ns, name));
1654    }
1655
1656    /**
1657     * Get char value of optional attribute from current start tag. If the
1658     * attribute is not present the supplied default value is returned instead.
1659     *
1660     * @param ns namespace URI for expected attribute (may be <code>null</code>
1661     * or the empty string for the empty namespace)
1662     * @param name attribute name expected
1663     * @param dflt value to be returned if attribute is not present
1664     * @return attribute char value
1665     * @throws JiBXException if attribute value is not a valid char
1666     */

1667    public char attributeChar(String JavaDoc ns, String JavaDoc name, char dflt)
1668        throws JiBXException {
1669        String JavaDoc text = getAttributeValue(ns, name);
1670        if (text == null) {
1671            return dflt;
1672        } else {
1673            return convertChar(text);
1674        }
1675    }
1676
1677    /**
1678     * Parse past end of element, returning char value of content. Assumes
1679     * you've already parsed past the start tag of the element, so it just looks
1680     * for text content followed by the end tag, and returns with the parser
1681     * positioned after the end tag.
1682     *
1683     * @param ns namespace URI for expected element (may be <code>null</code>
1684     * or the empty string for the empty namespace)
1685     * @param tag element name expected
1686     * @return converted value from element text
1687     * @throws JiBXException on any error (possible wrapping other exception)
1688     */

1689    public char parseContentChar(String JavaDoc ns, String JavaDoc tag) throws JiBXException {
1690        return convertChar(parseContentText(ns, tag));
1691    }
1692
1693    /**
1694     * Parse entire element, returning char value of content.
1695     * Expects to find the element start tag, text content, and end tag,
1696     * in that order, and returns with the parser positioned following
1697     * the end tag.
1698     *
1699     * @param ns namespace URI for expected element (may be <code>null</code>
1700     * or the empty string for the empty namespace)
1701     * @param tag element name expected
1702     * @return content text from element
1703     * @throws JiBXException on any error (possibly wrapping other exception)
1704     */

1705    public char parseElementChar(String JavaDoc ns, String JavaDoc tag) throws JiBXException {
1706        parsePastStartTag(ns, tag);
1707        return parseContentChar(ns, tag);
1708    }
1709
1710    /**
1711     * Parse entire element, returning char value of optional content.
1712     * Expects to find the element start tag, text content, and end tag,
1713     * in that order, and returns with the parser positioned following
1714     * the end tag. Returns the default value if the element is not present.
1715     *
1716     * @param ns namespace URI for expected element (may be <code>null</code>
1717     * or the empty string for the empty namespace)
1718     * @param tag element name expected
1719     * @param dflt default value
1720     * @return content text from element
1721     * @throws JiBXException on any error (possibly wrapping other exception)
1722     */

1723    public char parseElementChar(String JavaDoc ns, String JavaDoc tag, char dflt)
1724        throws JiBXException {
1725        if (parseIfStartTag(ns, tag)) {
1726            return convertChar(parseContentText(ns, tag));
1727        } else {
1728            return dflt;
1729        }
1730    }
1731
1732    /**
1733     * Convert long value with exception wrapper. This internal method is used
1734     * by all the long unmarshalling calls. It adds position information to
1735     * any exceptions that occur.
1736     *
1737     * @param text text for value to be converted
1738     * @return converted long value
1739     * @throws JiBXException if not a valid long value
1740     */

1741    public long convertLong(String JavaDoc text) throws JiBXException {
1742        try {
1743            return Utility.parseLong(text);
1744        } catch (JiBXException ex) {
1745            throw new JiBXException(ex.getMessage() + ' ' +
1746                buildPositionString(), ex.getRootCause());
1747        }
1748    }
1749
1750    /**
1751     * Get long value of attribute from current start tag. Throws an exception
1752     * if the attribute is not found in the start tag, or if it is not a valid
1753     * integer value.
1754     *
1755     * @param ns namespace URI for expected attribute (may be <code>null</code>
1756     * or the empty string for the empty namespace)
1757     * @param name attribute name expected
1758     * @return attribute long value
1759     * @throws JiBXException if attribute not present or not a valid long value
1760     */

1761    public long attributeLong(String JavaDoc ns, String JavaDoc name) throws JiBXException {
1762        return convertLong(attributeText(ns, name));
1763    }
1764
1765    /**
1766     * Get long value of optional attribute from current start tag. If the
1767     * attribute is not present the supplied default value is returned instead.
1768     *
1769     * @param ns namespace URI for expected attribute (may be <code>null</code>
1770     * or the empty string for the empty namespace)
1771     * @param name attribute name expected
1772     * @param dflt value to be returned if attribute is not present
1773     * @return attribute long value
1774     * @throws JiBXException if attribute value is not a valid long
1775     */

1776    public long attributeLong(String JavaDoc ns, String JavaDoc name, long dflt)
1777        throws JiBXException {
1778        String JavaDoc text = getAttributeValue(ns, name);
1779        if (text == null) {
1780            return dflt;
1781        } else {
1782            return convertLong(text);
1783        }
1784    }
1785
1786    /**
1787     * Parse past end of element, returning long value of content.
1788     * Expects to find the element start tag, text content, and end tag,
1789     * in that order, and returns with the parser positioned following
1790     * the end tag.
1791     *
1792     * @param ns namespace URI for expected element (may be <code>null</code>
1793     * or the empty string for the empty namespace)
1794     * @param tag element name expected
1795     * @return converted value from element text
1796     * @throws JiBXException on any error (possible wrapping other exception)
1797     */

1798    public long parseElementLong(String JavaDoc ns, String JavaDoc tag) throws JiBXException {
1799        parsePastStartTag(ns, tag);
1800        return convertLong(parseContentText(ns, tag));
1801    }
1802
1803    /**
1804     * Parse entire element, returning long value of optional content.
1805     * Expects to find the element start tag, text content, and end tag,
1806     * in that order, and returns with the parser positioned following
1807     * the end tag. Returns the default value if the element is not present.
1808     *
1809     * @param ns namespace URI for expected element (may be <code>null</code>
1810     * or the empty string for the empty namespace)
1811     * @param tag element name expected
1812     * @param dflt default value
1813     * @return content text from element
1814     * @throws JiBXException on any error (possibly wrapping other exception)
1815     */

1816    public long parseElementLong(String JavaDoc ns, String JavaDoc tag, long dflt)
1817        throws JiBXException {
1818        if (parseIfStartTag(ns, tag)) {
1819            return convertLong(parseContentText(ns, tag));
1820        } else {
1821            return dflt;
1822        }
1823    }
1824
1825    /**
1826     * Convert boolean value. This internal method is used by all the boolean
1827     * unmarshalling calls. It accepts "true" or "1" as equivalent, and "false"
1828     * or "0" as equivalent, and throws exceptions for anything else.
1829     *
1830     * @param text text for value to be converted
1831     * @return converted boolean value
1832     * @throws JiBXException if not a valid boolean value
1833     */

1834    public boolean convertBoolean(String JavaDoc text) throws JiBXException {
1835        if ("true".equals(text) || "1".equals(text)) {
1836            return true;
1837        } else if ("false".equals(text) || "0".equals(text)) {
1838            return false;
1839        }
1840        throw new JiBXException("Invalid boolean value " +
1841            buildPositionString());
1842    }
1843
1844    /**
1845     * Get boolean value of attribute from current start tag. Throws an
1846     * exception if the attribute is not found in the start tag, or if it is
1847     * not a valid integer value.
1848     *
1849     * @param ns namespace URI for expected attribute (may be <code>null</code>
1850     * or the empty string for the empty namespace)
1851     * @param name attribute name expected
1852     * @return attribute boolean value
1853     * @throws JiBXException if attribute not present or not a valid boolean
1854     * value
1855     */

1856    public boolean attributeBoolean(String JavaDoc ns, String JavaDoc name)
1857        throws JiBXException {
1858        return convertBoolean(attributeText(ns, name));
1859    }
1860
1861    /**
1862     * Get boolean value of optional attribute from current start tag. If the
1863     * attribute is not present the supplied default value is returned instead.
1864     *
1865     * @param ns namespace URI for expected attribute (may be <code>null</code>
1866     * or the empty string for the empty namespace)
1867     * @param name attribute name expected
1868     * @param dflt value to be returned if attribute is not present
1869     * @return attribute boolean value
1870     * @throws JiBXException if attribute value is not a valid boolean
1871     */

1872    public boolean attributeBoolean(String JavaDoc ns, String JavaDoc name, boolean dflt)
1873        throws JiBXException {
1874        String JavaDoc text = getAttributeValue(ns, name);
1875        if (text == null) {
1876            return dflt;
1877        } else {
1878            return convertBoolean(text);
1879        }
1880    }
1881
1882    /**
1883     * Parse entire element, returning boolean value of content.
1884     * Expects to find the element start tag, text content, and end tag,
1885     * in that order, and returns with the parser positioned following
1886     * the end tag.
1887     *
1888     * @param ns namespace URI for expected element (may be <code>null</code>
1889     * or the empty string for the empty namespace)
1890     * @param tag element name expected
1891     * @return converted value from element text
1892     * @throws JiBXException on any error (possible wrapping other exception)
1893     */

1894    public boolean parseElementBoolean(String JavaDoc ns, String JavaDoc tag)
1895        throws JiBXException {
1896        parsePastStartTag(ns, tag);
1897        return convertBoolean(parseContentText(ns, tag));
1898    }
1899
1900    /**
1901     * Parse entire element, returning boolean value of optional content.
1902     * Expects to find the element start tag, text content, and end tag,
1903     * in that order, and returns with the parser positioned following
1904     * the end tag. Returns the default value if the element is not present.
1905     *
1906     * @param ns namespace URI for expected element (may be <code>null</code>
1907     * or the empty string for the empty namespace)
1908     * @param tag element name expected
1909     * @param dflt default value
1910     * @return content text from element
1911     * @throws JiBXException on any error (possibly wrapping other exception)
1912     */

1913    public boolean parseElementBoolean(String JavaDoc ns, String JavaDoc tag, boolean dflt)
1914        throws JiBXException {
1915        if (parseIfStartTag(ns, tag)) {
1916            return convertBoolean(parseContentText(ns, tag));
1917        } else {
1918            return dflt;
1919        }
1920    }
1921
1922    /**
1923     * Convert float value with exception wrapper. This internal method is used
1924     * by all the float unmarshalling calls. It adds position information to
1925     * any exceptions that occur.
1926     *
1927     * @param text text for value to be converted
1928     * @return converted float value
1929     * @throws JiBXException if not a valid float value
1930     */

1931    public float convertFloat(String JavaDoc text) throws JiBXException {
1932        try {
1933            return Utility.parseFloat(text);
1934        } catch (JiBXException ex) {
1935            throw new JiBXException(ex.getMessage() + ' ' +
1936                buildPositionString(), ex.getRootCause());
1937        }
1938    }
1939
1940    /**
1941     * Get float value of attribute from current start tag. Throws an exception
1942     * if the attribute is not found in the start tag, or if it is not a valid
1943     * integer value.
1944     *
1945     * @param ns namespace URI for expected attribute (may be <code>null</code>
1946     * or the empty string for the empty namespace)
1947     * @param name attribute name expected
1948     * @return attribute float value
1949     * @throws JiBXException if attribute not present or not a valid float value
1950     */

1951    public float attributeFloat(String JavaDoc ns, String JavaDoc name) throws JiBXException {
1952        return convertFloat(attributeText(ns, name));
1953    }
1954
1955    /**
1956     * Get float value of optional attribute from current start tag. If the
1957     * attribute is not present the supplied default value is returned instead.
1958     *
1959     * @param ns namespace URI for expected attribute (may be <code>null</code>
1960     * or the empty string for the empty namespace)
1961     * @param name attribute name expected
1962     * @param dflt value to be returned if attribute is not present
1963     * @return attribute float value
1964     * @throws JiBXException if attribute value is not a valid float
1965     */

1966    public float attributeFloat(String JavaDoc ns, String JavaDoc name, float dflt)
1967        throws JiBXException {
1968        String JavaDoc text = getAttributeValue(ns, name);
1969        if (text == null) {
1970            return dflt;
1971        } else {
1972            return convertFloat(text);
1973        }
1974    }
1975
1976    /**
1977     * Parse past end of element, returning float value of content.
1978     * Expects to find the element start tag, text content, and end tag,
1979     * in that order, and returns with the parser positioned following
1980     * the end tag.
1981     *
1982     * @param ns namespace URI for expected element (may be <code>null</code>
1983     * or the empty string for the empty namespace)
1984     * @param tag element name expected
1985     * @return converted value from element text
1986     * @throws JiBXException on any error (possible wrapping other exception)
1987     */

1988    public float parseElementFloat(String JavaDoc ns, String JavaDoc tag) throws JiBXException {
1989        parsePastStartTag(ns, tag);
1990        return convertFloat(parseContentText(ns, tag));
1991    }
1992
1993    /**
1994     * Parse entire element, returning float value of optional content.
1995     * Expects to find the element start tag, text content, and end tag,
1996     * in that order, and returns with the parser positioned following
1997     * the end tag. Returns the default value if the element is not present.
1998     *
1999     * @param ns namespace URI for expected element (may be <code>null</code>
2000     * or the empty string for the empty namespace)
2001     * @param tag element name expected
2002     * @param dflt default value
2003     * @return content text from element
2004     * @throws JiBXException on any error (possibly wrapping other exception)
2005     */

2006    public float parseElementFloat(String JavaDoc ns, String JavaDoc tag, float dflt)
2007        throws JiBXException {
2008        if (parseIfStartTag(ns, tag)) {
2009            return convertFloat(parseContentText(ns, tag));
2010        } else {
2011            return dflt;
2012        }
2013    }
2014
2015    /**
2016     * Convert double value with exception wrapper. This internal method is used
2017     * by all the double unmarshalling calls. It adds position information to
2018     * any exceptions that occur.
2019     *
2020     * @param text text for value to be converted
2021     * @return converted double value
2022     * @throws JiBXException if not a valid double value
2023     */

2024    public double convertDouble(String JavaDoc text) throws JiBXException {
2025        try {
2026            return Utility.parseDouble(text);
2027        } catch (JiBXException ex) {
2028            throw new JiBXException(ex.getMessage() + ' ' +
2029                buildPositionString(), ex.getRootCause());
2030        }
2031    }
2032
2033    /**
2034     * Get double value of attribute from current start tag. Throws an exception
2035     * if the attribute is not found in the start tag, or if it is not a valid
2036     * integer value.
2037     *
2038     * @param ns namespace URI for expected attribute (may be <code>null</code>
2039     * or the empty string for the empty namespace)
2040     * @param name attribute name expected
2041     * @return attribute double value
2042     * @throws JiBXException if attribute not present or not a valid double
2043     * value
2044     */

2045    public double attributeDouble(String JavaDoc ns, String JavaDoc name) throws JiBXException {
2046        return convertDouble(attributeText(ns, name));
2047    }
2048
2049    /**
2050     * Get double value of optional attribute from current start tag. If the
2051     * attribute is not present the supplied default value is returned instead.
2052     *
2053     * @param ns namespace URI for expected attribute (may be <code>null</code>
2054     * or the empty string for the empty namespace)
2055     * @param name attribute name expected
2056     * @param dflt value to be returned if attribute is not present
2057     * @return attribute double value
2058     * @throws JiBXException if attribute value is not a valid double
2059     */

2060    public double attributeDouble(String JavaDoc ns, String JavaDoc name, double dflt)
2061        throws JiBXException {
2062        String JavaDoc text = getAttributeValue(ns, name);
2063        if (text == null) {
2064            return dflt;
2065        } else {
2066            return convertDouble(text);
2067        }
2068    }
2069
2070    /**
2071     * Parse past end of element, returning double value of content.
2072     * Expects to find the element start tag, text content, and end tag,
2073     * in that order, and returns with the parser positioned following
2074     * the end tag.
2075     *
2076     * @param ns namespace URI for expected element (may be <code>null</code>
2077     * or the empty string for the empty namespace)
2078     * @param tag element name expected
2079     * @return converted value from element text
2080     * @throws JiBXException on any error (possible wrapping other exception)
2081     */

2082    public double parseElementDouble(String JavaDoc ns, String JavaDoc tag)
2083        throws JiBXException {
2084        parsePastStartTag(ns, tag);
2085        return convertDouble(parseContentText(ns, tag));
2086    }
2087
2088    /**
2089     * Parse entire element, returning double value of optional content.
2090     * Expects to find the element start tag, text content, and end tag,
2091     * in that order, and returns with the parser positioned following
2092     * the end tag. Returns the default value if the element is not present.
2093     *
2094     * @param ns namespace URI for expected element (may be <code>null</code>
2095     * or the empty string for the empty namespace)
2096     * @param tag element name expected
2097     * @param dflt default value
2098     * @return content text from element
2099     * @throws JiBXException on any error (possibly wrapping other exception)
2100     */

2101    public double parseElementDouble(String JavaDoc ns, String JavaDoc tag, double dflt)
2102        throws JiBXException {
2103        if (parseIfStartTag(ns, tag)) {
2104            return convertDouble(parseContentText(ns, tag));
2105        } else {
2106            return dflt;
2107        }
2108    }
2109
2110    /**
2111     * Convert <code>java.util.Date</code> value with exception wrapper. This
2112     * internal method is used by all the Date unmarshalling calls. It adds
2113     * position information to any exceptions that occur.
2114     *
2115     * @param text text for value to be converted
2116     * @return converted Date value
2117     * @throws JiBXException if not a valid Date value
2118     */

2119    public Date convertDate(String JavaDoc text) throws JiBXException {
2120        try {
2121            return new Date(Utility.parseDateTime(text));
2122        } catch (JiBXException ex) {
2123            throw new JiBXException(ex.getMessage() + ' ' +
2124                buildPositionString(), ex.getRootCause());
2125        }
2126    }
2127
2128    /**
2129     * Get <code>java.util.Date</code> value of attribute from current start
2130     * tag. Throws an exception if the attribute is not found in the start tag,
2131     * or if it is not a valid integer value.
2132     *
2133     * @param ns namespace URI for expected attribute (may be <code>null</code>
2134     * or the empty string for the empty namespace)
2135     * @param name attribute name expected
2136     * @return attribute Date value
2137     * @throws JiBXException if attribute not present or not a valid Date
2138     * value
2139     */

2140    public Date attributeDate(String JavaDoc ns, String JavaDoc name) throws JiBXException {
2141        return convertDate(attributeText(ns, name));
2142    }
2143
2144    /**
2145     * Get <code>java.util.Date</code> value of optional attribute from current
2146     * start tag. If the attribute is not present the supplied default value is
2147     * returned instead.
2148     *
2149     * @param ns namespace URI for expected attribute (may be <code>null</code>
2150     * or the empty string for the empty namespace)
2151     * @param name attribute name expected
2152     * @param dflt value to be returned if attribute is not present
2153     * @return attribute Date value
2154     * @throws JiBXException if attribute value is not a valid Date
2155     */

2156    public Date attributeDate(String JavaDoc ns, String JavaDoc name, Date dflt)
2157        throws JiBXException {
2158        String JavaDoc text = getAttributeValue(ns, name);
2159        if (text == null) {
2160            return dflt;
2161        } else {
2162            return convertDate(text);
2163        }
2164    }
2165
2166    /**
2167     * Parse past end of element, returning <code>java.util.Date</code> value
2168     * of content. Expects to find the element start tag, text content,
2169     * and end tag, in that order, and returns with the parser positioned
2170     * following the end tag.
2171     *
2172     * @param ns namespace URI for expected element (may be <code>null</code>
2173     * or the empty string for the empty namespace)
2174     * @param tag element name expected
2175     * @return converted value from element text
2176     * @throws JiBXException on any error (possible wrapping other exception)
2177     */

2178    public Date parseElementDate(String JavaDoc ns, String JavaDoc tag) throws JiBXException {
2179        parsePastStartTag(ns, tag);
2180        return convertDate(parseContentText(ns, tag));
2181    }
2182
2183    /**
2184     * Parse entire element, returning <code>java.util.Date</code> value of
2185     * optional content. Expects to find the element start tag, text content,
2186     * and end tag, in that order, and returns with the parser positioned
2187     * following the end tag. Returns the default value if the element is not
2188     * present.
2189     *
2190     * @param ns namespace URI for expected element (may be <code>null</code>
2191     * or the empty string for the empty namespace)
2192     * @param tag element name expected
2193     * @param dflt default value
2194     * @return content text from element
2195     * @throws JiBXException on any error (possibly wrapping other exception)
2196     */

2197    public Date parseElementDate(String JavaDoc ns, String JavaDoc tag, Date dflt)
2198        throws JiBXException {
2199        if (parseIfStartTag(ns, tag)) {
2200            return convertDate(parseContentText(ns, tag));
2201        } else {
2202            return dflt;
2203        }
2204    }
2205
2206    /**
2207     * Register back fill item for undefined ID value. This adds a holder to
2208     * the mapping table if not already present, then adds the back fill item
2209     * to the holder.
2210     *
2211     * @param id target undefined ID value
2212     * @param index target reference type index
2213     * @param fill back fill item
2214     * @throws JiBXException if attribute not present, or ID already defined
2215     */

2216    public void registerBackFill(String JavaDoc id, int index, BackFillReference fill)
2217        throws JiBXException {
2218        HashMap map = m_idMaps[index];
2219        if (map == null) {
2220            m_idMaps[index] = map = new HashMap();
2221        }
2222        Object JavaDoc obj = map.get(id);
2223        if (obj == null) {
2224            String JavaDoc xclass = (m_idClasses == null) ? null : m_idClasses[index];
2225            BackFillHolder holder = new BackFillHolder(xclass);
2226            map.put(id, holder);
2227            holder.addBackFill(fill);
2228        } else if (obj instanceof BackFillHolder) {
2229            ((BackFillHolder)obj).addBackFill(fill);
2230        } else {
2231            throw new JiBXException
2232                ("Internal operation error (back fill error) " +
2233                buildPositionString());
2234        }
2235    }
2236
2237    /**
2238     * Register back fill item for last parsed ID value. This adds a holder to
2239     * the mapping table if not already present, then adds the back fill item
2240     * to the holder. This form of call always applies to the last IDREF value
2241     * parsed (from either an element or an attribute).
2242     *
2243     * @param index target reference type index
2244     * @param fill back fill item
2245     * @throws JiBXException if attribute not present, or ID already defined
2246     */

2247    public void registerBackFill(int index, BackFillReference fill)
2248        throws JiBXException {
2249        registerBackFill(m_idref, index, fill);
2250    }
2251
2252    /**
2253     * Define object for ID. Adds the owning object to a map with the ID
2254     * value as key. Throws an exception if the object class does not match
2255     * that expected from forward references, or if another object has
2256     * previously been registered with the same ID.
2257     *
2258     * @param id text ID value
2259     * @param index ID class index number
2260     * @param obj object corresponding to element
2261     * @throws JiBXException if duplicate ID or wrong class
2262     */

2263    public void defineID(String JavaDoc id, int index, Object JavaDoc obj)
2264        throws JiBXException {
2265        HashMap map = m_idMaps[index];
2266        if (map == null) {
2267            m_idMaps[index] = map = new HashMap();
2268        }
2269        Object JavaDoc prior = map.put(id, obj);
2270        if (prior instanceof BackFillHolder) {
2271            BackFillHolder holder = (BackFillHolder)prior;
2272            String JavaDoc xclass = holder.getExpectedClass();
2273            if (xclass == null || xclass.equals(obj.getClass().getName())) {
2274                holder.defineValue(obj);
2275            } else {
2276                throw new JiBXException("ID object has wrong type " +
2277                    buildPositionString());
2278            }
2279        } else if (prior != null) {
2280            throw new JiBXException("Duplicate ID definition " +
2281                buildPositionString());
2282        }
2283    }
2284
2285    /**
2286     * Map unmarshalling for element. Adds the entry for a particular class
2287     * index to the unmarshalling map.
2288     *
2289     * @param index class index for unmarshalling definition to be added
2290     */

2291    protected void mapUnmarshalling(int index) {
2292        Object JavaDoc value = m_unmarshalMap.get(m_names[index]);
2293        if (value instanceof Integer JavaDoc) {
2294            ArrayList list = new ArrayList();
2295            list.add(value);
2296            list.add(m_indexes[index]);
2297            m_unmarshalMap.put(m_names[index], list);
2298        } else if (value instanceof ArrayList) {
2299            ArrayList list = (ArrayList)value;
2300            list.add(m_indexes[index]);
2301        } else {
2302            m_unmarshalMap.put(m_names[index], m_indexes[index]);
2303        }
2304    }
2305
2306    /**
2307     * Define unmarshalling for element. Enables the unmarshalling definition
2308     * linking an element name (including namespace) with a handler. The
2309     * unmarshalling definitions use fixed indexes for each class, allowing
2310     * direct lookup of the unmarshaller when multiple versions are defined.
2311     *
2312     * @param index class index for unmarshalling definition
2313     * @param ns namespace for element (may be <code>null</code>
2314     * or the empty string for the empty namespace)
2315     * @param name name for element
2316     * @param cname name of class created by unmarshaller
2317     */

2318    public void addUnmarshalling(int index, String JavaDoc ns, String JavaDoc name,
2319        String JavaDoc cname) {
2320        m_namespaces[index] = ns;
2321        m_names[index] = name;
2322        m_unmarshallerClasses[index] = cname;
2323        if (m_unmarshalMap != null && name != null) {
2324            mapUnmarshalling(index);
2325        }
2326    }
2327
2328    /**
2329     * Undefine unmarshalling for element. Disables the unmarshalling
2330     * definition for a particular class index.
2331     *
2332     * @param index class index for unmarshalling definition
2333     */

2334    public void removeUnmarshalling(int index) {
2335        if (m_unmarshalMap != null && m_names[index] != null) {
2336            Object JavaDoc value = m_unmarshalMap.get(m_names[index]);
2337            if (value instanceof Integer JavaDoc) {
2338                m_unmarshalMap.remove(m_names[index]);
2339            } else if (value instanceof ArrayList) {
2340                ArrayList list = (ArrayList)value;
2341                list.remove(list.indexOf(m_indexes[index]));
2342            }
2343        }
2344        m_namespaces[index] = null;
2345        m_names[index] = null;
2346        m_unmarshallers[index] = null;
2347        m_unmarshallerClasses[index] = null;
2348    }
2349
2350    /**
2351     * Find the unmarshaller for a particular class index in the current
2352     * context.
2353     *
2354     * @param index class index for unmarshalling definition
2355     * @return unmarshalling handler for class
2356     * @throws JiBXException if unable to create unmarshaller
2357     */

2358    public IUnmarshaller getUnmarshaller(int index) throws JiBXException {
2359        if (m_unmarshallers[index] == null) {
2360            
2361            // load the unmarshaller class and create an instance
2362
Exception JavaDoc ex = null;
2363            try {
2364                
2365                // first try loading class from context classloader
2366
Class JavaDoc clas = null;
2367                String JavaDoc name = m_unmarshallerClasses[index];
2368                ClassLoader JavaDoc loader =
2369                    Thread.currentThread().getContextClassLoader();
2370                if (loader != null) {
2371                    try {
2372                        clas = loader.loadClass(name);
2373                    } catch (ClassNotFoundException JavaDoc e) { /* fall through */ }
2374                }
2375                if (clas == null) {
2376                    
2377                    // if not found, try the loader that loaded this class
2378
clas = UnmarshallingContext.class.getClassLoader().
2379                        loadClass(name);
2380                }
2381                
2382                // create an instance of unmarshaller class
2383
IUnmarshaller um = (IUnmarshaller)clas.newInstance();
2384                m_unmarshallers[index] = um;
2385                
2386            } catch (ClassNotFoundException JavaDoc e) {
2387                ex = e;
2388            } catch (ClassCastException JavaDoc e) {
2389                ex = e;
2390            } catch (InstantiationException JavaDoc e) {
2391                ex = e;
2392            } catch (IllegalAccessException JavaDoc e) {
2393                ex = e;
2394            } finally {
2395                if (ex != null) {
2396                    throw new JiBXException
2397                        ("Unable to create unmarshaller of class " +
2398                        m_unmarshallerClasses[index] + ": " + ex, ex);
2399                }
2400            }
2401        }
2402        return m_unmarshallers[index];
2403    }
2404
2405    /**
2406     * Find the unmarshaller for a particular element name (including
2407     * namespace) in the current context.
2408     *
2409     * @param ns namespace for element (may be <code>null</code>
2410     * or the empty string for the empty namespace)
2411     * @param name name for element
2412     * @return unmarshalling handler for element, or <code>null</code> if none
2413     * found
2414     * @throws JiBXException if unable to create unmarshaller
2415     */

2416    public IUnmarshaller getUnmarshaller(String JavaDoc ns, String JavaDoc name)
2417        throws JiBXException {
2418        if (m_unmarshalMap == null) {
2419            m_unmarshalMap = new HashMap();
2420            m_indexes = new Integer JavaDoc[m_names.length];
2421            for (int i = 0; i < m_names.length; i++) {
2422                m_indexes[i] = new Integer JavaDoc(i);
2423                if (m_names[i] != null) {
2424                    mapUnmarshalling(i);
2425                }
2426            }
2427        }
2428        Object JavaDoc value = m_unmarshalMap.get(name);
2429        if (value instanceof Integer JavaDoc) {
2430            int index = ((Integer JavaDoc)value).intValue();
2431            String JavaDoc mns = m_namespaces[index];
2432            if (ns == mns || (ns == null && mns.length() == 0) ||
2433                (mns == null && ns.length() == 0) ||
2434                (ns != null && ns.equals(mns))) {
2435                return getUnmarshaller(index);
2436            }
2437        } else if (value instanceof ArrayList) {
2438            ArrayList list = (ArrayList)value;
2439            for (int i = 0; i < list.size(); i++) {
2440                int index = ((Integer JavaDoc)list.get(i)).intValue();
2441                String JavaDoc mns = m_namespaces[index];
2442                if (ns == mns || (ns == null && mns.length() == 0) ||
2443                    (mns == null && ns.length() == 0) ||
2444                    (ns != null && ns.equals(mns))) {
2445                    return getUnmarshaller(index);
2446                }
2447            }
2448        }
2449        return null;
2450    }
2451
2452    /**
2453     * Unmarshal optional element. If not currently positioned at a start or
2454     * end tag this first advances the parse to the next start or end tag.
2455     *
2456     * @return unmarshalled object from element, or <code>null</code> if end tag
2457     * rather than start tag seen
2458     * @throws JiBXException on any error (possibly wrapping other exception)
2459     */

2460    public Object JavaDoc unmarshalOptionalElement() throws JiBXException {
2461        int type = toTag();
2462        if (type == XmlPullParser.START_TAG) {
2463            IUnmarshaller unmarshal =
2464                getUnmarshaller(m_parser.getNamespace(), m_parser.getName());
2465            if (unmarshal != null) {
2466                return unmarshal.unmarshal(null, this);
2467            }
2468        }
2469        return null;
2470    }
2471
2472    /**
2473     * Unmarshal required element of specified type. If not currently positioned
2474     * at a start or end tag this first advances the parse to the next start or
2475     * end tag. The returned object will always be assignable to the specified
2476     * type.
2477     *
2478     * @param clas expected class of unmarshalled object
2479     * @return unmarshalled object from element
2480     * @throws JiBXException on any error (possibly wrapping other exception)
2481     */

2482    public Object JavaDoc unmarshalElement(Class JavaDoc clas) throws JiBXException {
2483        String JavaDoc name = toStart();
2484        IUnmarshaller unmarshal =
2485            getUnmarshaller(m_parser.getNamespace(), name);
2486        if (unmarshal == null) {
2487            throw new JiBXException("No unmarshaller for element " +
2488                currentNameString() + " " + buildPositionString());
2489        } else {
2490            Object JavaDoc obj = unmarshal.unmarshal(null, this);
2491            if (!clas.isInstance(obj)) {
2492                throw new JiBXException("Element " + name +
2493                    " not compatible with expected type " + clas.getName() +
2494                    " " + buildPositionString());
2495            }
2496            return obj;
2497        }
2498    }
2499
2500    /**
2501     * Unmarshal required element. If not currently positioned at a start or
2502     * end tag this first advances the parse to the next start or end tag.
2503     *
2504     * @return unmarshalled object from element
2505     * @throws JiBXException on any error (possibly wrapping other exception)
2506     */

2507    public Object JavaDoc unmarshalElement() throws JiBXException {
2508        String JavaDoc name = toStart();
2509        IUnmarshaller unmarshal =
2510            getUnmarshaller(m_parser.getNamespace(), name);
2511        if (unmarshal == null) {
2512            throw new JiBXException("No unmarshaller for element " +
2513                currentNameString() + " " + buildPositionString());
2514        } else {
2515            return unmarshal.unmarshal(null, this);
2516        }
2517    }
2518
2519    /**
2520     * Parse past element, ignoring all content. This may be used while
2521     * positioned either before or on the element start tag. It checks if
2522     * currently positioned at the element start tag, and if so advances to the
2523     * next parse event. Then looks for the next end tag, ignoring character
2524     * data and skipping child elements. Leaves the parse positioned following
2525     * the end tag.
2526     *
2527     * @param ns namespace URI for expected element (may be <code>null</code>
2528     * or the empty string for the empty namespace)
2529     * @param tag element name expected
2530     * @throws JiBXException on any error (possible wrapping other exception)
2531     */

2532    public void parsePastElement(String JavaDoc ns, String JavaDoc tag) throws JiBXException {
2533        parsePastStartTag(ns, tag);
2534        int depth = 0;
2535        try {
2536            while (true) {
2537                switch (m_parser.getEventType()) {
2538
2539                    case XmlPullParser.END_TAG:
2540                        if (depth == 0) {
2541                            if (m_parser.getName().equals(tag) &&
2542                                verifyNamespace(ns)) {
2543                                m_parser.nextToken();
2544                                return;
2545                            } else {
2546                                throwEndTagNameError(ns, tag);
2547                            }
2548                        } else {
2549                            depth--;
2550                        }
2551                        break;
2552
2553                    case XmlPullParser.START_TAG:
2554                        depth++;
2555                        break;
2556                    
2557                    default:
2558                        break;
2559
2560                }
2561                m_parser.nextToken();
2562            }
2563        } catch (IOException ex) {
2564            throw new JiBXException("Error accessing document", ex);
2565        } catch (XmlPullParserException ex) {
2566            throw new JiBXException
2567                ("Error parsing document " + buildPositionString(), ex);
2568        }
2569    }
2570
2571    /**
2572     * Returns current element name.
2573     *
2574     * @return local name part of name, or <code>null</code> if not at a start
2575     * or end tag
2576     * @throws JiBXException if error from parser
2577     */

2578    public String JavaDoc getElementName() throws JiBXException {
2579        try {
2580            int type = m_parser.getEventType();
2581            if (type == XmlPullParser.START_TAG ||
2582                type == XmlPullParser.END_TAG) {
2583                return m_parser.getName();
2584            } else {
2585                return null;
2586            }
2587        } catch (XmlPullParserException ex) {
2588            throw new JiBXException
2589                ("Error parsing document " + buildPositionString(), ex);
2590        }
2591    }
2592
2593    /**
2594     * Returns current element namespace URI.
2595     *
2596     * @return namespace URI of name, or <code>null</code> if not at a start
2597     * or end tag
2598     * @throws JiBXException if error from parser
2599     */

2600    public String JavaDoc getElementNamespace() throws JiBXException {
2601        try {
2602            int type = m_parser.getEventType();
2603            if (type == XmlPullParser.START_TAG ||
2604                type == XmlPullParser.END_TAG) {
2605                return m_parser.getNamespace();
2606            } else {
2607                return null;
2608            }
2609        } catch (XmlPullParserException ex) {
2610            throw new JiBXException
2611                ("Error parsing document " + buildPositionString(), ex);
2612        }
2613    }
2614
2615    /**
2616     * Throw exception with start tag and position information.
2617     *
2618     * @param msg exception message text
2619     * @exception JiBXException always thrown
2620     */

2621    public void throwStartTagException(String JavaDoc msg) throws JiBXException {
2622        throw new JiBXException(msg + " at tag " + currentNameString() +
2623            buildPositionString());
2624    }
2625
2626    /**
2627     * Throw exception with start tag, position information, and nested
2628     * exception.
2629     *
2630     * @param msg exception message text
2631     * @param ex nested exception
2632     * @exception JiBXException always thrown
2633     */

2634    public void throwStartTagException(String JavaDoc msg, Exception JavaDoc ex)
2635        throws JiBXException {
2636        throw new JiBXException(msg + " at tag " + currentNameString() +
2637            buildPositionString(), ex);
2638    }
2639
2640    /**
2641     * Throw exception with position information.
2642     *
2643     * @param msg exception message text
2644     * @exception JiBXException always thrown
2645     */

2646    public void throwException(String JavaDoc msg) throws JiBXException {
2647        throw new JiBXException(msg + " " + buildPositionString());
2648    }
2649
2650    /**
2651     * Throw exception with position information and nested exception.
2652     *
2653     * @param msg exception message text
2654     * @param ex nested exception
2655     * @exception JiBXException always thrown
2656     */

2657    public void throwException(String JavaDoc msg, Exception JavaDoc ex) throws JiBXException {
2658        throw new JiBXException(msg + " " + buildPositionString(), ex);
2659    }
2660
2661    /**
2662     * Unmarshal document from stream to object. The effect of this is the same
2663     * as if {@link #setDocument} were called, followed by {@link
2664     * #unmarshalElement}
2665     *
2666     * @param ins stream supplying document data
2667     * @param enc document input encoding, or <code>null</code> if to be
2668     * determined by parser
2669     * @return unmarshalled object
2670     * @throws JiBXException if error creating parser
2671     */

2672    public Object JavaDoc unmarshalDocument(InputStream ins, String JavaDoc enc)
2673        throws JiBXException {
2674        setDocument(ins, enc);
2675        return unmarshalElement();
2676    }
2677
2678    /**
2679     * Unmarshal document from reader to object. The effect of this is the same
2680     * as if {@link #setDocument} were called, followed by {@link
2681     * #unmarshalElement}
2682     *
2683     * @param rdr reader supplying document data
2684     * @return unmarshalled object
2685     * @throws JiBXException if error creating parser
2686     */

2687    public Object JavaDoc unmarshalDocument(Reader rdr) throws JiBXException {
2688        setDocument(rdr);
2689        return unmarshalElement();
2690    }
2691
2692    /**
2693     * Unmarshal named document from stream to object. The effect of this is the
2694     * same as if {@link #setDocument} were called, followed by {@link
2695     * #unmarshalElement}
2696     *
2697     * @param ins stream supplying document data
2698     * @param name document name
2699     * @param enc document input encoding, or <code>null</code> if to be
2700     * determined by parser
2701     * @return unmarshalled object
2702     * @throws JiBXException if error creating parser
2703     */

2704    public Object JavaDoc unmarshalDocument(InputStream ins, String JavaDoc name, String JavaDoc enc)
2705        throws JiBXException {
2706        setDocument(ins, name, enc);
2707        return unmarshalElement();
2708    }
2709
2710    /**
2711     * Unmarshal named document from reader to object. The effect of this is the
2712     * same as if {@link #setDocument} were called, followed by {@link
2713     * #unmarshalElement}
2714     *
2715     * @param rdr reader supplying document data
2716     * @param name document name
2717     * @return unmarshalled object
2718     * @throws JiBXException if error creating parser
2719     */

2720    public Object JavaDoc unmarshalDocument(Reader rdr, String JavaDoc name)
2721        throws JiBXException {
2722        setDocument(rdr, name);
2723        return unmarshalElement();
2724    }
2725
2726    /**
2727     * Return the supplied document name.
2728     *
2729     * @return supplied document name (<code>null</code> if none)
2730     */

2731    public String JavaDoc getDocumentName() {
2732        return m_docName;
2733    }
2734
2735    /**
2736     * Return the input encoding, if known. This is only valid after parsing of
2737     * a document has been started.
2738     *
2739     * @return input encoding (<code>null</code> if unknown)
2740     */

2741    public String JavaDoc getInputEncoding() {
2742        return m_streamWrapper.getEncoding();
2743    }
2744
2745    /**
2746     * Push created object to unmarshalling stack. This must be called before
2747     * beginning the unmarshalling of the object. It is only called for objects
2748     * with structure, not for those converted directly to and from text. If the
2749     * object supports setting source location information, the location is also
2750     * set by this method.
2751     *
2752     * @param obj object being unmarshalled
2753     */

2754    public void pushObject(Object JavaDoc obj) {
2755        int depth = m_stackDepth;
2756        if (depth >= m_objectStack.length) {
2757            Object JavaDoc[] stack = new Object JavaDoc[depth*2];
2758            System.arraycopy(m_objectStack, 0, stack, 0, depth);
2759            m_objectStack = stack;
2760        }
2761        m_objectStack[depth] = obj;
2762        m_stackDepth++;
2763        if (obj instanceof ITrackSourceImpl) {
2764            ((ITrackSourceImpl)obj).jibx_setSource(m_docName,
2765                m_parser.getLineNumber(), m_parser.getColumnNumber());
2766        }
2767    }
2768
2769    /**
2770     * Pop unmarshalled object from stack.
2771     *
2772     * @throws JiBXException if no object on stack
2773     */

2774    public void popObject() throws JiBXException {
2775        if (m_stackDepth > 0) {
2776            --m_stackDepth;
2777        } else {
2778            throw new JiBXException("No object on stack");
2779        }
2780    }
2781    
2782    /**
2783     * Get current unmarshalling object stack depth. This allows tracking
2784     * nested calls to unmarshal one object while in the process of
2785     * unmarshalling another object. The bottom item on the stack is always the
2786     * root object being unmarshalled.
2787     *
2788     * @return number of objects in unmarshalling stack
2789     */

2790    public int getStackDepth() {
2791        return m_stackDepth;
2792    }
2793    
2794    /**
2795     * Get object from unmarshalling stack. This stack allows tracking nested
2796     * calls to unmarshal one object while in the process of unmarshalling
2797     * another object. The bottom item on the stack is always the root object
2798     * being unmarshalled.
2799     *
2800     * @param depth object depth in stack to be retrieved (must be in the range
2801     * of zero to the current depth minus one).
2802     * @return object from unmarshalling stack
2803     */

2804    public Object JavaDoc getStackObject(int depth) {
2805        if (depth >= 0 && depth < m_stackDepth) {
2806            return m_objectStack[m_stackDepth-depth-1];
2807        } else {
2808            throw new ArrayIndexOutOfBoundsException JavaDoc("Depth " + depth +
2809                " is out of range");
2810        }
2811    }
2812    
2813    /**
2814     * Get top object on unmarshalling stack. This is safe to call even when no
2815     * objects are on the stack.
2816     *
2817     * @return object from unmarshalling stack, or <code>null</code> if none
2818     */

2819    public Object JavaDoc getStackTop() {
2820        if (m_stackDepth > 0) {
2821            return m_objectStack[m_stackDepth-1];
2822        } else {
2823            return null;
2824        }
2825    }
2826
2827    /**
2828     * Get count of active namespaces.
2829     *
2830     * @return number of active namespaces in stack
2831     * @exception JiBXException on any error (possibly wrapping other exception)
2832     */

2833    public int getActiveNamespaceCount() throws JiBXException {
2834        try {
2835            return m_parser.getNamespaceCount(m_parser.getDepth());
2836        } catch (XmlPullParserException e) {
2837            throw new JiBXException
2838                ("Error parsing document " + buildPositionString(), e);
2839        }
2840    }
2841
2842    /**
2843     * Get URI for an active namespace.
2844     *
2845     * @param index index number of namespace to be returned
2846     * @return URI for namespace at position
2847     * @exception JiBXException on any error (possibly wrapping other exception)
2848     */

2849    public String JavaDoc getActiveNamespaceUri(int index) throws JiBXException {
2850        try {
2851            return m_parser.getNamespaceUri(index);
2852        } catch (XmlPullParserException e) {
2853            throw new JiBXException
2854                ("Error parsing document " + buildPositionString(), e);
2855        }
2856    }
2857
2858    /**
2859     * Get prefix for an active namespace.
2860     *
2861     * @param index stack position of namespace to be returned
2862     * @return prefix for namespace at position
2863     * @exception JiBXException on any error (possibly wrapping other exception)
2864     */

2865    public String JavaDoc getActiveNamespacePrefix(int index) throws JiBXException {
2866        try {
2867            return m_parser.getNamespacePrefix(index);
2868        } catch (XmlPullParserException e) {
2869            throw new JiBXException
2870                ("Error parsing document " + buildPositionString(), e);
2871        }
2872    }
2873    
2874    /**
2875     * Skip past current element.
2876     *
2877     * @exception JiBXException on any error (possibly wrapping other exception)
2878     */

2879    public void skipElement() throws JiBXException {
2880        
2881        // check positioned at start tag
2882
if (!isEnd()) {
2883            
2884            // skip past the start tag
2885
next();
2886            
2887            // loop until end tag reached
2888
int depth = 1;
2889            while (depth > 0) {
2890                if (isEnd()) {
2891                    depth--;
2892                } else {
2893                    depth++;
2894                }
2895                next();
2896            }
2897            
2898        }
2899    }
2900
2901    /**
2902     * Advance to next major parse event. This wraps the base parser call in
2903     * order to catch and handle exceptions, and to preserve a reasonable level
2904     * of parser independence.
2905     *
2906     * @return event type for next major parse event (START_TAG, TEXT, END_TAG,
2907     * or END_DOCUMENT)
2908     * @exception JiBXException on any error (possibly wrapping other exception)
2909     */

2910    public int next() throws JiBXException {
2911        try {
2912            return m_parser.next();
2913        } catch (IOException ex) {
2914            throw new JiBXException("Error accessing document", ex);
2915        } catch (XmlPullParserException ex) {
2916            throw new JiBXException
2917                ("Error parsing document " + buildPositionString(), ex);
2918        }
2919    }
2920
2921    /**
2922     * Advance to next parse event. This wraps the base parser call in order to
2923     * catch and handle exceptions, and to preserve a reasonable level of parser
2924     * independence.
2925     *
2926     * @return event type for next parse event
2927     * @exception JiBXException on any error (possibly wrapping other exception)
2928     */

2929    public int nextToken() throws JiBXException {
2930        try {
2931            return m_parser.nextToken();
2932        } catch (IOException ex) {
2933            throw new JiBXException("Error accessing document", ex);
2934        } catch (XmlPullParserException ex) {
2935            throw new JiBXException
2936                ("Error parsing document " + buildPositionString(), ex);
2937        }
2938    }
2939
2940    /**
2941     * Get the current parse event type. This wraps the base parser call in
2942     * order to catch and handle exceptions, and to preserve a reasonable level
2943     * of parser independence.
2944     *
2945     * @return event type for current parse event
2946     * @exception JiBXException on any error (possibly wrapping other exception)
2947     */

2948    public int currentEvent() throws JiBXException {
2949        try {
2950            return m_parser.getEventType();
2951        } catch (XmlPullParserException ex) {
2952            throw new JiBXException
2953                ("Error parsing document " + buildPositionString(), ex);
2954        }
2955    }
2956
2957    /**
2958     * Get name associated with current parse event.
2959     *
2960     * @return name text for name associated with event (START_ELEMENT,
2961     * END_ELEMENT, or ENTITY_REF only)
2962     * @exception JiBXException on any error (possibly wrapping other exception)
2963     */

2964    public String JavaDoc getName() throws JiBXException {
2965        return m_parser.getName();
2966    }
2967
2968    /**
2969     * Get namespace associated with current parse event.
2970     *
2971     * @return URI for namespace associated with event (START_ELEMENT or
2972     * END_ELEMENT only), empty string if none
2973     * @exception JiBXException on any error (possibly wrapping other exception)
2974     */

2975    public String JavaDoc getNamespace() throws JiBXException {
2976        return m_parser.getNamespace();
2977    }
2978
2979    /**
2980     * Get namespace prefix associated with current parse event.
2981     *
2982     * @return prefix for namespace associated with event (START_ELEMENT or
2983     * END_ELEMENT only), <code>null</code> if none
2984     * @exception JiBXException on any error (possibly wrapping other exception)
2985     */

2986    public String JavaDoc getPrefix() throws JiBXException {
2987        return m_parser.getPrefix();
2988    }
2989
2990    /**
2991     * Get number of attributes for current START_ELEMENT event. The results are
2992     * undefined if called when not at a START_ELEMENT event.
2993     *
2994     * @return number of attributes, or <code>-1</code> if not at START_ELEMENT
2995     * @exception JiBXException on any error (possibly wrapping other exception)
2996     */

2997    public int getAttributeCount() throws JiBXException {
2998        return m_parser.getAttributeCount();
2999    }
3000
3001    /**
3002     * Get attribute name for current START_ELEMENT event. The results are
3003     * undefined if called when not at a START_ELEMENT event.
3004     *
3005     * @param index index number of attribute to be returned
3006     * @return name of attribute at position
3007     * @exception JiBXException on any error (possibly wrapping other exception)
3008     */

3009    public String JavaDoc getAttributeName(int index) throws JiBXException {
3010        return m_parser.getAttributeName(index);
3011    }
3012
3013    /**
3014     * Get attribute namespace for current START_ELEMENT event. The results are
3015     * undefined if called when not at a START_ELEMENT event.
3016     *
3017     * @param index index number of attribute to be returned
3018     * @return namespace URI of attribute at position, empty string if none
3019     * @exception JiBXException on any error (possibly wrapping other exception)
3020     */

3021    public String JavaDoc getAttributeNamespace(int index) throws JiBXException {
3022        return m_parser.getAttributeNamespace(index);
3023    }
3024
3025    /**
3026     * Get attribute namespace prefix for current START_ELEMENT event. The
3027     * results are undefined if called when not at a START_ELEMENT event.
3028     *
3029     * @param index index number of attribute to be returned
3030     * @return prefix for namespace of attribute at position, <code>null</code>
3031     * if none
3032     * @exception JiBXException on any error (possibly wrapping other exception)
3033     */

3034    public String JavaDoc getAttributePrefix(int index) throws JiBXException {
3035        return m_parser.getAttributePrefix(index);
3036    }
3037
3038    /**
3039     * Get attribute value for current START_ELEMENT event. The results are
3040     * undefined if called when not at a START_ELEMENT event.
3041     *
3042     * @param index index number of attribute to be returned
3043     * @return value of attribute at position
3044     * @exception JiBXException on any error (possibly wrapping other exception)
3045     */

3046    public String JavaDoc getAttributeValue(int index) throws JiBXException {
3047        return m_parser.getAttributeValue(index);
3048    }
3049
3050    /**
3051     * Get number of namespace declarations for current START_ELEMENT event. The
3052     * results are undefined if called when not at a START_ELEMENT event.
3053     *
3054     * @return number of namespace declarations, or <code>-1</code> if not at
3055     * START_ELEMENT
3056     * @exception JiBXException on any error (possibly wrapping other exception)
3057     */

3058    public int getNamespaceCount() throws JiBXException {
3059        try {
3060            int level = m_parser.getDepth();
3061            return m_parser.getNamespaceCount(level)-
3062                m_parser.getNamespaceCount(level-1);
3063        } catch (XmlPullParserException e) {
3064            throw new JiBXException
3065                ("Error parsing document " + buildPositionString(), e);
3066        }
3067    }
3068
3069    /**
3070     * Get namespace URI for namespace declaration on current START_ELEMENT
3071     * event. The results are undefined if called when not at a START_ELEMENT
3072     * event.
3073     *
3074     * @param index index number of declaration to be returned
3075     * @return namespace URI for declaration at position
3076     * @exception JiBXException on any error (possibly wrapping other exception)
3077     */

3078    public String JavaDoc getNamespaceUri(int index) throws JiBXException {
3079        try {
3080            int base = m_parser.getNamespaceCount(m_parser.getDepth()-1);
3081            return m_parser.getNamespaceUri(base + index);
3082        } catch (XmlPullParserException e) {
3083            throw new JiBXException
3084                ("Error parsing document " + buildPositionString(), e);
3085        }
3086    }
3087
3088    /**
3089     * Get namespace prefix for namespace declaration on current START_ELEMENT
3090     * event. The results are undefined if called when not at a START_ELEMENT
3091     * event.
3092     *
3093     * @param index index number of declaration to be returned
3094     * @return namespace prefix for declaration at position,
3095     * @exception JiBXException on any error (possibly wrapping other exception)
3096     */

3097    public String JavaDoc getNamespacePrefix(int index) throws JiBXException {
3098        try {
3099            int base = m_parser.getNamespaceCount(m_parser.getDepth()-1);
3100            return m_parser.getNamespacePrefix(base + index);
3101        } catch (XmlPullParserException e) {
3102            throw new JiBXException
3103                ("Error parsing document " + buildPositionString(), e);
3104        }
3105    }
3106
3107    /**
3108     * Get text value for current event.
3109     *
3110     * @return text value for event
3111     * @exception JiBXException on any error (possibly wrapping other exception)
3112     */

3113    public String JavaDoc getText() throws JiBXException {
3114        return m_parser.getText();
3115    }
3116}
Popular Tags