se.l4.commons.serialization.enums.EnumSerializerResolver Maven / Gradle / Ivy
package se.l4.commons.serialization.enums;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.util.Set;
import com.google.common.base.Throwables;
import com.google.common.collect.ImmutableSet;
import se.l4.commons.serialization.SerializationException;
import se.l4.commons.serialization.Serializer;
import se.l4.commons.serialization.spi.AbstractSerializerResolver;
import se.l4.commons.serialization.spi.TypeEncounter;
/**
* Resolver for {@link Enum enums}, can handle any enum type and supports
* different translators between serialized and object form.
*
* @author Andreas Holstenson
*
*/
public class EnumSerializerResolver
extends AbstractSerializerResolver>
{
private static final Set> HINTS =
ImmutableSet.>of(MapEnumVia.class);
@Override
@SuppressWarnings({ "unchecked", "rawtypes" })
public Serializer> find(TypeEncounter encounter)
{
Class extends Enum>> type = (Class extends Enum>>) encounter.getType().getErasedType();
MapEnumVia hint = encounter.getHint(MapEnumVia.class);
ValueTranslator translator;
if(hint != null)
{
translator = create(hint.value(), type);
}
else if((hint = type.getAnnotation(MapEnumVia.class)) != null)
{
translator = create(hint.value(), type);
}
else
{
translator = new NameTranslator(type);
}
return new EnumSerializer(translator);
}
@SuppressWarnings("rawtypes")
private ValueTranslator create(
Class extends ValueTranslator> translator,
Class extends Enum>> type)
{
for(Constructor c : translator.getConstructors())
{
Class[] types = c.getParameterTypes();
if(types.length != 1) continue;
Class> t = types[0];
if(t.isAssignableFrom(Class.class))
{
try
{
return (ValueTranslator) c.newInstance(type);
}
catch(InstantiationException e)
{
Throwables.propagateIfInstanceOf(e.getCause(), SerializationException.class);
throw new SerializationException("Unable to create; " + e.getCause().getMessage(), e.getCause());
}
catch(Exception e)
{
throw new SerializationException("Unable to create; " + e.getMessage(), e);
}
}
}
throw new SerializationException("Constructor that takes Enum is required (for " + translator + ")");
}
@Override
public Set> getHints()
{
return HINTS;
}
}