package org.nuunframework.ensemble.util; import static org.junit.Assert.assertNull; import java.io.Serializable; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Vector; import org.junit.Assert; import org.junit.Test; import org.nuunframework.ensemble.util.TypeResolver; /** * @author Jonathan Halterman */ @SuppressWarnings("serial") public class TypeResolverTest { static class RepoImplA<A1, A2 extends Map<?, ?>> extends RepoImplB<A2, ArrayList<?>> { } static class RepoImplB<B1 extends Map<?, ?>, B2 extends List<?>> extends RepoImplC<B2, HashSet<?>, B1> { } static class RepoImplC<C1 extends List<?>, C2 extends Set<?>, C3 extends Map<?, ?>> implements IRepo<C3, C1, Vector<?>, C2> { } interface IRepo<I1, I2, I3, I4> extends Serializable, IIRepo<I1, I3> { } interface IIRepo<II1, II2> { } static class NonParameterizedType { } static class Foo extends Bar<ArrayList<?>> { } static class Bar<B extends List<?>> implements Baz<HashSet<?>, B> { } interface Baz<C1 extends Set<?>, C2 extends List<?>> { } static class SimpleRepo implements IIRepo<String, List<?>> { } static class Entity<ID extends Serializable, T, D, E> { ID id; void setId(List<ID> id) { } } static class SomeList extends ArrayList<Integer> { } static class SomeEntity extends Entity<Long, Object, Object, Object> { } @Test public void shouldResolveClass() throws Exception { Field field = Entity.class.getDeclaredField("id"); Assert.assertEquals(TypeResolver.resolveClass(field.getGenericType(), SomeEntity.class), Long.class); } @Test public void shouldResolveArgumentForGenericType() throws Exception { Method mutator = Entity.class.getDeclaredMethod("setId", List.class); Assert.assertEquals(TypeResolver.resolveArgument(mutator.getGenericParameterTypes()[0], SomeEntity.class), Long.class); Assert.assertEquals(TypeResolver.resolveArguments(SomeEntity.class, Entity.class)[0] , Long.class); Assert.assertEquals(TypeResolver.resolveArguments(SomeEntity.class, Entity.class)[1] , Object.class); Assert.assertEquals(TypeResolver.resolveArguments(SomeEntity.class, Entity.class)[2] , Object.class); Assert.assertEquals(TypeResolver.resolveArguments(SomeEntity.class, Entity.class)[3] , Object.class); } @Test public void shouldResolveArgumentForList() { Assert.assertEquals(TypeResolver.resolveArgument(SomeList.class, List.class), Integer.class); } @Test public void shouldResolveArgumentsForBazFromFoo() { Class<?>[] typeArguments = TypeResolver.resolveArguments(Foo.class, Baz.class); assert typeArguments[0] == HashSet.class; assert typeArguments[1] == ArrayList.class; } @Test public void shouldResolveArgumentsForNonParameterizedType() { assertNull(TypeResolver.resolveArguments(NonParameterizedType.class, NonParameterizedType.class)); } @Test public void shouldResolveArgumentsForIRepoFromRepoImplA() { Class<?>[] types = TypeResolver.resolveArguments(RepoImplA.class, IRepo.class); Assert.assertEquals(types[0], Map.class); Assert.assertEquals(types[1], ArrayList.class); Assert.assertEquals(types[2], Vector.class); Assert.assertEquals(types[3], HashSet.class); } @Test public void shouldResolveArgumentsForRepoImplCFromRepoImplA() { Class<?>[] types = TypeResolver.resolveArguments(RepoImplA.class, RepoImplC.class); Assert.assertEquals(types[0], ArrayList.class); Assert.assertEquals(types[1], HashSet.class); Assert.assertEquals(types[2], Map.class); } @Test public void shouldResolveArgumentsForRepoImplCFromRepoImplB() { Class<?>[] types = TypeResolver.resolveArguments(RepoImplB.class, RepoImplC.class); Assert.assertEquals(types[0], Object.class); Assert.assertEquals(types[1], HashSet.class); Assert.assertEquals(types[2], Object.class); } @Test public void shouldResolveArgumentsForIRepoFromRepoImplB() { Class<?>[] types = TypeResolver.resolveArguments(RepoImplB.class, IRepo.class); Assert.assertEquals(types[0], Map.class); Assert.assertEquals(types[1], List.class); Assert.assertEquals(types[2], Vector.class); Assert.assertEquals(types[3], HashSet.class); } @Test public void shouldResolveArgumentsForIRepoFromRepoImplC() { Class<?>[] types = TypeResolver.resolveArguments(RepoImplC.class, IRepo.class); Assert.assertEquals(types[0], Object.class); Assert.assertEquals(types[1], Object.class); Assert.assertEquals(types[2], Vector.class); Assert.assertEquals(types[3], Object.class); } @Test public void shouldResolveArgumentsForIIRepoFromRepoImplA() { Class<?>[] types = TypeResolver.resolveArguments(RepoImplA.class, IIRepo.class); Assert.assertEquals(types[0], Map.class); Assert.assertEquals(types[1], Vector.class); } @Test public void shouldResolveArgumentsForRepoImplBFromRepoImplA() { Class<?>[] types = TypeResolver.resolveArguments(RepoImplA.class, RepoImplB.class); Assert.assertEquals(types[0], Object.class); Assert.assertEquals(types[1], ArrayList.class); } @Test public void shouldResolveArgumentsForSimpleType() { Class<?>[] args = TypeResolver.resolveArguments(SimpleRepo.class, IIRepo.class); Assert.assertEquals(args[0], String.class); Assert.assertEquals(args[1], List.class); } }