Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import com.google.common.collect.ImmutableMap;
- import org.junit.Assert;
- import org.junit.Test;
- import java.lang.annotation.Annotation;
- import java.lang.annotation.ElementType;
- import java.lang.annotation.Retention;
- import java.lang.annotation.RetentionPolicy;
- import java.lang.annotation.Target;
- import java.lang.reflect.InvocationTargetException;
- import java.lang.reflect.Method;
- import java.util.HashMap;
- import java.util.Map;
- import java.util.Optional;
- import java.util.stream.Stream;
- import static java.lang.reflect.Modifier.isPublic;
- import static java.util.function.Function.identity;
- import static java.util.stream.Collectors.toMap;
- public class EnumMap<T extends Enum<T>, A extends Annotation> extends HashMap<T, String> {
- private static final Map<Class<?>, Method> methodsCache = new HashMap<>();
- public EnumMap(Class<T> clazz, Class<A> annotation) {
- super(constructEnumValuesMap(clazz, annotation));
- }
- private static <T, A extends Annotation> Map<T, String> constructEnumValuesMap(Class<T> clazz, Class<A> annotation) {
- methodsCache.computeIfAbsent(clazz, cl -> getSerializer(cl, annotation));
- return Stream.of(clazz.getEnumConstants()).collect(toMap(identity(), EnumMap::serialize));
- }
- private static <T> String serialize(T value) {
- Class<?> clazz = value.getClass();
- return Optional.ofNullable(methodsCache.get(clazz))
- .map(m -> invoke(m, value))
- .orElseThrow(() -> new IllegalArgumentException("No serializer found for class " + clazz));
- }
- private static <T> String invoke(Method method, T value) {
- try {
- return (String) method.invoke(value);
- } catch (IllegalAccessException | InvocationTargetException e) {
- throw new IllegalStateException("Some unreal error", e);
- }
- }
- private static <T, A extends Annotation> Method getSerializer(Class<T> clazz, Class<A> annotation) {
- return Stream.of(clazz.getDeclaredMethods())
- .filter(m -> isPublic(m.getModifiers()))
- .filter(m -> m.getParameterCount() == 0)
- .filter(m -> m.getReturnType() == String.class)
- .filter(m -> m.isAnnotationPresent(annotation))
- .findFirst().orElse(null);
- }
- public static class MyTest extends Assert {
- @Test
- public void testOK() {
- Map<Gender, String> manualMap = ImmutableMap.of(Gender.MALE, "male", Gender.FEMALE, "female");
- assertEquals("oops!", manualMap, new EnumMap<>(Gender.class, JsonValue.class));
- }
- @Test(expected = IllegalArgumentException.class)
- public void testAbsentAnnotation() {
- new EnumMap<>(AbsentAnnotation.class, JsonValue.class);
- }
- @Test(expected = IllegalArgumentException.class)
- public void testWrongArgs() {
- new EnumMap<>(WrongArgs.class, JsonValue.class);
- }
- @Test(expected = IllegalArgumentException.class)
- public void testWrongReturnType() {
- new EnumMap<>(WrongReturnType.class, JsonValue.class);
- }
- }
- }
- enum Gender {
- MALE, FEMALE;
- @JsonValue
- public String toValue() {
- return name().toLowerCase();
- }
- }
- enum AbsentAnnotation {
- MALE, FEMALE;
- public String toValue() {
- return name().toLowerCase();
- }
- }
- enum WrongArgs {
- MALE, FEMALE;
- @JsonValue
- public String toValue(String qwe) {
- return name().toLowerCase();
- }
- }
- enum WrongReturnType {
- MALE, FEMALE;
- @JsonValue
- public int toValue() {
- return name().length();
- }
- }
- @Retention(RetentionPolicy.RUNTIME)
- @Target(ElementType.METHOD)
- @interface JsonValue {}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement