You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by gn...@apache.org on 2016/06/13 18:29:53 UTC
svn commit: r1748298 - in /aries/trunk/blueprint/blueprint-core/src:
main/java/org/apache/aries/blueprint/container/AggregateConverter.java
test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java
Author: gnodet
Date: Mon Jun 13 18:29:53 2016
New Revision: 1748298
URL: http://svn.apache.org/viewvc?rev=1748298&view=rev
Log:
[ARIES-1572] Fix more complicated generic conversions
Modified:
aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AggregateConverter.java
aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java
Modified: aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AggregateConverter.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AggregateConverter.java?rev=1748298&r1=1748297&r2=1748298&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AggregateConverter.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/main/java/org/apache/aries/blueprint/container/AggregateConverter.java Mon Jun 13 18:29:53 2016
@@ -20,7 +20,9 @@ import java.io.ByteArrayInputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.AccessControlContext;
@@ -476,17 +478,90 @@ public class AggregateConverter implemen
return true;
}
}
+ } else {
+ ReifiedType t = getExactSuperType(from, to.getRawClass());
+ if (t != null) {
+ return isTypeAssignable(t, to);
+ }
}
- Type t = from.getRawClass().getGenericSuperclass();
- if (t != null && isTypeAssignable(new GenericType(t), to)) {
- return true;
+ return false;
+ }
+
+ private static ReifiedType getExactSuperType(ReifiedType from, Class<?> to) {
+ if (from.getRawClass() == to) {
+ return from;
+ }
+ if (!to.isAssignableFrom(from.getRawClass())) {
+ return null;
+ }
+ for (ReifiedType superType: getExactDirectSuperTypes(from)) {
+ ReifiedType result = getExactSuperType(superType, to);
+ if (result != null)
+ return result;
+ }
+ return null;
+ }
+
+ public static ReifiedType[] getExactDirectSuperTypes(ReifiedType type) {
+ Class<?> clazz = type.getRawClass();
+ Type[] superInterfaces = clazz.getGenericInterfaces();
+ Type superClass = clazz.getGenericSuperclass();
+ // the only supertype of an interface without superinterfaces is Object
+ if (superClass == null && superInterfaces.length == 0 && clazz.isInterface()) {
+ return new ReifiedType[] { new GenericType(Object.class) };
+ }
+ ReifiedType[] result;
+ int resultIndex;
+ if (superClass == null) {
+ result = new ReifiedType[superInterfaces.length];
+ resultIndex = 0;
+ } else {
+ result = new ReifiedType[superInterfaces.length + 1];
+ resultIndex = 1;
+ result[0] = mapTypeParameters(superClass, type);
}
- for (Type ti : from.getRawClass().getGenericInterfaces()) {
- if (ti != null && isTypeAssignable(new GenericType(ti), to)) {
- return true;
+ for (Type superInterface : superInterfaces) {
+ result[resultIndex++] = mapTypeParameters(superInterface, type);
+ }
+ return result;
+ }
+
+ private static ReifiedType mapTypeParameters(Type toMapType, ReifiedType typeAndParams) {
+ if (typeAndParams.size() == 0 && typeAndParams.getRawClass().getTypeParameters().length > 0) {
+ // Missing generics information, return erased type
+ return new GenericType(new GenericType(toMapType).getRawClass());
+ }
+ if (toMapType instanceof Class) {
+ return new GenericType(toMapType);
+ }
+ Map<TypeVariable<?>, GenericType> map = new HashMap<TypeVariable<?>, GenericType>();
+ for (int i = 0; i < typeAndParams.size(); i++) {
+ map.put(typeAndParams.getRawClass().getTypeParameters()[i], (GenericType) typeAndParams.getActualTypeArgument(i));
+ }
+ return map(map, toMapType);
+ }
+
+
+ private static GenericType map(Map<TypeVariable<?>, GenericType> map, Type type) {
+ if (type instanceof Class) {
+ return new GenericType(type);
+ }
+ if (type instanceof TypeVariable) {
+ TypeVariable<?> tv = (TypeVariable<?>) type;
+ if (!map.containsKey(type)) {
+ throw new IllegalArgumentException("Unable to resolve TypeVariable: " + tv);
}
+ return map.get(type);
}
- return false;
+ if (type instanceof ParameterizedType) {
+ ParameterizedType pType = (ParameterizedType) type;
+ GenericType[] args = new GenericType[pType.getActualTypeArguments().length];
+ for (int i = 0; i < args.length; i++) {
+ args[i] = map(map, pType.getActualTypeArguments()[i]);
+ }
+ return new GenericType((Class<?>) pType.getRawType(), args);
+ }
+ throw new RuntimeException("not implemented: mapping " + type.getClass() + " (" + type + ")");
}
private static boolean isWildcardCompatible(ReifiedType from, ReifiedType to) {
Modified: aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java?rev=1748298&r1=1748297&r2=1748298&view=diff
==============================================================================
--- aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java (original)
+++ aries/trunk/blueprint/blueprint-core/src/test/java/org/apache/aries/blueprint/container/BeanRecipeTest.java Mon Jun 13 18:29:53 2016
@@ -68,6 +68,16 @@ public class BeanRecipeTest {
public ExampleService(Example<String> e) {}
}
+ static public interface BaseInterface<T> { }
+ static public interface ExtendedInterface<T0, T1> extends BaseInterface<T1> {}
+ static public class MyClass implements ExtendedInterface<String, Integer> { }
+ static public class MyClass2<T> implements BaseInterface<T> { }
+ static public class MyClass3 extends MyClass2<Long> { }
+ static public class MyService {
+ public MyService(BaseInterface<? extends Number> e) {}
+ }
+
+
static public interface A {
String getA();
void setA(String a);
@@ -126,6 +136,26 @@ public class BeanRecipeTest {
recipe.setArgTypes(Arrays.<String>asList((String) null));
ExecutionContext.Holder.setContext(new BlueprintRepository(container));
recipe.create();
+ }
+
+ @Test
+ public void parameterWithComplexGenerics1() throws Exception {
+ BlueprintContainerImpl container = new BlueprintContainerImpl(null, null, null, null, null, null, null, null, null, null);
+ BeanRecipe recipe = new BeanRecipe("example", container, MyService.class, false);
+ recipe.setArguments(Arrays.<Object>asList(new MyClass()));
+ recipe.setArgTypes(Arrays.<String>asList((String) null));
+ ExecutionContext.Holder.setContext(new BlueprintRepository(container));
+ recipe.create();
+ }
+
+ @Test
+ public void parameterWithComplexGenerics2() throws Exception {
+ BlueprintContainerImpl container = new BlueprintContainerImpl(null, null, null, null, null, null, null, null, null, null);
+ BeanRecipe recipe = new BeanRecipe("example", container, MyService.class, false);
+ recipe.setArguments(Arrays.<Object>asList(new MyClass3()));
+ recipe.setArgTypes(Arrays.<String>asList((String) null));
+ ExecutionContext.Holder.setContext(new BlueprintRepository(container));
+ recipe.create();
}
@Test