KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jibx > extras > TypedArrayMapper


1 /*
2 Copyright (c) 2003-2004, 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.extras;
30
31 import java.lang.reflect.Array JavaDoc;
32 import java.util.ArrayList JavaDoc;
33
34 import org.jibx.runtime.IAliasable;
35 import org.jibx.runtime.IMarshallable;
36 import org.jibx.runtime.IMarshaller;
37 import org.jibx.runtime.IMarshallingContext;
38 import org.jibx.runtime.IUnmarshaller;
39 import org.jibx.runtime.IUnmarshallingContext;
40 import org.jibx.runtime.JiBXException;
41 import org.jibx.runtime.impl.MarshallingContext;
42 import org.jibx.runtime.impl.UnmarshallingContext;
43
44 /**
45  * <p>Custom marshaller/unmarshaller for reference arrays of a particular type.
46  * This handles mapping arrays typed as <code>object-type[]</code>, where the
47  * <i>object-type</i> is any class name (not a primitive type). All items in the
48  * array must be of a mapped type. If a name is specified by the mapping
49  * definition that name is used as a wrapper around the elements representing
50  * the items in the array; otherwise, the elements are just handled inline.</p>
51  *
52  * @author Dennis M. Sosnoski
53  * @version 1.0
54  */

55
56 public class TypedArrayMapper
57     implements IMarshaller, IUnmarshaller, IAliasable {
58     
59     private static final Object JavaDoc[] DUMMY_ARRAY = {};
60     
61     private String JavaDoc m_uri;
62     private int m_index;
63     private String JavaDoc m_name;
64     private Object JavaDoc[] m_baseArray;
65     private ArrayList JavaDoc m_holder;
66     
67     /**
68      * Aliased constructor. This takes a name definition for the top-level
69      * wrapper element. It'll be used by JiBX when a name is supplied by the
70      * mapping which references this custom marshaller/unmarshaller.
71      *
72      * @param uri namespace URI for the top-level element
73      * @param index namespace index corresponding to the defined URI within the
74      * marshalling context definitions
75      * @param name local name for the top-level element
76      * @param type class name for type of items in array
77      */

78     
79     public TypedArrayMapper(String JavaDoc uri, int index, String JavaDoc name, String JavaDoc type) {
80         
81         // save the simple values
82
m_uri = uri;
83         m_index = index;
84         m_name = name;
85         
86         // strip trailing array bracket sets from type (at least one)
87
int dimen = 0;
88         while (type.endsWith("[]")) {
89             type = type.substring(0, type.length()-2);
90             dimen++;
91         }
92         
93         // now get the class used for array items
94
try {
95             
96             // first try loading item class from context classloader
97
Class JavaDoc clas = null;
98             ClassLoader JavaDoc loader =
99                 Thread.currentThread().getContextClassLoader();
100             if (loader != null) {
101                 try {
102                     clas = loader.loadClass(type);
103                 } catch (ClassNotFoundException JavaDoc e) { /* fall through */ }
104             }
105             if (clas == null) {
106                 
107                 // if not found, try the loader that loaded this class
108
clas = UnmarshallingContext.class.getClassLoader().
109                     loadClass(type);
110             }
111             
112             // create a dummy base array of specified type
113
int[] dimens = new int[dimen];
114             m_baseArray = (Object JavaDoc[])Array.newInstance(clas, dimens);
115             
116         } catch (ClassNotFoundException JavaDoc e) {
117             throw new IllegalArgumentException JavaDoc
118                 ("Error loading array item class " + type + ": " +
119                     e.getMessage());
120         }
121     }
122     
123     /**
124      * Class only constructor. This just sets up for an XML representation with
125      * no element wrapping the actual item structures. It'll be used by JiBX
126      * when no name information is supplied by the mapping which references this
127      * custom marshaller/unmarshaller.
128      *
129      * @param type class name for type of items in array
130      */

131     
132     public TypedArrayMapper(String JavaDoc type) {
133         this(null, 0, null, type);
134     }
135     
136     /* (non-Javadoc)
137      * @see org.jibx.runtime.IMarshaller#isExtension(int)
138      */

139     
140     public boolean isExtension(int index) {
141         return false;
142     }
143
144     /* (non-Javadoc)
145      * @see org.jibx.runtime.IMarshaller#marshal(java.lang.Object,
146      * org.jibx.runtime.IMarshallingContext)
147      */

148     
149     public void marshal(Object JavaDoc obj, IMarshallingContext ictx)
150         throws JiBXException {
151         
152         // make sure the parameters are as expected
153
if (obj == null) {
154             if (m_name == null) {
155                 throw new JiBXException
156                     ("null array not allowed without wrapper");
157             }
158         } else if (!(ictx instanceof MarshallingContext)) {
159             throw new JiBXException("Marshalling context not of expected type");
160         } else {
161             
162             // verify object as a handled array type
163
Class JavaDoc clas = obj.getClass();
164             if (!clas.isArray() || !IMarshallable.class.
165                 isAssignableFrom(clas.getComponentType())) {
166                 throw new JiBXException("Invalid object type for marshaller");
167             } else {
168             
169                 // start by generating start tag for container
170
MarshallingContext ctx = (MarshallingContext)ictx;
171                 Object JavaDoc[] array = (Object JavaDoc[])obj;
172                 if (m_name != null) {
173                     ctx.startTag(m_index, m_name);
174                 }
175         
176                 // loop through all entries in array
177
for (int i = 0; i < array.length; i++) {
178                     Object JavaDoc item = array[i];
179                     if (item == null) {
180                         throw new JiBXException("Null value at offset " + i +
181                             " not supported");
182                     } else {
183                         ((IMarshallable)item).marshal(ctx);
184                     }
185                 }
186         
187                 // finish with end tag for container element
188
if (m_name != null) {
189                     ctx.endTag(m_index, m_name);
190                 }
191                 
192             }
193         }
194     }
195
196     /* (non-Javadoc)
197      * @see org.jibx.runtime.IUnmarshaller#isPresent(org.jibx.runtime.IUnmarshallingContext)
198      */

199      
200     public boolean isPresent(IUnmarshallingContext ctx) throws JiBXException {
201         return ctx.isAt(m_uri, m_name);
202     }
203
204     /* (non-Javadoc)
205      * @see org.jibx.runtime.IUnmarshaller#unmarshal(java.lang.Object,
206      * org.jibx.runtime.IUnmarshallingContext)
207      */

208      
209     public Object JavaDoc unmarshal(Object JavaDoc obj, IUnmarshallingContext ictx)
210         throws JiBXException {
211         
212         // make sure we're at the appropriate start tag
213
UnmarshallingContext ctx = (UnmarshallingContext)ictx;
214         if (m_name != null) {
215             if (ctx.isAt(m_uri, m_name)) {
216                 ctx.parsePastStartTag(m_uri, m_name);
217             } else {
218                 return null;
219             }
220         }
221         
222         // create new array if needed
223
if (m_holder == null) {
224             m_holder = new ArrayList JavaDoc();
225         }
226         
227         // process all items present in document
228
while (!ctx.isEnd()) {
229             Object JavaDoc item = ctx.unmarshalElement();
230             m_holder.add(item);
231         }
232         
233         // discard close tag if used
234
if (m_name != null) {
235             ctx.parsePastEndTag(m_uri, m_name);
236         }
237         
238         // return array containing all items
239
Object JavaDoc[] result = m_holder.toArray(m_baseArray);
240         m_holder.clear();
241         return result;
242     }
243 }
Popular Tags