in xstream/src/java/com/thoughtworks/xstream/mapper/AnnotationMapper.java [230:285]
private void addParametrizedTypes(Type type, final Set<Class<?>> types) {
final Set<Type> processedTypes = new HashSet<>();
final Set<Type> localTypes = new LinkedHashSet<Type>() {
private static final long serialVersionUID = 20151010L;
@Override
public boolean add(final Type o) {
if (o instanceof Class) {
return types.add((Class<?>)o);
}
return o == null || processedTypes.contains(o) ? false : super.add(o);
}
};
while (type != null) {
processedTypes.add(type);
if (type instanceof Class) {
final Class<?> clazz = (Class<?>)type;
types.add(clazz);
if (!clazz.isPrimitive()) {
final TypeVariable<?>[] typeParameters = clazz.getTypeParameters();
for (final TypeVariable<?> typeVariable : typeParameters) {
localTypes.add(typeVariable);
}
localTypes.add(clazz.getGenericSuperclass());
for (final Type iface : clazz.getGenericInterfaces()) {
localTypes.add(iface);
}
}
} else if (type instanceof TypeVariable) {
final TypeVariable<?> typeVariable = (TypeVariable<?>)type;
final Type[] bounds = typeVariable.getBounds();
for (final Type bound : bounds) {
localTypes.add(bound);
}
} else if (type instanceof ParameterizedType) {
final ParameterizedType parametrizedType = (ParameterizedType)type;
localTypes.add(parametrizedType.getRawType());
final Type[] actualArguments = parametrizedType.getActualTypeArguments();
for (final Type actualArgument : actualArguments) {
localTypes.add(actualArgument);
}
} else if (type instanceof GenericArrayType) {
final GenericArrayType arrayType = (GenericArrayType)type;
localTypes.add(arrayType.getGenericComponentType());
}
if (!localTypes.isEmpty()) {
final Iterator<Type> iter = localTypes.iterator();
type = iter.next();
iter.remove();
} else {
type = null;
}
}
}