aQute.lib.json.MapHandler Maven / Gradle / Ivy
package aQute.lib.json;
import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TreeMap;
public class MapHandler extends Handler {
final Class> rawClass;
final Type keyType;
final Type valueType;
MapHandler(Class> rawClass, Type keyType, Type valueType) {
if (rawClass != Map.class) {
ParameterizedType type = findAncestor(rawClass, Map.class);
this.keyType = keyType == Object.class ? resolve(type.getActualTypeArguments()[0]) : keyType;
this.valueType = valueType == Object.class ? resolve(type.getActualTypeArguments()[1]) : valueType;
} else {
this.keyType = keyType;
this.valueType = valueType;
}
if (rawClass.isInterface()) {
if (rawClass.isAssignableFrom(LinkedHashMap.class))
rawClass = LinkedHashMap.class;
else if (rawClass.isAssignableFrom(TreeMap.class))
rawClass = TreeMap.class;
else if (rawClass.isAssignableFrom(Hashtable.class))
rawClass = Hashtable.class;
else if (rawClass.isAssignableFrom(HashMap.class))
rawClass = HashMap.class;
else if (rawClass.isAssignableFrom(Dictionary.class))
rawClass = Hashtable.class;
else
throw new IllegalArgumentException("Unknown map interface: " + rawClass);
}
this.rawClass = rawClass;
}
private Type resolve(Type type) {
if (type instanceof TypeVariable>) {
TypeVariable> tv = (TypeVariable>) type;
Type[] bounds = tv.getBounds();
return resolve(bounds[bounds.length - 1]);
}
return type;
}
private ParameterizedType findAncestor(Class> start, Class> target) {
if (start == null || start == Object.class)
return null;
for (Type t : start.getGenericInterfaces()) {
if (t instanceof ParameterizedType) {
if (((ParameterizedType) t).getRawType() == target)
return (ParameterizedType) t;
}
}
for (Class> impls : start.getInterfaces()) {
ParameterizedType ancestor = findAncestor(impls, target);
if (ancestor != null)
return ancestor;
}
return findAncestor(start.getSuperclass(), target);
}
@Override
public void encode(Encoder app, Object object, Map