package br.com.caelum.vraptor.serialization.xstream; import static br.com.caelum.vraptor.serialization.xstream.VRaptorClassMapper.isPrimitive; import static com.google.common.base.Objects.firstNonNull; import java.lang.reflect.Field; import java.lang.reflect.Type; import java.util.Collections; import java.util.Map.Entry; import net.vidageek.mirror.dsl.Mirror; import com.google.common.collect.LinkedListMultimap; import com.google.common.collect.Multimap; import com.thoughtworks.xstream.XStream; public class OldAndProbablyBuggyConfigurer { private final XStream xstream; public OldAndProbablyBuggyConfigurer(XStream xstream) { this.xstream = xstream; } public void configure(Serializee serializee) { Multimap<Class<?>, String> excludesMap = LinkedListMultimap.create(); if (!serializee.isRecursive()) { Class<?> type = serializee.getRootClass(); excludeNonPrimitiveFields(excludesMap, type); for (Class<?> eType : firstNonNull(serializee.getElementTypes(), Collections.<Class<?>>emptySet())) { excludeNonPrimitiveFields(excludesMap, eType); } } for (Entry<String, Class<?>> include : serializee.getIncludes().entries()) { parseInclude(excludesMap, include); } for (Entry<String, Class<?>> exclude : serializee.getExcludes().entries()) { if(!serializee.getIncludes().containsKey(exclude.getKey())) { parseExclude(exclude); } } for (Entry<Class<?>, String> exclude : excludesMap.entries()) { xstream.omitField(exclude.getKey(), exclude.getValue()); } } private void parseExclude(Entry<String, Class<?>> exclude) { xstream.omitField(exclude.getValue(), getNameFor(exclude.getKey())); } private void parseInclude(Multimap<Class<?>, String> excludesMap, Entry<String, Class<?>> include) { Class<?> parentType = include.getValue(); String fieldName = getNameFor(include.getKey()); Field field = new Mirror().on(parentType).reflect().field(fieldName); if (field == null) return; Type genericType = field.getGenericType(); Class<?> fieldType = Serializee.getActualType(genericType); if (!excludesMap.containsKey(fieldType)) { excludeNonPrimitiveFields(excludesMap, fieldType); } excludesMap.remove(parentType, fieldName); } private static String getNameFor(String name) { String[] path = name.split("\\."); return path[path.length-1]; } private void excludeNonPrimitiveFields(Multimap<Class<?>, String> excludesMap, Class<?> type) { for (Field field : new Mirror().on(type).reflectAll().fields()) { if (!isPrimitive(field.getType())) { excludesMap.put(field.getDeclaringClass(), field.getName()); } } } }