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 16 public class JavaBeanConverter implements Converter { 17 18 25 private ClassMapper classMapper; 26 27 private String classAttributeIdentifier; 28 29 private BeanProvider beanProvider; 30 31 public JavaBeanConverter(ClassMapper classMapper, String classAttributeIdentifier) { 32 this.classMapper = classMapper; 33 this.classAttributeIdentifier = classAttributeIdentifier; 34 this.beanProvider = new BeanProvider(); 35 } 36 37 41 public boolean canConvert(Class type) { 42 return beanProvider.canInstantiate(type); 43 } 44 45 public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) { 46 47 beanProvider.visitSerializableProperties(source, new BeanProvider.Visitor() { 48 public void visit(String propertyName, Class fieldType, Object newObj) { 49 if (newObj != null) { 50 writeField(propertyName, fieldType, newObj); 51 } 52 } 53 54 private void writeField(String propertyName, Class fieldType, Object newObj) { 55 writer.startNode(classMapper.serializedMember(source.getClass(), propertyName)); 56 57 Class actualType = newObj.getClass(); 58 59 Class 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 unmarshal(final HierarchicalStreamReader reader, final UnmarshallingContext context) { 72 final Object result = instantiateNewInstance(context); 73 74 while (reader.hasMoreChildren()) { 75 reader.moveDown(); 76 77 String propertyName = classMapper.realMember(result.getClass(), reader.getNodeName()); 78 79 boolean propertyExistsInClass = beanProvider.propertyDefinedInClass(propertyName, result.getClass()); 80 81 Class type = determineType(reader, result, propertyName); 82 Object 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 instantiateNewInstance(UnmarshallingContext context) { 95 Object result = context.currentObject(); 96 if (result == null) { 97 result = beanProvider.newInstance(context.getRequiredType()); 98 } 99 return result; 100 } 101 102 private Class determineType(HierarchicalStreamReader reader, Object result, String fieldName) { 103 String 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 msg) { 113 super(msg); 114 } 115 } 116 } | Popular Tags |