KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > axis > encoding > ser > SimpleDeserializer


1 /*
2  * Copyright 2001-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.apache.axis.encoding.ser;
18
19 import org.apache.axis.description.TypeDesc;
20 import org.apache.axis.encoding.DeserializationContext;
21 import org.apache.axis.encoding.Deserializer;
22 import org.apache.axis.encoding.DeserializerImpl;
23 import org.apache.axis.encoding.SimpleType;
24 import org.apache.axis.encoding.TypeMapping;
25 import org.apache.axis.message.SOAPHandler;
26 import org.apache.axis.utils.BeanPropertyDescriptor;
27 import org.apache.axis.utils.BeanUtils;
28 import org.apache.axis.utils.Messages;
29 import org.xml.sax.Attributes JavaDoc;
30 import org.xml.sax.SAXException JavaDoc;
31
32 import javax.xml.namespace.QName JavaDoc;
33 import java.io.CharArrayWriter JavaDoc;
34 import java.lang.reflect.Constructor JavaDoc;
35 import java.lang.reflect.InvocationTargetException JavaDoc;
36 import java.util.HashMap JavaDoc;
37 import java.util.Iterator JavaDoc;
38 import java.util.Map JavaDoc;
39 import java.util.Set JavaDoc;
40
41 /**
42  * A deserializer for any simple type with a (String) constructor. Note:
43  * this class is designed so that subclasses need only override the makeValue
44  * method in order to construct objects of their own type.
45  *
46  * @author Glen Daniels (gdaniels@apache.org)
47  * @author Sam Ruby (rubys@us.ibm.com)
48  * Modified for JAX-RPC @author Rich Scheuerle (scheu@us.ibm.com)
49  */

50 public class SimpleDeserializer extends DeserializerImpl {
51     
52     private static final Class JavaDoc[] STRING_STRING_CLASS =
53         new Class JavaDoc [] {String JavaDoc.class, String JavaDoc.class};
54
55     public static final Class JavaDoc[] STRING_CLASS =
56         new Class JavaDoc [] {String JavaDoc.class};
57
58     private final CharArrayWriter JavaDoc val = new CharArrayWriter JavaDoc();
59     private Constructor JavaDoc constructor = null;
60     private Map JavaDoc propertyMap = null;
61     private HashMap JavaDoc attributeMap = null;
62     
63     public QName JavaDoc xmlType;
64     public Class JavaDoc javaType;
65     
66     private TypeDesc typeDesc = null;
67
68     protected DeserializationContext context = null;
69     protected SimpleDeserializer cacheStringDSer = null;
70     protected QName JavaDoc cacheXMLType = null;
71     /**
72      * The Deserializer is constructed with the xmlType and
73      * javaType (which could be a java primitive like int.class)
74      */

75     public SimpleDeserializer(Class JavaDoc javaType, QName JavaDoc xmlType) {
76          this.xmlType = xmlType;
77         this.javaType = javaType;
78         
79         init();
80     }
81
82     public SimpleDeserializer(Class JavaDoc javaType, QName JavaDoc xmlType, TypeDesc typeDesc) {
83         this.xmlType = xmlType;
84         this.javaType = javaType;
85         this.typeDesc = typeDesc;
86         
87         init();
88     }
89
90     /**
91      * Initialize the typeDesc, property descriptors and propertyMap.
92      */

93     private void init() {
94         // The typeDesc and map array are only necessary
95
// if this class extends SimpleType.
96
if (SimpleType.class.isAssignableFrom(javaType)) {
97             // Set the typeDesc if not already set
98
if (typeDesc == null) {
99                 typeDesc = TypeDesc.getTypeDescForClass(javaType);
100             }
101         }
102
103         // Get the cached propertyDescriptor from the type or
104
// generate a fresh one.
105
if (typeDesc != null) {
106             propertyMap = typeDesc.getPropertyDescriptorMap();
107         } else {
108             BeanPropertyDescriptor[] pd = BeanUtils.getPd(javaType, null);
109             propertyMap = new HashMap JavaDoc();
110             for (int i = 0; i < pd.length; i++) {
111                 BeanPropertyDescriptor descriptor = pd[i];
112                 propertyMap.put(descriptor.getName(), descriptor);
113             }
114         }
115     }
116     
117     /**
118      * Reset deserializer for re-use
119      */

120     public void reset() {
121         val.reset();
122         attributeMap = null; // Remove attribute map
123
isNil = false; // Don't know if nil
124
isEnded = false; // Indicate the end of element not yet called
125
}
126     
127     /**
128      * The Factory calls setConstructor.
129      */

130     public void setConstructor(Constructor JavaDoc c)
131     {
132         constructor = c;
133     }
134     
135     /**
136      * There should not be nested elements, so thow and exception if this occurs.
137      */

138     public SOAPHandler onStartChild(String JavaDoc namespace,
139                                     String JavaDoc localName,
140                                     String JavaDoc prefix,
141                                     Attributes JavaDoc attributes,
142                                     DeserializationContext context)
143             throws SAXException JavaDoc
144     {
145         throw new SAXException JavaDoc(
146                 Messages.getMessage("cantHandle00", "SimpleDeserializer"));
147     }
148     
149     /**
150      * Append any characters received to the value. This method is defined
151      * by Deserializer.
152      */

153     public void characters(char [] chars, int start, int end)
154             throws SAXException JavaDoc
155     {
156         val.write(chars,start,end);
157     }
158     
159     /**
160      * Append any characters to the value. This method is defined by
161      * Deserializer.
162      */

163     public void onEndElement(String JavaDoc namespace, String JavaDoc localName,
164                              DeserializationContext context)
165             throws SAXException JavaDoc
166     {
167         if (isNil) {
168             value = null;
169             return;
170         }
171         try {
172             value = makeValue(val.toString());
173         } catch (InvocationTargetException JavaDoc ite) {
174             Throwable JavaDoc realException = ite.getTargetException();
175             if (realException instanceof Exception JavaDoc)
176                 throw new SAXException JavaDoc((Exception JavaDoc)realException);
177             else
178                 throw new SAXException JavaDoc(ite.getMessage());
179         } catch (Exception JavaDoc e) {
180             throw new SAXException JavaDoc(e);
181         }
182         
183         // If this is a SimpleType, set attributes we have stashed away
184
setSimpleTypeAttributes();
185     }
186     
187     /**
188      * Convert the string that has been accumulated into an Object. Subclasses
189      * may override this. Note that if the javaType is a primitive, the returned
190      * object is a wrapper class.
191      * @param source the serialized value to be deserialized
192      * @throws Exception any exception thrown by this method will be wrapped
193      */

194     public Object JavaDoc makeValue(String JavaDoc source) throws Exception JavaDoc
195     {
196         if (javaType == java.lang.String JavaDoc.class) {
197             return source;
198         }
199
200         // Trim whitespace if non-String
201
source = source.trim();
202
203         if (source.length() == 0 && typeDesc == null) {
204             return null;
205         }
206         
207         // if constructor is set skip all basic java type checks
208
if (this.constructor == null) {
209             Object JavaDoc value = makeBasicValue(source);
210             if (value != null) {
211                 return value;
212             }
213         }
214             
215         Object JavaDoc [] args = null;
216         
217         boolean isQNameSubclass = QName JavaDoc.class.isAssignableFrom(javaType);
218
219         if (isQNameSubclass) {
220             int colon = source.lastIndexOf(":");
221             String JavaDoc namespace = colon < 0 ? "" :
222                 context.getNamespaceURI(source.substring(0, colon));
223             String JavaDoc localPart = colon < 0 ? source : source.substring(colon + 1);
224             args = new Object JavaDoc [] {namespace, localPart};
225         }
226
227         if (constructor == null) {
228             try {
229                 if (isQNameSubclass) {
230                     constructor =
231                         javaType.getDeclaredConstructor(STRING_STRING_CLASS);
232                 } else {
233                     constructor =
234                         javaType.getDeclaredConstructor(STRING_CLASS);
235                 }
236             } catch (Exception JavaDoc e) {
237                 return null;
238             }
239         }
240         
241         if(constructor.getParameterTypes().length==0){
242             try {
243                 Object JavaDoc obj = constructor.newInstance(new Object JavaDoc[]{});
244                 obj.getClass().getMethod("set_value", new Class JavaDoc[]{String JavaDoc.class})
245                         .invoke(obj, new Object JavaDoc[]{source});
246                 return obj;
247             } catch (Exception JavaDoc e){
248                 //Ignore exception
249
}
250         }
251         if (args == null) {
252             args = new Object JavaDoc[]{source};
253         }
254         return constructor.newInstance(args);
255     }
256
257     private Object JavaDoc makeBasicValue(String JavaDoc source) throws Exception JavaDoc {
258         // If the javaType is a boolean, except a number of different sources
259
if (javaType == boolean.class ||
260             javaType == Boolean JavaDoc.class) {
261             // This is a pretty lame test, but it is what the previous code did.
262
switch (source.charAt(0)) {
263                 case '0': case 'f': case 'F':
264                     return Boolean.FALSE;
265                     
266                 case '1': case 't': case 'T':
267                     return Boolean.TRUE;
268                     
269                 default:
270                     throw new NumberFormatException JavaDoc(
271                             Messages.getMessage("badBool00"));
272                 }
273             
274         }
275         
276         // If expecting a Float or a Double, need to accept some special cases.
277
if (javaType == float.class ||
278             javaType == java.lang.Float JavaDoc.class) {
279             if (source.equals("NaN")) {
280                 return new Float JavaDoc(Float.NaN);
281             } else if (source.equals("INF")) {
282                 return new Float JavaDoc(Float.POSITIVE_INFINITY);
283             } else if (source.equals("-INF")) {
284                 return new Float JavaDoc(Float.NEGATIVE_INFINITY);
285             } else {
286                 return new Float JavaDoc(source);
287             }
288         }
289         
290         if (javaType == double.class ||
291             javaType == java.lang.Double JavaDoc.class) {
292             if (source.equals("NaN")) {
293                 return new Double JavaDoc(Double.NaN);
294             } else if (source.equals("INF")) {
295                 return new Double JavaDoc(Double.POSITIVE_INFINITY);
296             } else if (source.equals("-INF")) {
297                 return new Double JavaDoc(Double.NEGATIVE_INFINITY);
298             } else {
299                 return new Double JavaDoc(source);
300             }
301         }
302         
303         if (javaType == int.class ||
304             javaType == java.lang.Integer JavaDoc.class) {
305             return new Integer JavaDoc(source);
306         }
307         
308         if (javaType == short.class ||
309             javaType == java.lang.Short JavaDoc.class) {
310             return new Short JavaDoc(source);
311         }
312         
313         if (javaType == long.class ||
314             javaType == java.lang.Long JavaDoc.class) {
315             return new Long JavaDoc(source);
316         }
317         
318         if (javaType == byte.class ||
319             javaType == java.lang.Byte JavaDoc.class) {
320             return new Byte JavaDoc(source);
321         }
322         
323         if (javaType == org.apache.axis.types.URI.class) {
324             return new org.apache.axis.types.URI(source);
325         }
326
327         return null;
328     }
329         
330     /**
331      * Set the bean properties that correspond to element attributes.
332      *
333      * This method is invoked after startElement when the element requires
334      * deserialization (i.e. the element is not an href and the value is not nil.)
335      * @param namespace is the namespace of the element
336      * @param localName is the name of the element
337      * @param prefix is the prefix of the element
338      * @param attributes are the attributes on the element...used to get the type
339      * @param context is the DeserializationContext
340      */

341     public void onStartElement(String JavaDoc namespace, String JavaDoc localName,
342                                String JavaDoc prefix, Attributes JavaDoc attributes,
343                                DeserializationContext context)
344             throws SAXException JavaDoc
345     {
346         
347         this.context = context;
348
349         // loop through the attributes and set bean properties that
350
// correspond to attributes
351
for (int i=0; i < attributes.getLength(); i++) {
352             QName JavaDoc attrQName = new QName JavaDoc(attributes.getURI(i),
353                                         attributes.getLocalName(i));
354             
355             String JavaDoc fieldName = attributes.getLocalName(i);
356             
357             if(typeDesc != null) {
358                 fieldName = typeDesc.getFieldNameForAttribute(attrQName);
359                 if (fieldName == null)
360                     continue;
361             }
362
363             if (propertyMap == null)
364                 continue;
365             
366             // look for the attribute property
367
BeanPropertyDescriptor bpd =
368                     (BeanPropertyDescriptor) propertyMap.get(fieldName);
369             if (bpd != null) {
370                 if (!bpd.isWriteable() || bpd.isIndexed() ) continue ;
371                 
372                 // determine the QName for this child element
373
TypeMapping tm = context.getTypeMapping();
374                 Class JavaDoc type = bpd.getType();
375                 QName JavaDoc qn = tm.getTypeQName(type);
376                 if (qn == null)
377                     throw new SAXException JavaDoc(
378                             Messages.getMessage("unregistered00", type.toString()));
379                 
380                 // get the deserializer
381
Deserializer dSer = context.getDeserializerForType(qn);
382                 if (dSer == null)
383                     throw new SAXException JavaDoc(
384                             Messages.getMessage("noDeser00", type.toString()));
385                 if (! (dSer instanceof SimpleDeserializer))
386                     throw new SAXException JavaDoc(
387                             Messages.getMessage("AttrNotSimpleType00",
388                                                 bpd.getName(),
389                                                 type.toString()));
390                 
391                 // Success! Create an object from the string and save
392
// it in our attribute map for later.
393
if (attributeMap == null) {
394                     attributeMap = new HashMap JavaDoc();
395                 }
396                 try {
397                     Object JavaDoc val = ((SimpleDeserializer)dSer).
398                             makeValue(attributes.getValue(i));
399                     attributeMap.put(fieldName, val);
400                 } catch (Exception JavaDoc e) {
401                     throw new SAXException JavaDoc(e);
402                 }
403             } // if
404
} // attribute loop
405
} // onStartElement
406

407     /**
408      * Process any attributes we may have encountered (in onStartElement)
409      */

410     private void setSimpleTypeAttributes() throws SAXException JavaDoc {
411         if (attributeMap == null)
412             return;
413         
414         // loop through map
415
Set JavaDoc entries = attributeMap.entrySet();
416         for (Iterator JavaDoc iterator = entries.iterator(); iterator.hasNext();) {
417             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) iterator.next();
418             String JavaDoc name = (String JavaDoc) entry.getKey();
419             Object JavaDoc val = entry.getValue();
420             
421             BeanPropertyDescriptor bpd =
422                     (BeanPropertyDescriptor) propertyMap.get(name);
423             if (!bpd.isWriteable() || bpd.isIndexed()) continue;
424             try {
425                 bpd.set(value, val );
426             } catch (Exception JavaDoc e) {
427                 throw new SAXException JavaDoc(e);
428             }
429         }
430     }
431     
432 }
433
Popular Tags