diff --git a/src/main/java/org/hibernate/annotations/common/reflection/ReflectionManager.java b/src/main/java/org/hibernate/annotations/common/reflection/ReflectionManager.java index 8f2eb72..045dbca 100644 --- a/src/main/java/org/hibernate/annotations/common/reflection/ReflectionManager.java +++ b/src/main/java/org/hibernate/annotations/common/reflection/ReflectionManager.java @@ -8,6 +8,7 @@ import java.lang.reflect.AnnotatedElement; import java.lang.reflect.Method; +import java.lang.reflect.Type; import java.util.Map; /** @@ -23,6 +24,8 @@ public interface ReflectionManager { public Class toClass(XClass xClazz); + public Type toType(XClass xClazz); + public Method toMethod(XMethod method); public XPackage toXPackage(Package pkg); diff --git a/src/main/java/org/hibernate/annotations/common/reflection/java/JavaReflectionManager.java b/src/main/java/org/hibernate/annotations/common/reflection/java/JavaReflectionManager.java index d0b6858..39e62ee 100644 --- a/src/main/java/org/hibernate/annotations/common/reflection/java/JavaReflectionManager.java +++ b/src/main/java/org/hibernate/annotations/common/reflection/java/JavaReflectionManager.java @@ -175,6 +175,37 @@ public JavaXType toXType(TypeEnvironment context, Type propType) { throw new IllegalArgumentException( "No PropertyTypeExtractor available for type void " ); } + @Override + public Type toType(XClass xClazz) { + if ( ! ( xClazz instanceof JavaXClass ) ) { + throw new IllegalArgumentException( "XClass not coming from this ReflectionManager implementation" ); + } + final JavaXClass javaXClazz = (JavaXClass) xClazz; + final Class clazz = javaXClazz.toClass(); + final Type[] typeArguments = clazz.getTypeParameters(); + if ( typeArguments.length == 0 ) { + return clazz; + } + return javaXClazz.getTypeEnvironment().bind( + new ParameterizedType() { + @Override + public Type[] getActualTypeArguments() { + return typeArguments; + } + + @Override + public Type getRawType() { + return clazz; + } + + @Override + public Type getOwnerType() { + return null; + } + } + ); + } + public boolean equals(XClass class1, Class class2) { if ( class1 == null ) { return class2 == null; diff --git a/src/main/java/org/hibernate/annotations/common/reflection/java/generics/TypeFactory.java b/src/main/java/org/hibernate/annotations/common/reflection/java/generics/TypeFactory.java index 07795e5..2a79ec5 100644 --- a/src/main/java/org/hibernate/annotations/common/reflection/java/generics/TypeFactory.java +++ b/src/main/java/org/hibernate/annotations/common/reflection/java/generics/TypeFactory.java @@ -11,6 +11,7 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.Arrays; +import java.util.StringJoiner; /** * This class instances our own ParameterizedTypes and GenericArrayTypes. @@ -57,6 +58,42 @@ public int hashCode() { getOwnerType() ); } + + @Override + public String toString() { + final StringBuilder sb = new StringBuilder(); + if ( ownerType != null ) { + sb.append( ownerType.getTypeName() ); + + sb.append( "$" ); + + if ( ownerType instanceof ParameterizedType ) { + // Find simple name of nested type by removing the + // shared prefix with owner. + sb.append( + rawType.getTypeName().replace( + ( (ParameterizedType) ownerType ).getRawType().getTypeName() + "$", + "" + ) + ); + } else if ( rawType instanceof Class ) { + sb.append( ( (Class) rawType ).getSimpleName() ); + } else + sb.append( rawType.getTypeName() ); + } else + sb.append( rawType.getTypeName() ); + + if ( substTypeArgs != null ) { + final StringJoiner sj = new StringJoiner( ", ", "<", ">" ); + sj.setEmptyValue( "" ); + for ( Type t : substTypeArgs ) { + sj.add( t.getTypeName() ); + } + sb.append( sj ); + } + + return sb.toString(); + } }; } diff --git a/src/test/java/org/hibernate/annotations/common/test/reflection/java/JavaXClassTest.java b/src/test/java/org/hibernate/annotations/common/test/reflection/java/JavaXClassTest.java index 71777d3..d7a6f1e 100644 --- a/src/test/java/org/hibernate/annotations/common/test/reflection/java/JavaXClassTest.java +++ b/src/test/java/org/hibernate/annotations/common/test/reflection/java/JavaXClassTest.java @@ -7,6 +7,8 @@ package org.hibernate.annotations.common.test.reflection.java; import java.io.Serializable; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.util.List; import org.hibernate.annotations.common.reflection.ReflectionManager; @@ -88,6 +90,19 @@ public void testCanBeAnEnum() { assertTrue( factory.toXClass( Sex.class ).isEnum() ); } + public void testParameterizedType() { + Type type = factory.toType( + fatherAsSeenFromSon.getDeclaredProperties( "property" ) + .stream() + .filter( p -> p.getName().equals( "genericCollectionProperty" ) ) + .findFirst() + .get() + .getType() + ); + assertTrue( type instanceof ParameterizedType ); + assertEquals( String.class, ((ParameterizedType) type).getActualTypeArguments()[0] ); + } + @Override protected XAnnotatedElement getConcreteInstance() { return factory.toXClass( Dad.class );