KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > jxpath > util > BasicTypeConverter


1 /*
2  * Copyright 1999-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 package org.apache.commons.jxpath.util;
17
18 import java.lang.reflect.Array JavaDoc;
19 import java.lang.reflect.Modifier JavaDoc;
20 import java.util.ArrayList JavaDoc;
21 import java.util.Collection JavaDoc;
22 import java.util.Collections JavaDoc;
23 import java.util.HashSet JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.List JavaDoc;
26 import java.util.Set JavaDoc;
27
28 import org.apache.commons.beanutils.ConvertUtils;
29 import org.apache.commons.beanutils.Converter;
30 import org.apache.commons.jxpath.JXPathException;
31 import org.apache.commons.jxpath.NodeSet;
32 import org.apache.commons.jxpath.Pointer;
33
34 /**
35  * The default implementation of TypeConverter.
36  *
37  * @author Dmitri Plotnikov
38  * @version $Revision: 1.15 $ $Date: 2004/07/25 13:16:04 $
39  */

40 public class BasicTypeConverter implements TypeConverter {
41
42     /**
43      * Returns true if it can convert the supplied
44      * object to the specified class.
45      */

46     public boolean canConvert(Object JavaDoc object, Class JavaDoc toType) {
47         if (object == null) {
48             return true;
49         }
50
51         if (toType == Object JavaDoc.class) {
52             return true;
53         }
54
55         Class JavaDoc fromType = object.getClass();
56         if (fromType.equals(toType)) {
57             return true;
58         }
59
60         if (toType.isAssignableFrom(fromType)) {
61             return true;
62         }
63
64         if (toType == String JavaDoc.class) {
65             return true;
66         }
67
68         if (object instanceof Boolean JavaDoc) {
69             if (toType == boolean.class
70                 || Number JavaDoc.class.isAssignableFrom(toType)) {
71                 return true;
72             }
73         }
74         else if (object instanceof Number JavaDoc) {
75             if (toType.isPrimitive()
76                 || Number JavaDoc.class.isAssignableFrom(toType)) {
77                 return true;
78             }
79         }
80         else if (object instanceof Character JavaDoc) {
81             if (toType == char.class) {
82                 return true;
83             }
84         }
85         else if (object instanceof String JavaDoc) {
86             if (toType.isPrimitive()) {
87                 return true;
88             }
89             if (toType == Boolean JavaDoc.class
90                 || toType == Character JavaDoc.class
91                 || toType == Byte JavaDoc.class
92                 || toType == Short JavaDoc.class
93                 || toType == Integer JavaDoc.class
94                 || toType == Long JavaDoc.class
95                 || toType == Float JavaDoc.class
96                 || toType == Double JavaDoc.class) {
97                 return true;
98             }
99         }
100         else if (fromType.isArray()) {
101             // Collection -> array
102
if (toType.isArray()) {
103                 Class JavaDoc cType = toType.getComponentType();
104                 int length = Array.getLength(object);
105                 for (int i = 0; i < length; i++) {
106                     Object JavaDoc value = Array.get(object, i);
107                     if (!canConvert(value, cType)) {
108                         return false;
109                     }
110                 }
111                 return true;
112             }
113             else if (Collection JavaDoc.class.isAssignableFrom(toType)) {
114                 return canCreateCollection(toType);
115             }
116             else {
117                 if (Array.getLength(object) > 0) {
118                     Object JavaDoc value = Array.get(object, 0);
119                     return canConvert(value, toType);
120                 }
121                 else {
122                     return canConvert("", toType);
123                 }
124             }
125         }
126         else if (object instanceof Collection JavaDoc) {
127             // Collection -> array
128
if (toType.isArray()) {
129                 Class JavaDoc cType = toType.getComponentType();
130                 Iterator JavaDoc it = ((Collection JavaDoc) object).iterator();
131                 while (it.hasNext()) {
132                     Object JavaDoc value = it.next();
133                     if (!canConvert(value, cType)) {
134                         return false;
135                     }
136                 }
137                 return true;
138             }
139             else if (Collection JavaDoc.class.isAssignableFrom(toType)) {
140                 return canCreateCollection(toType);
141             }
142             else {
143                 if (((Collection JavaDoc) object).size() > 0) {
144                     Object JavaDoc value;
145                     if (object instanceof List JavaDoc) {
146                         value = ((List JavaDoc) object).get(0);
147                     }
148                     else {
149                         Iterator JavaDoc it = ((Collection JavaDoc) object).iterator();
150                         value = it.next();
151                     }
152                     return canConvert(value, toType);
153                 }
154                 else {
155                     return canConvert("", toType);
156                 }
157             }
158         }
159         else if (object instanceof NodeSet) {
160             return canConvert(((NodeSet) object).getValues(), toType);
161         }
162         else if (object instanceof Pointer) {
163             return canConvert(((Pointer) object).getValue(), toType);
164         }
165         return ConvertUtils.lookup(toType) != null;
166     }
167
168     /**
169      * Converts the supplied object to the specified
170      * type. Throws a runtime exception if the conversion is
171      * not possible.
172      */

173     public Object JavaDoc convert(Object JavaDoc object, Class JavaDoc toType) {
174         if (object == null) {
175             if (toType.isPrimitive()) {
176                 return convertNullToPrimitive(toType);
177             }
178             return null;
179         }
180
181         if (toType == Object JavaDoc.class) {
182             if (object instanceof NodeSet) {
183                 return convert(((NodeSet) object).getValues(), toType);
184             }
185             else if (object instanceof Pointer) {
186                 return convert(((Pointer) object).getValue(), toType);
187             }
188             return object;
189         }
190
191         Class JavaDoc fromType = object.getClass();
192         if (fromType.equals(toType) || toType.isAssignableFrom(fromType)) {
193             return object;
194         }
195
196         if (fromType.isArray()) {
197             int length = Array.getLength(object);
198             if (toType.isArray()) {
199                 Class JavaDoc cType = toType.getComponentType();
200
201                 Object JavaDoc array = Array.newInstance(cType, length);
202                 for (int i = 0; i < length; i++) {
203                     Object JavaDoc value = Array.get(object, i);
204                     Array.set(array, i, convert(value, cType));
205                 }
206                 return array;
207             }
208             else if (Collection JavaDoc.class.isAssignableFrom(toType)) {
209                 Collection JavaDoc collection = allocateCollection(toType);
210                 for (int i = 0; i < length; i++) {
211                     collection.add(Array.get(object, i));
212                 }
213                 return unmodifiableCollection(collection);
214             }
215             else {
216                 if (length > 0) {
217                     Object JavaDoc value = Array.get(object, 0);
218                     return convert(value, toType);
219                 }
220                 else {
221                     return convert("", toType);
222                 }
223             }
224         }
225         else if (object instanceof Collection JavaDoc) {
226             int length = ((Collection JavaDoc) object).size();
227             if (toType.isArray()) {
228                 Class JavaDoc cType = toType.getComponentType();
229                 Object JavaDoc array = Array.newInstance(cType, length);
230                 Iterator JavaDoc it = ((Collection JavaDoc) object).iterator();
231                 for (int i = 0; i < length; i++) {
232                     Object JavaDoc value = it.next();
233                     Array.set(array, i, convert(value, cType));
234                 }
235                 return array;
236             }
237             else if (Collection JavaDoc.class.isAssignableFrom(toType)) {
238                 Collection JavaDoc collection = allocateCollection(toType);
239                 collection.addAll((Collection JavaDoc) object);
240                 return unmodifiableCollection(collection);
241             }
242             else {
243                 if (length > 0) {
244                     Object JavaDoc value;
245                     if (object instanceof List JavaDoc) {
246                         value = ((List JavaDoc) object).get(0);
247                     }
248                     else {
249                         Iterator JavaDoc it = ((Collection JavaDoc) object).iterator();
250                         value = it.next();
251                     }
252                     return convert(value, toType);
253                 }
254                 else {
255                     return convert("", toType);
256                 }
257             }
258         }
259         else if (object instanceof NodeSet) {
260             return convert(((NodeSet) object).getValues(), toType);
261         }
262         else if (object instanceof Pointer) {
263             return convert(((Pointer) object).getValue(), toType);
264         }
265         else if (toType == String JavaDoc.class) {
266             return object.toString();
267         }
268         else if (object instanceof Boolean JavaDoc) {
269             if (toType == boolean.class) {
270                 return object;
271             }
272             boolean value = ((Boolean JavaDoc) object).booleanValue();
273             return allocateNumber(toType, value ? 1 : 0);
274         }
275         else if (object instanceof Number JavaDoc) {
276             double value = ((Number JavaDoc) object).doubleValue();
277             if (toType == boolean.class || toType == Boolean JavaDoc.class) {
278                 return value == 0.0 ? Boolean.FALSE : Boolean.TRUE;
279             }
280             if (toType.isPrimitive()
281                 || Number JavaDoc.class.isAssignableFrom(toType)) {
282                 return allocateNumber(toType, value);
283             }
284         }
285         else if (object instanceof Character JavaDoc) {
286             if (toType == char.class) {
287                 return object;
288             }
289         }
290         else if (object instanceof String JavaDoc) {
291             Object JavaDoc value = convertStringToPrimitive(object, toType);
292             if (value != null) {
293                 return value;
294             }
295         }
296         
297         Converter converter = ConvertUtils.lookup(toType);
298         if (converter != null) {
299             return converter.convert(toType, object);
300         }
301
302         throw new RuntimeException JavaDoc(
303             "Cannot convert " + object.getClass() + " to " + toType);
304     }
305
306     protected Object JavaDoc convertNullToPrimitive(Class JavaDoc toType) {
307         if (toType == boolean.class) {
308             return Boolean.FALSE;
309         }
310         if (toType == char.class) {
311             return new Character JavaDoc('\0');
312         }
313         if (toType == byte.class) {
314             return new Byte JavaDoc((byte) 0);
315         }
316         if (toType == short.class) {
317             return new Short JavaDoc((short) 0);
318         }
319         if (toType == int.class) {
320             return new Integer JavaDoc(0);
321         }
322         if (toType == long.class) {
323             return new Long JavaDoc(0L);
324         }
325         if (toType == float.class) {
326             return new Float JavaDoc(0.0f);
327         }
328         if (toType == double.class) {
329             return new Double JavaDoc(0.0);
330         }
331         return null;
332     }
333
334     protected Object JavaDoc convertStringToPrimitive(Object JavaDoc object, Class JavaDoc toType) {
335         if (toType == boolean.class || toType == Boolean JavaDoc.class) {
336             return Boolean.valueOf((String JavaDoc) object);
337         }
338         if (toType == char.class || toType == Character JavaDoc.class) {
339             return new Character JavaDoc(((String JavaDoc) object).charAt(0));
340         }
341         if (toType == byte.class || toType == Byte JavaDoc.class) {
342             return new Byte JavaDoc((String JavaDoc) object);
343         }
344         if (toType == short.class || toType == Short JavaDoc.class) {
345             return new Short JavaDoc((String JavaDoc) object);
346         }
347         if (toType == int.class || toType == Integer JavaDoc.class) {
348             return new Integer JavaDoc((String JavaDoc) object);
349         }
350         if (toType == long.class || toType == Long JavaDoc.class) {
351             return new Long JavaDoc((String JavaDoc) object);
352         }
353         if (toType == float.class || toType == Float JavaDoc.class) {
354             return new Float JavaDoc((String JavaDoc) object);
355         }
356         if (toType == double.class || toType == Double JavaDoc.class) {
357             return new Double JavaDoc((String JavaDoc) object);
358         }
359         return null;
360     }
361     
362     protected Number JavaDoc allocateNumber(Class JavaDoc type, double value) {
363         if (type == Byte JavaDoc.class || type == byte.class) {
364             return new Byte JavaDoc((byte) value);
365         }
366         if (type == Short JavaDoc.class || type == short.class) {
367             return new Short JavaDoc((short) value);
368         }
369         if (type == Integer JavaDoc.class || type == int.class) {
370             return new Integer JavaDoc((int) value);
371         }
372         if (type == Long JavaDoc.class || type == long.class) {
373             return new Long JavaDoc((long) value);
374         }
375         if (type == Float JavaDoc.class || type == float.class) {
376             return new Float JavaDoc((float) value);
377         }
378         if (type == Double JavaDoc.class || type == double.class) {
379             return new Double JavaDoc(value);
380         }
381         return null;
382     }
383
384     protected boolean canCreateCollection(Class JavaDoc type) {
385         if (!type.isInterface()
386             && ((type.getModifiers() & Modifier.ABSTRACT) == 0)) {
387             return true;
388         }
389
390         if (type == List JavaDoc.class) {
391             return true;
392         }
393
394         if (type == Set JavaDoc.class) {
395             return true;
396         }
397         return false;
398     }
399
400     protected Collection JavaDoc allocateCollection(Class JavaDoc type) {
401         if (!type.isInterface()
402             && ((type.getModifiers() & Modifier.ABSTRACT) == 0)) {
403             try {
404                 return (Collection JavaDoc) type.newInstance();
405             }
406             catch (Exception JavaDoc ex) {
407                 throw new JXPathException(
408                     "Cannot create collection of type: " + type,
409                     ex);
410             }
411         }
412
413         if (type == List JavaDoc.class) {
414             return new ArrayList JavaDoc();
415         }
416         if (type == Set JavaDoc.class) {
417             return new HashSet JavaDoc();
418         }
419         throw new RuntimeException JavaDoc("Cannot create collection of type: " + type);
420     }
421     
422     protected Collection JavaDoc unmodifiableCollection(Collection JavaDoc collection) {
423         if (collection instanceof List JavaDoc) {
424             return Collections.unmodifiableList((List JavaDoc) collection);
425         }
426         else if (collection instanceof Set JavaDoc) {
427             return Collections.unmodifiableSet((Set JavaDoc) collection);
428         }
429         // Cannot wrap it into a proper unmodifiable collection,
430
// so we just return the original collection itself
431
return collection;
432     }
433     
434     static final class ValueNodeSet implements NodeSet {
435         private List JavaDoc values;
436         private List JavaDoc pointers;
437
438         public ValueNodeSet(List JavaDoc values) {
439            this.values = values;
440         }
441         
442         public List JavaDoc getValues() {
443             return Collections.unmodifiableList(values);
444         }
445         
446         public List JavaDoc getNodes() {
447             return Collections.unmodifiableList(values);
448         }
449         
450         public List JavaDoc getPointers() {
451             if (pointers == null) {
452                 pointers = new ArrayList JavaDoc();
453                 for (int i = 0; i < values.size(); i++) {
454                     pointers.add(new ValuePointer(values.get(i)));
455                 }
456                 pointers = Collections.unmodifiableList(pointers);
457             }
458             return pointers;
459         }
460     }
461     
462     static final class ValuePointer implements Pointer {
463         private Object JavaDoc bean;
464
465         public ValuePointer(Object JavaDoc object) {
466             this.bean = object;
467         }
468         
469         public Object JavaDoc getValue() {
470             return bean;
471         }
472         
473         public Object JavaDoc getNode() {
474             return bean;
475         }
476         
477         public Object JavaDoc getRootNode() {
478             return bean;
479         }
480         
481         public void setValue(Object JavaDoc value) {
482             throw new UnsupportedOperationException JavaDoc();
483         }
484         
485         public Object JavaDoc clone() {
486             return this;
487         }
488         
489         public int compareTo(Object JavaDoc object) {
490             return 0;
491         }
492         
493         public String JavaDoc asPath() {
494             if (bean == null) {
495                 return "null()";
496             }
497             else if (bean instanceof Number JavaDoc) {
498                 String JavaDoc string = bean.toString();
499                 if (string.endsWith(".0")) {
500                     string = string.substring(0, string.length() - 2);
501                 }
502                 return string;
503             }
504             else if (bean instanceof Boolean JavaDoc) {
505                 return ((Boolean JavaDoc) bean).booleanValue() ? "true()" : "false()";
506             }
507             else if (bean instanceof String JavaDoc) {
508                 return "'" + bean + "'";
509             }
510             return "{object of type " + bean.getClass().getName() + "}";
511         }
512     }
513 }
Popular Tags