Repository: johnzon Updated Branches: refs/heads/master 6fc58b4c8 -> e2562bf73
aligning code from AccessMode and Generics to avoid duplication Project: http://git-wip-us.apache.org/repos/asf/johnzon/repo Commit: http://git-wip-us.apache.org/repos/asf/johnzon/commit/e2562bf7 Tree: http://git-wip-us.apache.org/repos/asf/johnzon/tree/e2562bf7 Diff: http://git-wip-us.apache.org/repos/asf/johnzon/diff/e2562bf7 Branch: refs/heads/master Commit: e2562bf73ca323cb1fb889c89e1b19875db4a6fd Parents: 6fc58b4 Author: Romain Manni-Bucau <rmannibu...@apache.org> Authored: Sun Feb 4 18:02:34 2018 +0100 Committer: Romain Manni-Bucau <rmannibu...@apache.org> Committed: Sun Feb 4 18:02:34 2018 +0100 ---------------------------------------------------------------------- .../johnzon/mapper/MappingParserImpl.java | 54 ++++++----- .../org/apache/johnzon/mapper/Mappings.java | 10 +- .../johnzon/mapper/access/BaseAccessMode.java | 96 ++------------------ .../johnzon/mapper/access/FieldAccessMode.java | 16 ++-- .../johnzon/mapper/access/MethodAccessMode.java | 18 ++-- .../johnzon/mapper/reflection/Generics.java | 31 +++---- 6 files changed, 76 insertions(+), 149 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/johnzon/blob/e2562bf7/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java index 538b737..18af2ec 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java @@ -172,23 +172,23 @@ public class MappingParserImpl implements MappingParser { if (Class.class.isInstance(targetType) && ((Class) targetType).isArray()) { final Class componentType = ((Class) targetType).getComponentType(); return (T) buildArrayWithComponentType(jsonArray, componentType, config.findAdapter(componentType), - isDeduplicateObjects ? new JsonPointerTracker(null, "/") : null); + isDeduplicateObjects ? new JsonPointerTracker(null, "/") : null, Object.class); } if (ParameterizedType.class.isInstance(targetType)) { final ParameterizedType pt = (ParameterizedType) targetType; - final Mappings.CollectionMapping mapping = mappings.findCollectionMapping(pt); + final Mappings.CollectionMapping mapping = mappings.findCollectionMapping(pt, Object.class); if (mapping == null) { throw new UnsupportedOperationException("type " + targetType + " not supported"); } final Type arg = pt.getActualTypeArguments()[0]; return (T) mapCollection(mapping, jsonArray, Class.class.isInstance(arg) ? config.findAdapter(Class.class.cast(arg)) : null, - null, isDeduplicateObjects ? new JsonPointerTracker(null, "/") : null); + null, isDeduplicateObjects ? new JsonPointerTracker(null, "/") : null, Object.class); } if (Object.class == targetType) { return (T) new ArrayList(asList(Object[].class.cast(buildArrayWithComponentType(jsonArray, Object.class, null, - isDeduplicateObjects ? new JsonPointerTracker(null, "/") : null)))); + isDeduplicateObjects ? new JsonPointerTracker(null, "/") : null, Object.class)))); } } if (JsonValue.NULL.equals(jsonValue)) { @@ -263,7 +263,7 @@ public class MappingParserImpl implements MappingParser { } else if (JsonString.class.isInstance(jsonValue) && any) { map.put(value.getKey(), JsonString.class.cast(jsonValue).getString()); } else { - map.put(convertTo(keyType, value.getKey()), toObject(null, jsonValue, fieldArgTypes[1], null, jsonPointer)); + map.put(convertTo(keyType, value.getKey()), toObject(null, jsonValue, fieldArgTypes[1], null, jsonPointer, Object.class)); } } return map; @@ -272,7 +272,7 @@ public class MappingParserImpl implements MappingParser { } else if (Map.class == type || HashMap.class == type || LinkedHashMap.class == type) { final LinkedHashMap<String, Object> map = new LinkedHashMap<String, Object>(); for (final Map.Entry<String, JsonValue> value : object.entrySet()) { - map.put(value.getKey(), toObject(null, value.getValue(), Object.class, null, jsonPointer)); + map.put(value.getKey(), toObject(null, value.getValue(), Object.class, null, jsonPointer, Object.class)); } return map; } @@ -340,7 +340,7 @@ public class MappingParserImpl implements MappingParser { } } final Object convertedValue = toValue(existingInstance, jsonValue, value.converter, value.itemConverter, value.paramType, value.objectConverter, - new JsonPointerTracker(jsonPointer, setter.getKey())); + new JsonPointerTracker(jsonPointer, setter.getKey()), inType); if (convertedValue != null) { setterMethod.write(t, convertedValue); } @@ -352,7 +352,7 @@ public class MappingParserImpl implements MappingParser { if (!classMapping.setters.containsKey(key)) { try { classMapping.anySetter.invoke(t, key, toValue(null, entry.getValue(), null, null, Object.class, null, - isDeduplicateObjects ? new JsonPointerTracker(jsonPointer, entry.getKey()) : null)); + isDeduplicateObjects ? new JsonPointerTracker(jsonPointer, entry.getKey()) : null, type)); } catch (final IllegalAccessException e) { throw new IllegalStateException(e); } catch (final InvocationTargetException e) { @@ -465,7 +465,8 @@ public class MappingParserImpl implements MappingParser { private Object toObject(final Object baseInstance, final JsonValue jsonValue, - final Type type, final Adapter itemConverter, JsonPointerTracker jsonPointer) { + final Type type, final Adapter itemConverter, final JsonPointerTracker jsonPointer, + final Type rootType) { if (jsonValue == null || JsonValue.NULL.equals(jsonValue)) { return null; } @@ -515,7 +516,7 @@ public class MappingParserImpl implements MappingParser { if (JsonArray.class == type || JsonStructure.class == type) { return jsonValue; } - return buildArray(type, JsonArray.class.cast(jsonValue), itemConverter, null, jsonPointer); + return buildArray(type, JsonArray.class.cast(jsonValue), itemConverter, null, jsonPointer, rootType); } else if (JsonNumber.class.isInstance(jsonValue)) { if (JsonNumber.class == type) { return jsonValue; @@ -577,43 +578,46 @@ public class MappingParserImpl implements MappingParser { throw new MapperException("Unable to parse " + jsonValue + " to " + type); } - private Object buildArray(final Type type, final JsonArray jsonArray, final Adapter itemConverter, ObjectConverter.Reader objectConverter, - final JsonPointerTracker jsonPointer) { + private Object buildArray(final Type type, final JsonArray jsonArray, final Adapter itemConverter, + final ObjectConverter.Reader objectConverter, + final JsonPointerTracker jsonPointer, final Type rootType) { if (Class.class.isInstance(type)) { final Class clazz = Class.class.cast(type); if (clazz.isArray()) { final Class<?> componentType = clazz.getComponentType(); - return buildArrayWithComponentType(jsonArray, componentType, itemConverter, jsonPointer); + return buildArrayWithComponentType(jsonArray, componentType, itemConverter, jsonPointer, rootType); } } if (ParameterizedType.class.isInstance(type)) { - final Mappings.CollectionMapping mapping = mappings.findCollectionMapping(ParameterizedType.class.cast(type)); + final Mappings.CollectionMapping mapping = mappings.findCollectionMapping(ParameterizedType.class.cast(type), rootType); if (mapping != null) { - return mapCollection(mapping, jsonArray, itemConverter, objectConverter, jsonPointer); + return mapCollection(mapping, jsonArray, itemConverter, objectConverter, jsonPointer, rootType); } } if (Object.class == type) { - return buildArray(ANY_LIST, jsonArray, null, null, jsonPointer); + return buildArray(ANY_LIST, jsonArray, null, null, jsonPointer, rootType); } throw new UnsupportedOperationException("type " + type + " not supported"); } - private Object buildArrayWithComponentType(final JsonArray jsonArray, final Class<?> componentType, final Adapter itemConverter, JsonPointerTracker jsonPointer) { + private Object buildArrayWithComponentType(final JsonArray jsonArray, final Class<?> componentType, final Adapter itemConverter, + final JsonPointerTracker jsonPointer, final Type rootType) { final Object array = Array.newInstance(componentType, jsonArray.size()); int i = 0; for (final JsonValue value : jsonArray) { Array.set(array, i, toObject(null, value, componentType, itemConverter, - isDeduplicateObjects ? new JsonPointerTracker(jsonPointer, i) : null)); + isDeduplicateObjects ? new JsonPointerTracker(jsonPointer, i) : null, rootType)); i++; } return array; } private <T> Collection<T> mapCollection(final Mappings.CollectionMapping mapping, final JsonArray jsonArray, - final Adapter itemConverter, ObjectConverter.Reader objectConverter, JsonPointerTracker jsonPointer) { + final Adapter itemConverter, ObjectConverter.Reader objectConverter, + final JsonPointerTracker jsonPointer, final Type rootType) { final Collection collection; if (SortedSet.class == mapping.raw || NavigableSet.class == mapping.raw || TreeSet.class == mapping.raw) { @@ -639,7 +643,7 @@ public class MappingParserImpl implements MappingParser { collection.add(JsonValue.NULL.equals(value) ? null : toValue(null, value, null, itemConverter, mapping.arg, objectConverter, - isDeduplicateObjects ? new JsonPointerTracker(jsonPointer, i) : null)); + isDeduplicateObjects ? new JsonPointerTracker(jsonPointer, i) : null, rootType)); i++; } @@ -671,27 +675,29 @@ public class MappingParserImpl implements MappingParser { mapping.factory.getParameterItemConverter()[i], mapping.factory.getParameterTypes()[i], mapping.factory.getObjectConverter()[i], - isDeduplicateObjects ? new JsonPointerTracker(jsonPointer, paramName) : null); //X TODO ObjectConverter in @JOhnzonConverter with Constructors! + isDeduplicateObjects ? new JsonPointerTracker(jsonPointer, paramName) : null, + mapping.clazz); //X TODO ObjectConverter in @JohnzonConverter with Constructors! } return objects; } private Object toValue(final Object baseInstance, final JsonValue jsonValue, final Adapter converter, - final Adapter itemConverter, final Type type, final ObjectConverter.Reader objectConverter, JsonPointerTracker jsonPointer) { + final Adapter itemConverter, final Type type, final ObjectConverter.Reader objectConverter, + final JsonPointerTracker jsonPointer, final Type rootType) { if (objectConverter != null) { if (jsonValue instanceof JsonObject) { return objectConverter.fromJson((JsonObject) jsonValue, type, this); } else if (jsonValue instanceof JsonArray) { - return buildArray(type, jsonValue.asJsonArray(), itemConverter, objectConverter, jsonPointer); + return buildArray(type, jsonValue.asJsonArray(), itemConverter, objectConverter, jsonPointer, rootType); } else { throw new UnsupportedOperationException("Array handling with ObjectConverter currently not implemented"); } } - return converter == null ? toObject(baseInstance, jsonValue, type, itemConverter, jsonPointer) + return converter == null ? toObject(baseInstance, jsonValue, type, itemConverter, jsonPointer, rootType) : jsonValue.getValueType() == JsonValue.ValueType.STRING ? converter.to(JsonString.class.cast(jsonValue).getString()) : convertTo(converter, jsonValue, jsonPointer); } http://git-wip-us.apache.org/repos/asf/johnzon/blob/e2562bf7/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mappings.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mappings.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mappings.java index 8a04515..a722602 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mappings.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mappings.java @@ -24,6 +24,7 @@ import org.apache.johnzon.mapper.converter.DateWithCopyConverter; import org.apache.johnzon.mapper.converter.EnumConverter; import org.apache.johnzon.mapper.internal.AdapterKey; import org.apache.johnzon.mapper.internal.ConverterAdapter; +import org.apache.johnzon.mapper.reflection.Generics; import org.apache.johnzon.mapper.reflection.JohnzonParameterizedType; import java.lang.annotation.Annotation; @@ -258,10 +259,10 @@ public class Mappings { this.config = config; } - public CollectionMapping findCollectionMapping(final ParameterizedType genericType) { + public CollectionMapping findCollectionMapping(final ParameterizedType genericType, final Type enclosingType) { CollectionMapping collectionMapping = collections.get(genericType); if (collectionMapping == null) { - collectionMapping = createCollectionMapping(genericType); + collectionMapping = createCollectionMapping(genericType, enclosingType); if (collectionMapping == null) { return null; } @@ -273,7 +274,7 @@ public class Mappings { return collectionMapping; } - private <T> CollectionMapping createCollectionMapping(final ParameterizedType aType) { + private <T> CollectionMapping createCollectionMapping(final ParameterizedType aType, final Type root) { final Type[] fieldArgTypes = aType.getActualTypeArguments(); final Type raw = aType.getRawType(); if (fieldArgTypes.length == 1 && Class.class.isInstance(raw)) { @@ -295,7 +296,8 @@ public class Mappings { return null; } - final CollectionMapping mapping = new CollectionMapping(isPrimitive(fieldArgTypes[0]), collectionType, fieldArgTypes[0]); + final CollectionMapping mapping = new CollectionMapping(isPrimitive(fieldArgTypes[0]), collectionType, + Generics.resolve(fieldArgTypes[0], Class.class.isInstance(root) ? Class.class.cast(root) : null)); collections.putIfAbsent(aType, mapping); return mapping; } http://git-wip-us.apache.org/repos/asf/johnzon/blob/e2562bf7/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java index 36200ad..5661ee2 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/BaseAccessMode.java @@ -18,32 +18,26 @@ */ package org.apache.johnzon.mapper.access; -import org.apache.johnzon.mapper.Adapter; -import org.apache.johnzon.mapper.JohnzonAny; -import org.apache.johnzon.mapper.Converter; -import org.apache.johnzon.mapper.JohnzonConverter; -import org.apache.johnzon.mapper.MapperConverter; -import org.apache.johnzon.mapper.ObjectConverter; -import org.apache.johnzon.mapper.internal.ConverterAdapter; -import org.apache.johnzon.mapper.reflection.JohnzonParameterizedType; +import static org.apache.johnzon.mapper.reflection.Converters.matches; import java.beans.ConstructorProperties; import java.lang.annotation.Annotation; import java.lang.reflect.Constructor; -import java.lang.reflect.GenericDeclaration; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; -import java.lang.reflect.TypeVariable; -import java.util.Collection; import java.util.Comparator; import java.util.HashMap; import java.util.Map; -import static java.util.Arrays.asList; -import static org.apache.johnzon.mapper.reflection.Converters.matches; +import org.apache.johnzon.mapper.Adapter; +import org.apache.johnzon.mapper.Converter; +import org.apache.johnzon.mapper.JohnzonAny; +import org.apache.johnzon.mapper.JohnzonConverter; +import org.apache.johnzon.mapper.MapperConverter; +import org.apache.johnzon.mapper.ObjectConverter; +import org.apache.johnzon.mapper.internal.ConverterAdapter; // handle some specific types public abstract class BaseAccessMode implements AccessMode { @@ -271,78 +265,4 @@ public abstract class BaseAccessMode implements AccessMode { } return delegate; } - - protected Type fixType(final Class<?> clazz, final Type type) { // to enhance - if (TypeVariable.class.isInstance(type)) { // we need to handle it on deserialization side, not needed on serialization side - return fixTypeVariable(clazz, type); - } - if (ParameterizedType.class.isInstance(type)) { - final ParameterizedType pt = ParameterizedType.class.cast(type); - final Type[] actualTypeArguments = pt.getActualTypeArguments(); - if (actualTypeArguments.length == 1 && Class.class.isInstance(pt.getRawType()) - && Collection.class.isAssignableFrom(Class.class.cast(pt.getRawType())) - && Class.class.cast(pt.getRawType()).getName().startsWith("java.util.") - && TypeVariable.class.isInstance(actualTypeArguments[0])) { - return new JohnzonParameterizedType(pt.getRawType(), fixTypeVariable(clazz, actualTypeArguments[0])); - } else if (actualTypeArguments.length == 2 && Class.class.isInstance(pt.getRawType()) - && Map.class.isAssignableFrom(Class.class.cast(pt.getRawType())) - && Class.class.cast(pt.getRawType()).getName().startsWith("java.util.") - && TypeVariable.class.isInstance(actualTypeArguments[1])) { - return new JohnzonParameterizedType(pt.getRawType(), actualTypeArguments[0], fixTypeVariable(clazz, actualTypeArguments[1])); - } - } - return type; - } - - private Type fixTypeVariable(final Class<?> clazz, final Type type) { - final TypeVariable typeVariable = TypeVariable.class.cast(type); - final Class<?> classWithDeclaration = findClass(clazz.getSuperclass(), typeVariable.getGenericDeclaration()); - - if (classWithDeclaration != null) { - // try to match generic - final TypeVariable<? extends Class<?>>[] typeParameters = classWithDeclaration.getTypeParameters(); - final int idx = asList(typeParameters).indexOf(typeVariable); - if (idx >= 0) { - - ParameterizedType pt = findParameterizedType(clazz, classWithDeclaration); - if (pt != null) { - if (pt.getActualTypeArguments().length == typeParameters.length) { - return pt.getActualTypeArguments()[idx]; - } - } - } - } - return type; - } - - private Class<?> findClass(final Class<?> clazz, final GenericDeclaration genericDeclaration) { - - if (clazz == null || clazz == genericDeclaration) { - return clazz; - } - - final Class<?> superclass = clazz.getSuperclass(); - if (superclass != null && superclass != Object.class) { - return findClass(superclass, genericDeclaration); - } - - return null; - } - - private ParameterizedType findParameterizedType(Class<?> clazz, Class<?> classWithDeclaration) { - - if (clazz == Object.class) { - return null; - } - - Type genericSuperclass = clazz.getGenericSuperclass(); - - if (genericSuperclass instanceof ParameterizedType && - ((ParameterizedType) genericSuperclass).getRawType() == classWithDeclaration) { - - return (ParameterizedType) genericSuperclass; - } - - return findParameterizedType(clazz.getSuperclass(), classWithDeclaration); - } } http://git-wip-us.apache.org/repos/asf/johnzon/blob/e2562bf7/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java index f2cec48..831f895 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java @@ -18,12 +18,6 @@ */ package org.apache.johnzon.mapper.access; -import org.apache.johnzon.mapper.Adapter; -import org.apache.johnzon.mapper.JohnzonAny; -import org.apache.johnzon.mapper.JohnzonProperty; -import org.apache.johnzon.mapper.MapperException; -import org.apache.johnzon.mapper.ObjectConverter; - import java.lang.annotation.Annotation; import java.lang.reflect.Field; import java.lang.reflect.Modifier; @@ -31,6 +25,12 @@ import java.lang.reflect.Type; import java.util.HashMap; import java.util.Map; +import org.apache.johnzon.mapper.Adapter; +import org.apache.johnzon.mapper.JohnzonAny; +import org.apache.johnzon.mapper.JohnzonProperty; +import org.apache.johnzon.mapper.MapperException; +import org.apache.johnzon.mapper.ObjectConverter; + public class FieldAccessMode extends BaseAccessMode { public FieldAccessMode(final boolean useConstructor, final boolean acceptHiddenConstructor) { super(useConstructor, acceptHiddenConstructor); @@ -46,7 +46,7 @@ public class FieldAccessMode extends BaseAccessMode { } final Field field = f.getValue(); - readers.put(extractKey(field, key), new FieldReader(field, fixType(clazz, field.getGenericType()))); + readers.put(extractKey(field, key), new FieldReader(field, field.getGenericType())); } return readers; } @@ -61,7 +61,7 @@ public class FieldAccessMode extends BaseAccessMode { } final Field field = f.getValue(); - writers.put(extractKey(field, key), new FieldWriter(field, fixType(clazz, field.getGenericType()))); + writers.put(extractKey(field, key), new FieldWriter(field, field.getGenericType())); } return writers; } http://git-wip-us.apache.org/repos/asf/johnzon/blob/e2562bf7/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java index c81c070..b694bd2 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java @@ -18,12 +18,6 @@ */ package org.apache.johnzon.mapper.access; -import org.apache.johnzon.mapper.Adapter; -import org.apache.johnzon.mapper.JohnzonAny; -import org.apache.johnzon.mapper.JohnzonProperty; -import org.apache.johnzon.mapper.MapperException; -import org.apache.johnzon.mapper.ObjectConverter; - import java.beans.IntrospectionException; import java.beans.Introspector; import java.beans.PropertyDescriptor; @@ -34,6 +28,12 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +import org.apache.johnzon.mapper.Adapter; +import org.apache.johnzon.mapper.JohnzonAny; +import org.apache.johnzon.mapper.JohnzonProperty; +import org.apache.johnzon.mapper.MapperException; +import org.apache.johnzon.mapper.ObjectConverter; + public class MethodAccessMode extends BaseAccessMode { private final boolean supportGetterAsWritter; @@ -52,7 +52,7 @@ public class MethodAccessMode extends BaseAccessMode { if (isIgnored(descriptor.getName()) || Meta.getAnnotation(readMethod, JohnzonAny.class) != null) { continue; } - readers.put(extractKey(descriptor.getName(), readMethod, null), new MethodReader(readMethod, fixType(clazz, readMethod.getGenericReturnType()))); + readers.put(extractKey(descriptor.getName(), readMethod, null), new MethodReader(readMethod, readMethod.getGenericReturnType())); } } return readers; @@ -69,12 +69,12 @@ public class MethodAccessMode extends BaseAccessMode { final Method writeMethod = descriptor.getWriteMethod(); if (writeMethod != null) { writers.put(extractKey(descriptor.getName(), writeMethod, descriptor.getReadMethod()), - new MethodWriter(writeMethod, fixType(clazz, writeMethod.getGenericParameterTypes()[0]))); + new MethodWriter(writeMethod, writeMethod.getGenericParameterTypes()[0])); } else if (supportGetterAsWritter && Collection.class.isAssignableFrom(descriptor.getPropertyType()) && descriptor.getReadMethod() != null) { final Method readMethod = descriptor.getReadMethod(); - writers.put(extractKey(descriptor.getName(), readMethod, null), new MethodGetterAsWriter(readMethod, fixType(clazz, readMethod.getGenericReturnType()))); + writers.put(extractKey(descriptor.getName(), readMethod, null), new MethodGetterAsWriter(readMethod, readMethod.getGenericReturnType())); } } return writers; http://git-wip-us.apache.org/repos/asf/johnzon/blob/e2562bf7/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Generics.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Generics.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Generics.java index 31ad7f2..8e06529 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Generics.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/reflection/Generics.java @@ -56,12 +56,12 @@ public final class Generics { if (args == null) { args = new ArrayList<>(); if (index > 0) { - args.addAll(asList(parameterizedType.getActualTypeArguments()).subList(0, index + 1)); + args.addAll(asList(parameterizedType.getActualTypeArguments()).subList(0, index)); } } } if (args != null) { - args.add(arg); + args.add(type); } index++; } @@ -74,23 +74,22 @@ public final class Generics { // for now the level is hardcoded to 2 with generic > concrete private static Type resolveTypeVariable(final Type value, final Class<?> rootClass) { final TypeVariable<?> tv = TypeVariable.class.cast(value); - final Type parent = rootClass.getGenericSuperclass(); + Type parent = rootClass == null ? null : rootClass.getGenericSuperclass(); + while (Class.class.isInstance(parent)) { + parent = Class.class.cast(parent).getGenericSuperclass(); + } + while (ParameterizedType.class.isInstance(parent) && ParameterizedType.class.cast(parent).getRawType() != tv.getGenericDeclaration()) { + parent = Class.class.cast(ParameterizedType.class.cast(parent).getRawType()).getGenericSuperclass(); + } if (ParameterizedType.class.isInstance(parent)) { final ParameterizedType parentPt = ParameterizedType.class.cast(parent); - if (Class.class.isInstance(parentPt.getRawType())) { - final Type grandParent = Class.class.cast(parentPt.getRawType()).getGenericSuperclass(); - if (ParameterizedType.class.isInstance(grandParent)) { - final ParameterizedType grandParentPt = ParameterizedType.class.cast(grandParent); - final Type[] grandParentArgs = grandParentPt.getActualTypeArguments(); - int index = 0; - final String name = tv.getName(); - for (final Type t : grandParentArgs) { - if (TypeVariable.class.isInstance(t) && TypeVariable.class.cast(t).getName().equals(name)) { - return parentPt.getActualTypeArguments()[index]; - } - index++; - } + final int argIndex = asList(Class.class.cast(parentPt.getRawType()).getTypeParameters()).indexOf(tv); + if (argIndex >= 0) { + final Type type = parentPt.getActualTypeArguments()[argIndex]; + if (TypeVariable.class.isInstance(type)) { + return resolveTypeVariable(type, rootClass); } + return type; } } return value;