summaryrefslogtreecommitdiffstatsabout
diff options
context:
space:
mode:
authorMatt Bishop2012-11-26 18:12:54 (EST)
committer Glyn Normington2012-11-30 07:46:00 (EST)
commit664bc5e982029334a2b9aabc566f969dd2de7a87 (patch)
treee170b6c1522da161e500d6336fa83c86bd6e979c
parent85fe2975f54b824c0a470a5c960e81ac0d0d1040 (diff)
downloadorg.eclipse.gemini.blueprint-664bc5e982029334a2b9aabc566f969dd2de7a87.zip
org.eclipse.gemini.blueprint-664bc5e982029334a2b9aabc566f969dd2de7a87.tar.gz
org.eclipse.gemini.blueprint-664bc5e982029334a2b9aabc566f969dd2de7a87.tar.bz2
Additional fixes for https://bugs.eclipse.org/bugs/show_bug.cgi?id=392500
Recursive Generics can me mutually recursive, Multi-bounded and wildcard-scoped. Conflicts: core/src/test/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactoryTest.java Fix compilation errors
-rw-r--r--core/src/main/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactory.java35
-rw-r--r--core/src/test/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactoryTest.java152
2 files changed, 105 insertions, 82 deletions
diff --git a/core/src/main/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactory.java b/core/src/main/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactory.java
index aded1e0..336201a 100644
--- a/core/src/main/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactory.java
+++ b/core/src/main/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactory.java
@@ -20,6 +20,7 @@ import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -104,13 +105,13 @@ class TypeFactory {
TypeVariable[] tvs = type.getType().getTypeParameters();
arguments = new ArrayList<ReifiedType>(tvs.length);
for (@SuppressWarnings("rawtypes") TypeVariable tv : tvs) {
- ReifiedType rType = getReifiedType(tv);
+ ReifiedType rType = getReifiedType(tv, null);
arguments.add(rType);
}
return arguments;
}
- private static ReifiedType getReifiedType(Type targetType) {
+ private static ReifiedType getReifiedType(Type targetType, Collection<Type> variableTypes) {
if (targetType instanceof Class) {
if (Object.class.equals(targetType)) {
return OBJECT;
@@ -119,7 +120,7 @@ class TypeFactory {
}
if (targetType instanceof ParameterizedType) {
Type ata = ((ParameterizedType) targetType).getActualTypeArguments()[0];
- return getReifiedType(ata);
+ return getReifiedType(ata, variableTypes);
}
if (targetType instanceof WildcardType) {
WildcardType wt = (WildcardType) targetType;
@@ -127,29 +128,37 @@ class TypeFactory {
if (ObjectUtils.isEmpty(lowerBounds)) {
// there's always an upper bound (Object)
Type upperBound = wt.getUpperBounds()[0];
- return getReifiedType(upperBound);
+ return getReifiedType(upperBound, variableTypes);
}
- return getReifiedType(lowerBounds[0]);
+ return getReifiedType(lowerBounds[0], variableTypes);
}
if (targetType instanceof TypeVariable) {
TypeVariable<?> typeVariable = (TypeVariable<?>) targetType;
+ if (variableTypes == null) {
+ variableTypes = new ArrayList<Type>(2);
+ } else if (variableTypes.contains(targetType)) {
+ //Looped around on itself via a recursive Generics definition
+ return OBJECT;
+ }
+ variableTypes.add(targetType);
Type[] bounds = typeVariable.getBounds();
- Type boundZero = bounds[0];
- if (bounds.length == 1 && boundZero instanceof ParameterizedType) {
- Type ata = ((ParameterizedType) boundZero).getActualTypeArguments()[0];
- if (targetType.equals(ata)) {
- //recursive declaration like <T extends Comparable<T>>
- return OBJECT;
+ for (Type bound : bounds) {
+ if (bound instanceof ParameterizedType) {
+ Type ata = ((ParameterizedType) bound).getActualTypeArguments()[0];
+ if (ata instanceof TypeVariable) {
+ variableTypes.add(ata);
+ }
+ return getReifiedType(bound, variableTypes);
}
}
- return getReifiedType(boundZero);
+ return getReifiedType(bounds[0], variableTypes);
}
if (targetType instanceof GenericArrayType) {
- return getReifiedType(((GenericArrayType) targetType).getGenericComponentType());
+ return getReifiedType(((GenericArrayType) targetType).getGenericComponentType(), variableTypes);
}
throw new IllegalArgumentException("Unknown type " + targetType.getClass());
diff --git a/core/src/test/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactoryTest.java b/core/src/test/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactoryTest.java
index b762de0..e56745d 100644
--- a/core/src/test/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactoryTest.java
+++ b/core/src/test/java/org/eclipse/gemini/blueprint/blueprint/container/TypeFactoryTest.java
@@ -54,8 +54,8 @@ public class TypeFactoryTest {
public void typedList(LinkedList<Point> arg) {
}
- public void array(Integer[] arg) {
- }
+ public void array(Integer[] arg) {
+ }
public void extendsList(LinkedList<? extends Shape> arg) {
}
@@ -94,23 +94,28 @@ public class TypeFactoryTest {
private static class RecursiveGenericType<T extends Comparable<T>> {
}
- private static class SingleAndRecursiveGenericType<S extends String, T extends Comparable<T>> {
+ private static class SingleAndRecursiveGenericType<S extends String, T extends Comparable<S>> {
}
private static class MultipleRecursiveGenericType<T extends Comparable<T>, U extends T> {
}
-
+
private static class MutuallyRecursiveGenericType<T extends Comparable<U>, U extends Comparable<T>> {
- // Must T always equal U?
+ // Must T always equal U?
}
-
+
private static class ComplexRecursiveGenericType<T extends Comparable<? super T>> {
}
-
+
private static class MultiBoundedRecursiveGenericType<T extends Comparable<T> & Cloneable> {
- // Cloneable could be replaced by any interface
+ // Cloneable could be replaced by any interface
}
-
+
+ private static interface Ice {}
+ private static interface Juice {}
+ private static class A<T extends Ice & Juice> {}
+ private static class B<T extends Juice & Ice> {}
+
@Test
public void testJdk4Classes() throws Exception {
ReifiedType tp = getReifiedTypeFor("rawList");
@@ -118,29 +123,29 @@ public class TypeFactoryTest {
assertEquals(List.class, tp.getRawClass());
}
- @Test
+ @Test
public void testPrimitive() throws Exception {
ReifiedType tp = getReifiedTypeFor("primitive");
assertEquals(0, tp.size());
assertEquals(Integer.class, tp.getRawClass());
}
- @Test
+ @Test
public void testArray() throws Exception {
ReifiedType tp = getReifiedTypeFor("array");
assertEquals(1, tp.size());
assertEquals(Integer[].class, tp.getRawClass());
- assertEquals(Integer.class, tp.getActualTypeArgument(0).getRawClass());
+ assertEquals(Integer.class, tp.getActualTypeArgument(0).getRawClass());
}
- @Test
+ @Test
public void testInteger() throws Exception {
ReifiedType tp = getReifiedTypeFor("integer");
assertEquals(0, tp.size());
assertEquals(Integer.class, tp.getRawClass());
}
- @Test
+ @Test
public void testTypedObjectList() throws Exception {
ReifiedType tp = getReifiedTypeFor("typedList");
assertEquals(1, tp.size());
@@ -148,7 +153,7 @@ public class TypeFactoryTest {
assertEquals(Point.class, tp.getActualTypeArgument(0).getRawClass());
}
- @Test
+ @Test
public void testExtendsList() throws Exception {
ReifiedType tp = getReifiedTypeFor("extendsList");
assertEquals(1, tp.size());
@@ -156,7 +161,7 @@ public class TypeFactoryTest {
assertEquals(Shape.class, tp.getActualTypeArgument(0).getRawClass());
}
- @Test
+ @Test
public void testSuperList() throws Exception {
ReifiedType tp = getReifiedTypeFor("superList");
assertEquals(1, tp.size());
@@ -164,7 +169,7 @@ public class TypeFactoryTest {
assertEquals(Shape.class, tp.getActualTypeArgument(0).getRawClass());
}
- @Test
+ @Test
public void testTypedMap() throws Exception {
ReifiedType tp = getReifiedTypeFor("typedMap");
assertEquals(2, tp.size());
@@ -173,7 +178,7 @@ public class TypeFactoryTest {
assertEquals(Double.class, tp.getActualTypeArgument(1).getRawClass());
}
- @Test
+ @Test
public void testPointMap() throws Exception {
ReifiedType tp = getReifiedTypeFor("pointMap");
assertEquals(2, tp.size());
@@ -182,59 +187,59 @@ public class TypeFactoryTest {
assertEquals(Point.class, tp.getActualTypeArgument(1).getRawClass());
}
- // Since spring 3.1 the TypeDescriptor no longer contains any reference to the MethodParameter
- // class, we we are unable to get the ParameterizedType of a method parameter.
- // So all actual type arguments just become Object.class.
+ // Since spring 3.1 the TypeDescriptor no longer contains any reference to the MethodParameter
+ // class, we we are unable to get the ParameterizedType of a method parameter.
+ // So all actual type arguments just become Object.class.
@Test
- @Ignore
- public void testTypedReference() throws Exception {
+ @Ignore
+ public void testTypedReference() throws Exception {
ReifiedType tp = getReifiedTypeFor("typedReference");
assertEquals(AtomicReference.class, tp.getRawClass());
- assertEquals(1, tp.size());
- assertEquals(Boolean.class, tp.getActualTypeArgument(0).getRawClass());
+ assertEquals(1, tp.size());
+ assertEquals(Boolean.class, tp.getActualTypeArgument(0).getRawClass());
}
- @Test
+ @Test
public void testObjectTypedReference() throws Exception {
ReifiedType tp = getReifiedTypeFor("objectTypedReference");
assertEquals(AtomicReference.class, tp.getRawClass());
- assertEquals(1, tp.size());
- assertEquals(Object.class, tp.getActualTypeArgument(0).getRawClass());
+ assertEquals(1, tp.size());
+ assertEquals(Object.class, tp.getActualTypeArgument(0).getRawClass());
}
- @Test
+ @Test
public void testWildcardReference() throws Exception {
ReifiedType tp = getReifiedTypeFor("wildcardReference");
assertEquals(AtomicReference.class, tp.getRawClass());
- assertEquals(1, tp.size());
- assertEquals(Object.class, tp.getActualTypeArgument(0).getRawClass());
+ assertEquals(1, tp.size());
+ assertEquals(Object.class, tp.getActualTypeArgument(0).getRawClass());
}
- // Since spring 3.1 the TypeDescriptor no longer contains any reference to the MethodParameter
- // class, we we are unable to get the ParameterizedType of a method parameter.
- // So all actual type arguments just become Object.class.
- @Test
- @Ignore
+ // Since spring 3.1 the TypeDescriptor no longer contains any reference to the MethodParameter
+ // class, we we are unable to get the ParameterizedType of a method parameter.
+ // So all actual type arguments just become Object.class.
+ @Test
+ @Ignore
public void testSuperReference() throws Exception {
ReifiedType tp = getReifiedTypeFor("superTypedReference");
assertEquals(AtomicReference.class, tp.getRawClass());
- assertEquals(1, tp.size());
- assertEquals(Properties.class, tp.getActualTypeArgument(0).getRawClass());
+ assertEquals(1, tp.size());
+ assertEquals(Properties.class, tp.getActualTypeArgument(0).getRawClass());
}
- // Since spring 3.1 the TypeDescriptor no longer contains any reference to the MethodParameter
- // class, we we are unable to get the ParameterizedType of a method parameter.
- // So all actual type arguments just come Object.class.
- @Test
- @Ignore
+ // Since spring 3.1 the TypeDescriptor no longer contains any reference to the MethodParameter
+ // class, we we are unable to get the ParameterizedType of a method parameter.
+ // So all actual type arguments just come Object.class.
+ @Test
+ @Ignore
public void testExtendsReference() throws Exception {
ReifiedType tp = getReifiedTypeFor("extendsTypedReference");
assertEquals(AtomicReference.class, tp.getRawClass());
- assertEquals(1, tp.size());
- assertEquals(Properties.class, tp.getActualTypeArgument(0).getRawClass());
+ assertEquals(1, tp.size());
+ assertEquals(Properties.class, tp.getActualTypeArgument(0).getRawClass());
}
- @Test
+ @Test
public void testTypeVariable() throws Exception {
ReifiedType tp = getReifiedTypeFor("typeVariable");
assertEquals(1, tp.size());
@@ -242,7 +247,7 @@ public class TypeFactoryTest {
assertEquals(Object.class, tp.getActualTypeArgument(0).getRawClass());
}
- @Test
+ @Test
public void testCustomDictionary() throws Exception {
ReifiedType tp = getReifiedTypeFor("customDictionary");
assertEquals(2, tp.size());
@@ -251,41 +256,50 @@ public class TypeFactoryTest {
assertEquals(Object.class, tp.getActualTypeArgument(1).getRawClass());
}
- @Test
+ @Test
public void testUnknownType() throws Exception {
ReifiedType type = TypeFactory.getType(TypeDescriptor.forObject(null));
assertEquals(Object.class, type.getRawClass());
}
- @Test
+ @Test
public void testRecursiveGenericType() throws Exception {
assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(RecursiveGenericType.class)));
}
- @Test
- public void testSingleAndRecursiveGenericType() throws Exception {
- assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(SingleAndRecursiveGenericType.class)));
- }
+ @Test
+ public void testSingleAndRecursiveGenericType() throws Exception {
+ assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(SingleAndRecursiveGenericType.class)));
+ }
+
+ @Test
+ public void testMultipleRecursiveGenericType() throws Exception {
+ assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(MultipleRecursiveGenericType.class)));
+ }
- @Test
- public void testMultipleRecursiveGenericType() throws Exception {
- assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(MultipleRecursiveGenericType.class)));
- }
+ @Test
+ public void testMutuallyRecursiveGenericType() throws Exception {
+ assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(MutuallyRecursiveGenericType.class)));
+ }
- @Test
- public void testMutuallyRecursiveGenericType() throws Exception {
- assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(MutuallyRecursiveGenericType.class)));
- }
+ @Test
+ public void testComplexRecursiveGenericType() throws Exception {
+ assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(ComplexRecursiveGenericType.class)));
+ }
- @Test
- public void testComplexRecursiveGenericType() throws Exception {
- assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(ComplexRecursiveGenericType.class)));
- }
+ @Test
+ public void testMultiBoundedRecursiveGenericType() throws Exception {
+ assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(MultiBoundedRecursiveGenericType.class)));
+ }
+
+ @Test
+ public void testMultiBoundedGenericType() throws Exception {
+ ReifiedType reifiedA = TypeFactory.getType(TypeDescriptor.valueOf(A.class));
+ assertNotNull(reifiedA);
+ ReifiedType reifiedB = TypeFactory.getType(TypeDescriptor.valueOf(B.class));
+ assertNotNull(reifiedB);
+ }
- @Test
- public void testMultiBoundedRecursiveGenericType() throws Exception {
- assertNotNull(TypeFactory.getType(TypeDescriptor.valueOf(MultiBoundedRecursiveGenericType.class)));
- }
private ReifiedType getReifiedTypeFor(String methodName) {
Method mt = BeanUtils.findDeclaredMethodWithMinimalParameters(TestSet.class, methodName);