HHH-8854 Resolve any TypeVariables to Class or ParameterizedType when
creating AttributeConverterDefinition
This commit is contained in:
parent
b5845138e6
commit
bb2833bafc
|
@ -156,6 +156,7 @@ public class AttributeConverterDefinition {
|
|||
types.add( clazz.getGenericSuperclass() );
|
||||
types.addAll( Arrays.asList( clazz.getGenericInterfaces() ) );
|
||||
for ( Type type : types ) {
|
||||
type = resolveType( type, base );
|
||||
if ( ParameterizedType.class.isInstance( type ) ) {
|
||||
final ParameterizedType parameterizedType = (ParameterizedType) type;
|
||||
if ( AttributeConverter.class.equals( parameterizedType.getRawType() ) ) {
|
||||
|
@ -171,6 +172,54 @@ public class AttributeConverterDefinition {
|
|||
return null;
|
||||
}
|
||||
|
||||
private static Type resolveType(Type target, Type context) {
|
||||
if ( target instanceof ParameterizedType ) {
|
||||
return resolveParameterizedType( (ParameterizedType) target, context );
|
||||
}
|
||||
else if ( target instanceof TypeVariable ) {
|
||||
return resolveTypeVariable( (TypeVariable) target, (ParameterizedType) context );
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
private static ParameterizedType resolveParameterizedType(final ParameterizedType parameterizedType, Type context) {
|
||||
Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
|
||||
|
||||
final Type[] resolvedTypeArguments = new Type[actualTypeArguments.length];
|
||||
for ( int idx = 0; idx < actualTypeArguments.length; idx++ ) {
|
||||
resolvedTypeArguments[idx] = resolveType( actualTypeArguments[idx], context );
|
||||
}
|
||||
return new ParameterizedType() {
|
||||
|
||||
@Override
|
||||
public Type[] getActualTypeArguments() {
|
||||
return resolvedTypeArguments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getRawType() {
|
||||
return parameterizedType.getRawType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getOwnerType() {
|
||||
return parameterizedType.getOwnerType();
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
private static Type resolveTypeVariable(TypeVariable typeVariable, ParameterizedType context) {
|
||||
Class clazz = extractClass( context.getRawType() );
|
||||
TypeVariable[] typeParameters = clazz.getTypeParameters();
|
||||
for ( int idx = 0; idx < typeParameters.length; idx++ ) {
|
||||
if ( typeVariable.getName().equals( typeParameters[idx].getName() ) ) {
|
||||
return resolveType( context.getActualTypeArguments()[idx], context );
|
||||
}
|
||||
}
|
||||
return typeVariable;
|
||||
}
|
||||
|
||||
public AttributeConverter getAttributeConverter() {
|
||||
return attributeConverter;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@ package org.hibernate.test.type;
|
|||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.AttributeConverter;
|
||||
|
||||
import org.hibernate.cfg.AttributeConverterDefinition;
|
||||
|
@ -11,7 +13,8 @@ import org.junit.Test;
|
|||
|
||||
/**
|
||||
* Test the ability to interpret and understand AttributeConverter impls when the base class does not
|
||||
* explicitly implement AttributeConverter but implements it via an interface or superclass.
|
||||
* explicitly implement AttributeConverter but implements it via an interface or superclass. This also
|
||||
* involves resolving any TypeVariables to Class or ParameterizedType.
|
||||
*
|
||||
* @author Svein Baardsen
|
||||
*/
|
||||
|
@ -62,4 +65,38 @@ public class AttributeConverterOnSuperclassTest extends BaseUnitTestCase {
|
|||
assertEquals( String.class, def.getEntityAttributeType() );
|
||||
}
|
||||
|
||||
public static class NoopAttributeConverter<T> implements AttributeConverter<T, T> {
|
||||
|
||||
@Override
|
||||
public T convertToDatabaseColumn(T attribute) {
|
||||
return attribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T convertToEntityAttribute(T dbData) {
|
||||
return dbData;
|
||||
}
|
||||
}
|
||||
|
||||
public static class StringNoopAttributeConverter extends NoopAttributeConverter<String> {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTypeVariableAttributeConverterTypeArguments() {
|
||||
AttributeConverterDefinition def = AttributeConverterDefinition.from( StringNoopAttributeConverter.class );
|
||||
assertEquals( String.class, def.getEntityAttributeType() );
|
||||
}
|
||||
|
||||
public static class ListNoopAttributeConverter<T> extends NoopAttributeConverter<List<T>> {
|
||||
}
|
||||
|
||||
public static class StringListNoopAttributeConverter extends ListNoopAttributeConverter<String> {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParameterizedTypeWithTypeVariableAttributeConverterTypeArguments() {
|
||||
AttributeConverterDefinition def = AttributeConverterDefinition.from( StringListNoopAttributeConverter.class );
|
||||
assertEquals( List.class, def.getEntityAttributeType() );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue