1 package com.thoughtworks.xstream.converters.reflection; 2 3 import com.thoughtworks.xstream.alias.ClassMapper; 4 import com.thoughtworks.xstream.converters.Converter; 5 import com.thoughtworks.xstream.converters.MarshallingContext; 6 import com.thoughtworks.xstream.converters.UnmarshallingContext; 7 import com.thoughtworks.xstream.io.HierarchicalStreamReader; 8 import com.thoughtworks.xstream.io.HierarchicalStreamWriter; 9 10 import java.util.HashSet ; 11 import java.util.Set ; 12 13 public class ReflectionConverter implements Converter { 14 15 private ClassMapper classMapper; 16 private String classAttributeIdentifier; 17 private String definedInAttributeIdentifier = "defined-in"; 18 private ReflectionProvider reflectionProvider; 19 20 public ReflectionConverter(ClassMapper classMapper, String classAttributeIdentifier, String definedInAttributeIdentifier, ReflectionProvider reflectionProvider) { 21 this.classMapper = classMapper; 22 this.classAttributeIdentifier = classAttributeIdentifier; 23 this.definedInAttributeIdentifier = definedInAttributeIdentifier; 24 this.reflectionProvider = reflectionProvider; 25 } 26 27 public boolean canConvert(Class type) { 28 return true; 29 } 30 31 public void marshal(final Object source, final HierarchicalStreamWriter writer, final MarshallingContext context) { 32 final Set seenFields = new HashSet (); 33 reflectionProvider.visitSerializableFields(source, new ReflectionProvider.Visitor() { 34 public void visit(String fieldName, Class fieldType, Class definedIn, Object newObj) { 35 if (newObj != null) { 36 writer.startNode(classMapper.mapNameToXML(fieldName)); 37 38 Class actualType = newObj.getClass(); 39 40 Class defaultType = classMapper.lookupDefaultType(fieldType); 41 if (!actualType.equals(defaultType)) { 42 writer.addAttribute(classAttributeIdentifier, classMapper.lookupName(actualType)); 43 } 44 45 if (seenFields.contains(fieldName)) { 46 writer.addAttribute(definedInAttributeIdentifier, classMapper.lookupName(definedIn)); 47 } 48 context.convertAnother(newObj); 49 50 writer.endNode(); 51 seenFields.add(fieldName); 52 } 53 } 54 }); 55 } 56 57 public Object unmarshal(HierarchicalStreamReader reader, UnmarshallingContext context) { 58 Object result = context.currentObject(); 59 60 if (result == null) { 61 result = reflectionProvider.newInstance(context.getRequiredType()); 62 } 63 64 while (reader.hasMoreChildren()) { 65 reader.moveDown(); 66 67 String fieldName = classMapper.mapNameFromXML(reader.getNodeName()); 68 69 String definedIn = reader.getAttribute(definedInAttributeIdentifier); 70 Class definedInCls = definedIn == null ? null : classMapper.lookupType(definedIn); 71 72 Class type; 73 String classAttribute = reader.getAttribute(classAttributeIdentifier); 74 if (classAttribute == null) { 75 type = classMapper.lookupDefaultType(reflectionProvider.getFieldType(result, fieldName, definedInCls)); 76 } else { 77 type = classMapper.lookupType(classAttribute); 78 } 79 80 Object fieldValue = context.convertAnother(result, type); 81 82 reflectionProvider.writeField(result, fieldName, fieldValue, definedInCls); 83 84 reader.moveUp(); 85 } 86 return result; 87 } 88 89 } 90 | Popular Tags |