[SPR-5644] Support for Enum<?> and Enum<T> values as FQN.FIELD_NAME in type conversion
This commit is contained in:
parent
f7562614bc
commit
1480202aa3
|
|
@ -232,18 +232,8 @@ class TypeConverterDelegate {
|
||||||
// It's an empty enum identifier: reset the enum value to null.
|
// It's an empty enum identifier: reset the enum value to null.
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// Try field lookup as fallback: for JDK 1.5 enum or custom enum
|
|
||||||
// with values defined as static fields. Resulting value still needs
|
convertedValue = attemptToConvertStringToEnum(requiredType, trimmedValue, convertedValue);
|
||||||
// to be checked, hence we don't return it right away.
|
|
||||||
try {
|
|
||||||
Field enumField = requiredType.getField(trimmedValue);
|
|
||||||
convertedValue = enumField.get(null);
|
|
||||||
}
|
|
||||||
catch (Throwable ex) {
|
|
||||||
if (logger.isTraceEnabled()) {
|
|
||||||
logger.trace("Field [" + convertedValue + "] isn't an enum value", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -270,6 +260,52 @@ class TypeConverterDelegate {
|
||||||
return (T) convertedValue;
|
return (T) convertedValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Object attemptToConvertStringToEnum(Class<?> requiredType, String trimmedValue, Object currentConvertedValue) {
|
||||||
|
Object convertedValue = currentConvertedValue;
|
||||||
|
|
||||||
|
if(Enum.class.equals(requiredType)) {
|
||||||
|
// target type is declared as raw enum, treat the trimmed value as <enum.fqn>.FIELD_NAME
|
||||||
|
int index = trimmedValue.lastIndexOf(".");
|
||||||
|
if(index > - 1) {
|
||||||
|
String enumType = trimmedValue.substring(0, index);
|
||||||
|
String fieldName = trimmedValue.substring(index + 1);
|
||||||
|
|
||||||
|
ClassLoader loader = this.targetObject.getClass().getClassLoader();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Class<?> enumValueType = loader.loadClass(enumType);
|
||||||
|
Field enumField = enumValueType.getField(fieldName);
|
||||||
|
convertedValue = enumField.get(null);
|
||||||
|
} catch(ClassNotFoundException ex) {
|
||||||
|
if(logger.isTraceEnabled()) {
|
||||||
|
logger.trace("Enum class [" + enumType + "] cannot be loaded from [" + loader + "]", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
if(logger.isTraceEnabled()) {
|
||||||
|
logger.trace("Field [" + fieldName + "] isn't an enum value for type [" + enumType + "]", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (convertedValue == currentConvertedValue) {
|
||||||
|
// Try field lookup as fallback: for JDK 1.5 enum or custom enum
|
||||||
|
// with values defined as static fields. Resulting value still needs
|
||||||
|
// to be checked, hence we don't return it right away.
|
||||||
|
try {
|
||||||
|
Field enumField = requiredType.getField(trimmedValue);
|
||||||
|
convertedValue = enumField.get(null);
|
||||||
|
}
|
||||||
|
catch (Throwable ex) {
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("Field [" + convertedValue + "] isn't an enum value", ex);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return convertedValue;
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Find a default editor for the given type.
|
* Find a default editor for the given type.
|
||||||
* @param requiredType the type to find an editor for
|
* @param requiredType the type to find an editor for
|
||||||
|
|
|
||||||
|
|
@ -1462,6 +1462,21 @@ public final class BeanWrapperTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGenericEnum() {
|
||||||
|
EnumConsumer consumer = new EnumConsumer();
|
||||||
|
BeanWrapper bw = new BeanWrapperImpl(consumer);
|
||||||
|
bw.setPropertyValue("enumValue", TestEnum.class.getName() + ".TEST_VALUE");
|
||||||
|
assertEquals(TestEnum.TEST_VALUE, consumer.getEnumValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testWildcardedGenericEnum() {
|
||||||
|
WildcardEnumConsumer consumer = new WildcardEnumConsumer();
|
||||||
|
BeanWrapper bw = new BeanWrapperImpl(consumer);
|
||||||
|
bw.setPropertyValue("enumValue", TestEnum.class.getName() + ".TEST_VALUE");
|
||||||
|
assertEquals(TestEnum.TEST_VALUE, consumer.getEnumValue());
|
||||||
|
}
|
||||||
|
|
||||||
private static class DifferentTestBean extends TestBean {
|
private static class DifferentTestBean extends TestBean {
|
||||||
// class to test naming of beans in a BeanWrapper error message
|
// class to test naming of beans in a BeanWrapper error message
|
||||||
|
|
@ -1747,4 +1762,32 @@ public final class BeanWrapperTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class EnumConsumer {
|
||||||
|
private Enum<TestEnum> enumValue;
|
||||||
|
|
||||||
|
public Enum<TestEnum> getEnumValue() {
|
||||||
|
return enumValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnumValue(Enum<TestEnum> enumValue) {
|
||||||
|
this.enumValue = enumValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class WildcardEnumConsumer {
|
||||||
|
private Enum<?> enumValue;
|
||||||
|
|
||||||
|
public Enum<?> getEnumValue() {
|
||||||
|
return enumValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnumValue(Enum<?> enumValue) {
|
||||||
|
this.enumValue = enumValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TestEnum {
|
||||||
|
TEST_VALUE
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue