Index: src/java/com/thoughtworks/xstream/mapper/InheritedFieldAliasingMapper.java =================================================================== --- src/java/com/thoughtworks/xstream/mapper/InheritedFieldAliasingMapper.java (revision 0) +++ src/java/com/thoughtworks/xstream/mapper/InheritedFieldAliasingMapper.java (revision 0) @@ -0,0 +1,130 @@ +package com.thoughtworks.xstream.mapper; + +import com.thoughtworks.xstream.alias.ClassMapper; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Mapper that allows a field of a specific class to be replaced with a shorter alias, or omitted + * entirely. + * + * @author Joe Walnes + * @author David Blevins + */ +public class InheritedFieldAliasingMapper extends MapperWrapper { + + protected final Map fieldToAliasMap = new HashMap(); + protected final Map aliasToFieldMap = new HashMap(); + protected final Set fieldsToOmit = new HashSet(); + + public InheritedFieldAliasingMapper(Mapper wrapped) { + super(wrapped); + } + + /** + * @deprecated As of 1.2, use {@link #InheritedFieldAliasingMapper(Mapper)} + */ + public InheritedFieldAliasingMapper(ClassMapper wrapped) { + this((Mapper)wrapped); + } + + public void addFieldAlias(String alias, Class type, String fieldName) { + fieldToAliasMap.put(key(type, fieldName), alias); + aliasToFieldMap.put(key(type, alias), fieldName); + } + + private Key key(Class type, String value) { + return new Key(type, value); + } + + public String serializedMember(Class type, String memberName) { + String alias = get(key(type, memberName), fieldToAliasMap); + if (alias == null) { + return super.serializedMember(type, memberName); + } else { + return alias; + } + } + + public String realMember(Class type, String serialized) { + String real = get(key(type, serialized), aliasToFieldMap); + if (real == null) { + return super.realMember(type, serialized); + } else { + return real; + } + } + + public boolean shouldSerializeMember(Class definedIn, String fieldName) { + return !fieldsToOmit.contains(key(definedIn, fieldName)); + } + + public void omitField(Class type, String fieldName) { + fieldsToOmit.add(key(type, fieldName)); + } + + private String get(Key key, Map map){ + String value = (String) map.get(key); + if (value != null){ + return value; + } + + Class superclass = key.getType().getSuperclass(); + + if (superclass == null || superclass == Object.class){ + return null; + } + + value = get(new Key(superclass, key.getName()), map); + + if (value != null){ + map.put(key, value); + } + + return value; + } + + private static class Key { + private final Class type; + private final String name; + + public Key(Class type, String name) { + this.type = type; + this.name = name; + } + + public Class getType() { + return type; + } + + public String getName() { + return name; + } + + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + final Key key = (Key) o; + + if (name != null ? !name.equals(key.name) : key.name != null) return false; + if (type != null ? !type.equals(key.type) : key.type != null) return false; + + return true; + } + + public int hashCode() { + int result; + result = (type != null ? type.hashCode() : 0); + result = 29 * result + (name != null ? name.hashCode() : 0); + return result; + } + + public String toString() { + return "key("+type.getName()+", "+name+")"; + } + } +}