I have implemented a Printer for printing (So you can convert the Enum to String, but not the other way around.
In the code below, you will find an example where the String/Name/Value/How-ever-you-call-it, is taken from a MessageSource (message property file) - this allows to support multiple languages.
public class EnumToStringPrinter implements Printer<Enum<?>> {
/** Use the same immutable value instead of creating an new array every time. */
private static final Object[] NO_PARAM = new Object[0];
/** The prefix of all message codes. */
private static final String PREFIX = "label_";
/** The separator in the message code, between different packages as well as between package can class. */
private static final String PACKAGE_SEPARATOR = "_";
/** The separator in the message code, between the class name and the enum case name. */
private static final String ENUM_CASE_SEPARATOR = "_";
/** The message source. */
private MessageSource messageSource;
@Autowired
public EnumToStringPrinter(final MessageSource messageSource) {
if(messageSource == null) {
throw new RuntimeException("messageSource must not be null");
}
this.messageSource = messageSource;
}
@Override
public String print(final Enum<?> source, final Locale locale) {
/* locale null can mean default locale, this depends on the messageSource implmentation */
if (source != null) {
String enumValueName = source.name();
String code = PREFIX + source.getClass().getName().toLowerCase().replace(".", PACKAGE_SEPARATOR)
+ ENUM_CASE_SEPARATOR + enumValueName.toLowerCase();
String message = messageSource.getMessage(code, NO_PARAM, enumValueName, locale);
return message;
} else {
return "";
}
}
}
The mayor drawback with Printers is, that it is hard to register them in Spring. Therefor I implemented a Printer2ConverterAdapter. and used the adaptor to register the Printer like a X->String Converter
/**
* Adapter that adapts a {@link Printer} to an Converter, more correct to an {@link GenericConverter}.
*
* Follows the Object Adapter pattern:
* <ul>
* <li>Adaptor - this class</li>
* <li>Target - {@link GenericConverter}</li>
* <li>Adaptee - the Printer {@link #Printer2ConverterAdapter(Printer)}</li>
* </ul>
*
* @author Ralph
*/
public class Printer2ConverterAdapter implements GenericConverter {
private final Class<?> printerObjectType;
@SuppressWarnings("rawtypes")
private final Printer printer;
public <T> Printer2ConverterAdapter(final Printer<T> printer) {
this.printerObjectType = resolvePrinterObjectType(printer);
this.printer = printer;
}
@Override
public Set<ConvertiblePair> getConvertibleTypes() {
return Collections.singleton(new ConvertiblePair(this.printerObjectType, String.class));
}
@SuppressWarnings("unchecked")
@Override
public Object convert(final Object source, final TypeDescriptor sourceType, final TypeDescriptor targetType) {
if (source == null) {
return "";
}
return this.printer.print(source, LocaleContextHolder.getLocale());
}
private Class<?> resolvePrinterObjectType(final Printer<?> printer) {
return GenericTypeResolver.resolveTypeArgument(printer.getClass(), Printer.class);
}
@Override
public String toString() {
return this.printerObjectType.getName() + " -> java.lang.String : " + this.printer;
}
}