Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/apache/axis/encoding/ser/SimpleListDeserializer.java


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 java.lang.reflect.Array;
20  import java.lang.reflect.Constructor;
21  import java.lang.reflect.InvocationTargetException;
22  import java.util.HashMap;
23  import java.util.Iterator;
24  import java.util.Map;
25  import java.util.Set;
26  import java.util.StringTokenizer;
27  
28  import javax.xml.namespace.QName;
29  
30  import org.apache.axis.description.TypeDesc;
31  import org.apache.axis.encoding.DeserializationContext;
32  import org.apache.axis.encoding.Deserializer;
33  import org.apache.axis.encoding.SimpleType;
34  import org.apache.axis.encoding.TypeMapping;
35  import org.apache.axis.message.SOAPHandler;
36  import org.apache.axis.utils.BeanPropertyDescriptor;
37  import org.apache.axis.utils.Messages;
38  import org.xml.sax.Attributes;
39  import org.xml.sax.SAXException;
40  
41  /**
42   * Deserializer for 
43   * <xsd:simpleType ...>
44   *   <xsd:list itemType="...">
45   * </xsd:simpleType>
46   * based on SimpleDeserializer
47   *
48   * @author Ias (iasandcb@tmax.co.kr)
49   */
50  public class SimpleListDeserializer extends SimpleDeserializer {
51  
52      StringBuffer val = new StringBuffer();
53      private Constructor constructor = null;
54      private Map propertyMap = null;
55      private HashMap attributeMap = null;
56      private DeserializationContext context = null;
57  
58      public QName xmlType;
59      public Class javaType;
60  
61      private TypeDesc typeDesc = null;
62  
63      protected SimpleListDeserializer cacheStringDSer = null;
64      protected QName cacheXMLType = null;
65      /**
66       * The Deserializer is constructed with the xmlType and
67       * javaType (which could be a java primitive like int.class)
68       */
69      public SimpleListDeserializer(Class javaType, QName xmlType) {
70          super (javaType, xmlType);
71  
72          this.xmlType = xmlType;
73          this.javaType = javaType;
74      }
75      public SimpleListDeserializer(Class javaType, QName xmlType, TypeDesc typeDesc) {
76          super (javaType, xmlType, typeDesc);
77  
78          this.xmlType = xmlType;
79          this.javaType = javaType;
80          this.typeDesc = typeDesc;
81      }
82     
83      
84      /**
85       * Reset deserializer for re-use
86       */
87      public void reset() {
88          val.setLength(0); // Reset string buffer back to zero
89          attributeMap = null; // Remove attribute map
90          isNil = false; // Don't know if nil
91          isEnded = false; // Indicate the end of element not yet called
92      }
93  
94      /**
95       * The Factory calls setConstructor.
96       */
97      public void setConstructor(Constructor c)
98      {
99          constructor = c;
100     }
101 
102     /**
103      * There should not be nested elements, so thow and exception if this occurs.
104      */
105     public SOAPHandler onStartChild(String namespace,
106                                     String localName,
107                                     String prefix,
108                                     Attributes attributes,
109                                     DeserializationContext context)
110         throws SAXException
111     {
112         throw new SAXException(
113                 Messages.getMessage("cantHandle00", "SimpleDeserializer"));
114     }
115 
116     /**
117      * Append any characters received to the value.  This method is defined
118      * by Deserializer.
119      */
120     public void characters(char [] chars, int start, int end)
121         throws SAXException
122     {
123         val.append(chars, start, end);
124     }
125 
126     /**
127      * Append any characters to the value.  This method is defined by
128      * Deserializer.
129      */
130     public void onEndElement(String namespace, String localName,
131                            DeserializationContext context)
132         throws SAXException
133     {
134         if (isNil || val == null) {
135             value = null;
136             return;
137         }
138         try {
139             value = makeValue(val.toString());
140         } catch (InvocationTargetException ite) {
141             Throwable realException = ite.getTargetException();
142             if (realException instanceof Exception)
143                throw new SAXException((Exception)realException);
144             else
145                throw new SAXException(ite.getMessage());
146         } catch (Exception e) {
147             throw new SAXException(e);
148         }
149 
150         // If this is a SimpleType, set attributes we have stashed away
151         setSimpleTypeAttributes();
152     }
153 
154     /**
155      * Convert the string that has been accumulated into an Object.  Subclasses
156      * may override this. 
157      * @param source the serialized value to be deserialized
158      * @throws Exception any exception thrown by this method will be wrapped
159      */
160     public Object makeValue(String source) throws Exception
161     {
162         // According to XML Schema Spec Part 0: Primer 2.3.1 - white space delimitor
163         StringTokenizer tokenizer = new StringTokenizer(source.trim());
164         int length = tokenizer.countTokens();
165         Object list = Array.newInstance(javaType, length);
166         for (int i = 0; i < length; i++) {
167             String token = tokenizer.nextToken();
168             Array.set(list, i, makeUnitValue(token));
169         }
170         return list;
171     }
172 
173     private Object makeUnitValue(String source) throws Exception
174     {
175         // If the javaType is a boolean, except a number of different sources
176         if (javaType == boolean.class || javaType == Boolean.class) {
177             // This is a pretty lame test, but it is what the previous code did.
178             switch (source.charAt(0)) {
179                 case '0': case 'f': case 'F':
180                     return Boolean.FALSE;
181                     
182                    case '1': case 't': case 'T':
183                        return Boolean.TRUE;
184                        
185                       default:
186                           throw new NumberFormatException(
187                                   Messages.getMessage("badBool00"));
188             }
189             
190         }
191         
192         // If expecting a Float or a Double, need to accept some special cases.
193         if (javaType == float.class ||
194                 javaType == java.lang.Float.class) {
195             if (source.equals("NaN")) {
196                 return new Float(Float.NaN);
197             } else if (source.equals("INF")) {
198                 return new Float(Float.POSITIVE_INFINITY);
199             } else if (source.equals("-INF")) {
200                 return new Float(Float.NEGATIVE_INFINITY);
201             }
202         }
203         if (javaType == double.class ||
204                 javaType == java.lang.Double.class) {
205             if (source.equals("NaN")) {
206                 return new Double(Double.NaN);
207             } else if (source.equals("INF")) {
208                 return new Double(Double.POSITIVE_INFINITY);
209             } else if (source.equals("-INF")) {
210                 return new Double(Double.NEGATIVE_INFINITY);
211             }
212         }
213         if (javaType == QName.class) {
214             int colon = source.lastIndexOf(":");
215             String namespace = colon < 0 ? "" :
216                 context.getNamespaceURI(source.substring(0, colon));
217             String localPart = colon < 0 ? source : 
218                 source.substring(colon + 1);
219             return new QName(namespace, localPart);
220         }
221 
222         return constructor.newInstance(new Object [] { source });
223     }
224     /**
225      * Set the bean properties that correspond to element attributes.
226      *
227      * This method is invoked after startElement when the element requires
228      * deserialization (i.e. the element is not an href and the value is not nil.)
229      * @param namespace is the namespace of the element
230      * @param localName is the name of the element
231      * @param prefix is the prefix of the element
232      * @param attributes are the attributes on the element...used to get the type
233      * @param context is the DeserializationContext
234      */
235     public void onStartElement(String namespace, String localName,
236                                String prefix, Attributes attributes,
237                                DeserializationContext context)
238             throws SAXException
239     {
240 
241         this.context = context;
242 
243         // If we have no metadata, we have no attributes.  Q.E.D.
244         if (typeDesc == null)
245             return;
246 
247         // loop through the attributes and set bean properties that
248         // correspond to attributes
249         for (int i=0; i < attributes.getLength(); i++) {
250             QName attrQName = new QName(attributes.getURI(i),
251                                         attributes.getLocalName(i));
252             String fieldName = typeDesc.getFieldNameForAttribute(attrQName);
253             if (fieldName == null)
254                 continue;
255 
256             // look for the attribute property
257             BeanPropertyDescriptor bpd =
258                     (BeanPropertyDescriptor) propertyMap.get(fieldName);
259             if (bpd != null) {
260                 if (!bpd.isWriteable() || bpd.isIndexed() ) continue ;
261 
262                 // determine the QName for this child element
263                 TypeMapping tm = context.getTypeMapping();
264                 Class type = bpd.getType();
265                 QName qn = tm.getTypeQName(type);
266                 if (qn == null)
267                     throw new SAXException(
268                             Messages.getMessage("unregistered00", type.toString()));
269 
270                 // get the deserializer
271                 Deserializer dSer = context.getDeserializerForType(qn);
272                 if (dSer == null)
273                     throw new SAXException(
274                             Messages.getMessage("noDeser00", type.toString()));
275                 if (! (dSer instanceof SimpleListDeserializer))
276                     throw new SAXException(
277                             Messages.getMessage("AttrNotSimpleType00",
278                                                  bpd.getName(),
279                                                  type.toString()));
280 
281                 // Success!  Create an object from the string and save
282                 // it in our attribute map for later.
283                 if (attributeMap == null) {
284                     attributeMap = new HashMap();
285                 }
286                 try {
287                     Object val = ((SimpleListDeserializer)dSer).
288                         makeValue(attributes.getValue(i));
289                     attributeMap.put(fieldName, val);
290                 } catch (Exception e) {
291                     throw new SAXException(e);
292                 }
293             } // if
294         } // attribute loop
295     } // onStartElement
296 
297     /**
298      * Process any attributes we may have encountered (in onStartElement)
299      */
300     private void setSimpleTypeAttributes() throws SAXException {
301         // if this isn't a simpleType bean, wont have attributes
302         if (! SimpleType.class.isAssignableFrom(javaType) ||
303             attributeMap == null)
304             return;
305 
306         // loop through map
307         Set entries = attributeMap.entrySet();
308         for (Iterator iterator = entries.iterator(); iterator.hasNext();) {
309             Map.Entry entry = (Map.Entry) iterator.next();
310             String name = (String) entry.getKey();
311             Object val = entry.getValue();
312 
313             BeanPropertyDescriptor bpd =
314                     (BeanPropertyDescriptor) propertyMap.get(name);
315             if (!bpd.isWriteable() || bpd.isIndexed()) continue;
316             try {
317                 bpd.set(value, val );
318             } catch (Exception e) {
319                 throw new SAXException(e);
320             }
321         }
322     }
323 
324 }