KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > thoughtworks > xstream > converters > javabean > JavaBeanConverter


1 package com.thoughtworks.xstream.converters.javabean;
2
3 import com.thoughtworks.xstream.alias.ClassMapper;
4 import com.thoughtworks.xstream.converters.ConversionException;
5 import com.thoughtworks.xstream.converters.Converter;
6 import com.thoughtworks.xstream.converters.MarshallingContext;
7 import com.thoughtworks.xstream.converters.UnmarshallingContext;
8 import com.thoughtworks.xstream.io.HierarchicalStreamReader;
9 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
10
11 /**
12  * Can convert any bean with a public default constructor. BeanInfo are not
13  * taken into consideration, this class looks for bean patterns for simple
14  * properties
15  */

16 public class JavaBeanConverter implements Converter {
17
18     /**
19      * TODO:
20      * - use bean introspection instead of reflection.
21      * - support indexed properties
22      * - ignore default values
23      * - use BeanInfo
24      */

25     private ClassMapper classMapper;
26
27     private String JavaDoc classAttributeIdentifier;
28
29     private BeanProvider beanProvider;
30
31     public JavaBeanConverter(ClassMapper classMapper, String JavaDoc classAttributeIdentifier) {
32         this.classMapper = classMapper;
33         this.classAttributeIdentifier = classAttributeIdentifier;
34         this.beanProvider = new BeanProvider();
35     }
36
37     /**
38      * Only checks for the availability of a public default constructor.
39      * If you need stricter checks, subclass JavaBeanConverter
40      */

41     public boolean canConvert(Class JavaDoc type) {
42         return beanProvider.canInstantiate(type);
43     }
44
45     public void marshal(final Object JavaDoc source, final HierarchicalStreamWriter writer, final MarshallingContext context) {
46
47         beanProvider.visitSerializableProperties(source, new BeanProvider.Visitor() {
48             public void visit(String JavaDoc propertyName, Class JavaDoc fieldType, Object JavaDoc newObj) {
49                 if (newObj != null) {
50                     writeField(propertyName, fieldType, newObj);
51                 }
52             }
53
54             private void writeField(String JavaDoc propertyName, Class JavaDoc fieldType, Object JavaDoc newObj) {
55                 writer.startNode(classMapper.serializedMember(source.getClass(), propertyName));
56
57                 Class JavaDoc actualType = newObj.getClass();
58
59                 Class JavaDoc defaultType = classMapper.defaultImplementationOf(fieldType);
60                 if (!actualType.equals(defaultType)) {
61                     writer.addAttribute(classAttributeIdentifier, classMapper.serializedClass(actualType));
62                 }
63                 context.convertAnother(newObj);
64
65                 writer.endNode();
66             }
67
68         });
69     }
70
71     public Object JavaDoc unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) {
72         final Object JavaDoc result = instantiateNewInstance(context);
73
74         while (reader.hasMoreChildren()) {
75             reader.moveDown();
76
77             String JavaDoc propertyName = classMapper.realMember(result.getClass(), reader.getNodeName());
78
79             boolean propertyExistsInClass = beanProvider.propertyDefinedInClass(propertyName, result.getClass());
80
81             Class JavaDoc type = determineType(reader, result, propertyName);
82             Object JavaDoc value = context.convertAnother(result, type);
83
84             if (propertyExistsInClass) {
85                 beanProvider.writeProperty(result, propertyName, value);
86             }
87
88             reader.moveUp();
89         }
90
91         return result;
92     }
93
94     private Object JavaDoc instantiateNewInstance(UnmarshallingContext context) {
95         Object JavaDoc result = context.currentObject();
96         if (result == null) {
97             result = beanProvider.newInstance(context.getRequiredType());
98         }
99         return result;
100     }
101
102     private Class JavaDoc determineType(HierarchicalStreamReader reader, Object JavaDoc result, String JavaDoc fieldName) {
103         String JavaDoc classAttribute = reader.getAttribute(classAttributeIdentifier);
104         if (classAttribute != null) {
105             return classMapper.realClass(classAttribute);
106         } else {
107             return classMapper.defaultImplementationOf(beanProvider.getPropertyType(result, fieldName));
108         }
109     }
110
111     public static class DuplicateFieldException extends ConversionException {
112         public DuplicateFieldException(String JavaDoc msg) {
113             super(msg);
114         }
115     }
116 }
Popular Tags