Advertisement
Guest User

Untitled

a guest
Jun 24th, 2019
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.64 KB | None | 0 0
  1. import com.google.common.collect.ImmutableMap;
  2. import org.junit.Assert;
  3. import org.junit.Test;
  4.  
  5. import java.lang.annotation.Annotation;
  6. import java.lang.annotation.ElementType;
  7. import java.lang.annotation.Retention;
  8. import java.lang.annotation.RetentionPolicy;
  9. import java.lang.annotation.Target;
  10. import java.lang.reflect.InvocationTargetException;
  11. import java.lang.reflect.Method;
  12. import java.util.HashMap;
  13. import java.util.Map;
  14. import java.util.Optional;
  15. import java.util.stream.Stream;
  16.  
  17. import static java.lang.reflect.Modifier.isPublic;
  18. import static java.util.function.Function.identity;
  19. import static java.util.stream.Collectors.toMap;
  20.  
  21. public class EnumMap<T extends Enum<T>, A extends Annotation> extends HashMap<T, String> {
  22. private static final Map<Class<?>, Method> methodsCache = new HashMap<>();
  23.  
  24. public EnumMap(Class<T> clazz, Class<A> annotation) {
  25. super(constructEnumValuesMap(clazz, annotation));
  26. }
  27.  
  28. private static <T, A extends Annotation> Map<T, String> constructEnumValuesMap(Class<T> clazz, Class<A> annotation) {
  29. methodsCache.computeIfAbsent(clazz, cl -> getSerializer(cl, annotation));
  30. return Stream.of(clazz.getEnumConstants()).collect(toMap(identity(), EnumMap::serialize));
  31. }
  32.  
  33. private static <T> String serialize(T value) {
  34. Class<?> clazz = value.getClass();
  35. return Optional.ofNullable(methodsCache.get(clazz))
  36. .map(m -> invoke(m, value))
  37. .orElseThrow(() -> new IllegalArgumentException("No serializer found for class " + clazz));
  38. }
  39.  
  40. private static <T> String invoke(Method method, T value) {
  41. try {
  42. return (String) method.invoke(value);
  43. } catch (IllegalAccessException | InvocationTargetException e) {
  44. throw new IllegalStateException("Some unreal error", e);
  45. }
  46. }
  47.  
  48. private static <T, A extends Annotation> Method getSerializer(Class<T> clazz, Class<A> annotation) {
  49. return Stream.of(clazz.getDeclaredMethods())
  50. .filter(m -> isPublic(m.getModifiers()))
  51. .filter(m -> m.getParameterCount() == 0)
  52. .filter(m -> m.getReturnType() == String.class)
  53. .filter(m -> m.isAnnotationPresent(annotation))
  54. .findFirst().orElse(null);
  55. }
  56.  
  57. public static class MyTest extends Assert {
  58. @Test
  59. public void testOK() {
  60. Map<Gender, String> manualMap = ImmutableMap.of(Gender.MALE, "male", Gender.FEMALE, "female");
  61. assertEquals("oops!", manualMap, new EnumMap<>(Gender.class, JsonValue.class));
  62. }
  63.  
  64. @Test(expected = IllegalArgumentException.class)
  65. public void testAbsentAnnotation() {
  66. new EnumMap<>(AbsentAnnotation.class, JsonValue.class);
  67. }
  68.  
  69. @Test(expected = IllegalArgumentException.class)
  70. public void testWrongArgs() {
  71. new EnumMap<>(WrongArgs.class, JsonValue.class);
  72. }
  73.  
  74. @Test(expected = IllegalArgumentException.class)
  75. public void testWrongReturnType() {
  76. new EnumMap<>(WrongReturnType.class, JsonValue.class);
  77. }
  78. }
  79. }
  80.  
  81. enum Gender {
  82. MALE, FEMALE;
  83.  
  84. @JsonValue
  85. public String toValue() {
  86. return name().toLowerCase();
  87. }
  88. }
  89.  
  90. enum AbsentAnnotation {
  91. MALE, FEMALE;
  92.  
  93. public String toValue() {
  94. return name().toLowerCase();
  95. }
  96. }
  97.  
  98. enum WrongArgs {
  99. MALE, FEMALE;
  100.  
  101. @JsonValue
  102. public String toValue(String qwe) {
  103. return name().toLowerCase();
  104. }
  105. }
  106.  
  107. enum WrongReturnType {
  108. MALE, FEMALE;
  109.  
  110. @JsonValue
  111. public int toValue() {
  112. return name().length();
  113. }
  114. }
  115.  
  116. @Retention(RetentionPolicy.RUNTIME)
  117. @Target(ElementType.METHOD)
  118. @interface JsonValue {}
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement