From af7518626f3b1370a7aa5f74fce41b1cbe29ff31 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 13 Feb 2009 12:17:48 +0000 Subject: [PATCH] TypeUtils detects variations of ParameterizedType/GenericArrayType assignability as well git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@633 50f2f4bb-b051-0410-bef5-90022cba6387 --- .../org/springframework/util/TypeUtils.java | 49 ++++++++++++++++--- .../springframework/util/TypeUtilsTests.java | 43 ++++++++++++++-- 2 files changed, 80 insertions(+), 12 deletions(-) diff --git a/org.springframework.core/src/main/java/org/springframework/util/TypeUtils.java b/org.springframework.core/src/main/java/org/springframework/util/TypeUtils.java index a4f0742e803..d535f635858 100644 --- a/org.springframework.core/src/main/java/org/springframework/util/TypeUtils.java +++ b/org.springframework.core/src/main/java/org/springframework/util/TypeUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,7 @@ package org.springframework.util; +import java.lang.reflect.GenericArrayType; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.lang.reflect.WildcardType; @@ -34,20 +35,54 @@ public abstract class TypeUtils { * Check if the right-hand side type may be assigned to the left-hand side * type following the Java generics rules. * @param lhsType the target type - * @param rhsType the value type that should be assigned to the target type + * @param rhsType the value type that should be assigned to the target type * @return true if rhs is assignable to lhs */ public static boolean isAssignable(Type lhsType, Type rhsType) { Assert.notNull(lhsType, "Left-hand side type must not be null"); Assert.notNull(rhsType, "Right-hand side type must not be null"); - if (lhsType.equals(rhsType)) { + if (lhsType.equals(rhsType) || lhsType.equals(Object.class)) { return true; } - if (lhsType instanceof Class && rhsType instanceof Class) { - return ClassUtils.isAssignable((Class) lhsType, (Class) rhsType); + if (lhsType instanceof Class) { + Class lhsClass = (Class) lhsType; + if (rhsType instanceof Class) { + return ClassUtils.isAssignable(lhsClass, (Class) rhsType); + } + else if (rhsType instanceof ParameterizedType){ + Type rhsRaw = ((ParameterizedType) rhsType).getRawType(); + if (rhsRaw instanceof Class) { + return ClassUtils.isAssignable(lhsClass, (Class) rhsRaw); + } + } + else if (lhsClass.isArray() && rhsType instanceof GenericArrayType){ + Type rhsComponent = ((GenericArrayType) rhsType).getGenericComponentType(); + return isAssignable(lhsClass.getComponentType(), rhsComponent); + } } - if (lhsType instanceof ParameterizedType && rhsType instanceof ParameterizedType) { - return isAssignable((ParameterizedType) lhsType, (ParameterizedType) rhsType); + if (lhsType instanceof ParameterizedType) { + if (rhsType instanceof Class) { + Type lhsRaw = ((ParameterizedType) lhsType).getRawType(); + if (lhsRaw instanceof Class) { + return ClassUtils.isAssignable((Class) lhsRaw, (Class) rhsType); + } + } + else if (rhsType instanceof ParameterizedType) { + return isAssignable((ParameterizedType) lhsType, (ParameterizedType) rhsType); + } + } + if (lhsType instanceof GenericArrayType) { + Type lhsComponent = ((GenericArrayType) lhsType).getGenericComponentType(); + if (rhsType instanceof Class) { + Class rhsClass = (Class) rhsType; + if (rhsClass.isArray()) { + return isAssignable(lhsComponent, rhsClass.getComponentType()); + } + } + else if (rhsType instanceof GenericArrayType) { + Type rhsComponent = ((GenericArrayType) rhsType).getGenericComponentType(); + return isAssignable(lhsComponent, rhsComponent); + } } if (lhsType instanceof WildcardType) { return isAssignable((WildcardType) lhsType, rhsType); diff --git a/org.springframework.core/src/test/java/org/springframework/util/TypeUtilsTests.java b/org.springframework.core/src/test/java/org/springframework/util/TypeUtilsTests.java index a33d49fc2f6..746269e5d11 100644 --- a/org.springframework.core/src/test/java/org/springframework/util/TypeUtilsTests.java +++ b/org.springframework.core/src/test/java/org/springframework/util/TypeUtilsTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2007 the original author or authors. + * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -22,12 +22,14 @@ import java.util.HashSet; import java.util.LinkedList; import java.util.List; -import junit.framework.TestCase; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import org.junit.Test; /** * @author Juergen Hoeller */ -public class TypeUtilsTests extends TestCase { +public class TypeUtilsTests { public static List objects; @@ -35,7 +37,13 @@ public class TypeUtilsTests extends TestCase { public static List strings; - public void testClasses() { + public static List[] array; + + public static List[] openArray; + + + @Test + public void withClasses() { assertTrue(TypeUtils.isAssignable(Object.class, Object.class)); assertTrue(TypeUtils.isAssignable(Object.class, String.class)); assertFalse(TypeUtils.isAssignable(String.class, Object.class)); @@ -45,10 +53,20 @@ public class TypeUtilsTests extends TestCase { assertFalse(TypeUtils.isAssignable(List.class, HashSet.class)); } - public void testParameterizedTypes() throws Exception { + @Test + public void withParameterizedTypes() throws Exception { Type objectsType = getClass().getField("objects").getGenericType(); Type openObjectsType = getClass().getField("openObjects").getGenericType(); Type stringsType = getClass().getField("strings").getGenericType(); + assertTrue(TypeUtils.isAssignable(Object.class, objectsType)); + assertTrue(TypeUtils.isAssignable(Object.class, openObjectsType)); + assertTrue(TypeUtils.isAssignable(Object.class, stringsType)); + assertTrue(TypeUtils.isAssignable(List.class, objectsType)); + assertTrue(TypeUtils.isAssignable(List.class, openObjectsType)); + assertTrue(TypeUtils.isAssignable(List.class, stringsType)); + assertTrue(TypeUtils.isAssignable(objectsType, List.class)); + assertTrue(TypeUtils.isAssignable(openObjectsType, List.class)); + assertTrue(TypeUtils.isAssignable(stringsType, List.class)); assertTrue(TypeUtils.isAssignable(objectsType, objectsType)); assertTrue(TypeUtils.isAssignable(openObjectsType, openObjectsType)); assertTrue(TypeUtils.isAssignable(stringsType, stringsType)); @@ -58,4 +76,19 @@ public class TypeUtilsTests extends TestCase { assertFalse(TypeUtils.isAssignable(objectsType, stringsType)); } + @Test + public void withGenericArrayTypes() throws Exception { + Type arrayType = getClass().getField("array").getGenericType(); + Type openArrayType = getClass().getField("openArray").getGenericType(); + assertTrue(TypeUtils.isAssignable(Object.class, arrayType)); + assertTrue(TypeUtils.isAssignable(Object.class, openArrayType)); + assertTrue(TypeUtils.isAssignable(List[].class, arrayType)); + assertTrue(TypeUtils.isAssignable(List[].class, openArrayType)); + assertTrue(TypeUtils.isAssignable(arrayType, List[].class)); + assertTrue(TypeUtils.isAssignable(openArrayType, List[].class)); + assertTrue(TypeUtils.isAssignable(arrayType, arrayType)); + assertTrue(TypeUtils.isAssignable(openArrayType, openArrayType)); + assertTrue(TypeUtils.isAssignable(openArrayType, arrayType)); + } + }