Эх сурвалжийг харах

Implement own setter method finder for listeners

Lortseam 4 жил өмнө
parent
commit
8880422f74

+ 11 - 9
lib/src/main/java/me/lortseam/completeconfig/data/Entry.java

@@ -23,10 +23,8 @@ import org.apache.commons.lang3.StringUtils;
 import org.spongepowered.configurate.CommentedConfigurationNode;
 import org.spongepowered.configurate.serialize.SerializationException;
 
-import java.beans.IntrospectionException;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.lang.reflect.Type;
 import java.util.Arrays;
 import java.util.Objects;
@@ -67,6 +65,7 @@ public class Entry<T> implements DataPart, Identifiable, Translatable, TooltipSu
     private final boolean requiresRestart;
     private final String comment;
     private final UnaryOperator<T> valueModifier;
+    private final Setter<T> setter;
 
     protected Entry(EntryOrigin origin, UnaryOperator<T> valueModifier) {
         ConfigRegistry.register(origin);
@@ -81,6 +80,7 @@ public class Entry<T> implements DataPart, Identifiable, Translatable, TooltipSu
         id = annotation.isPresent() && !StringUtils.isBlank(annotation.get().value()) ? annotation.get().value() : origin.getField().getName();
         requiresRestart = annotation.isPresent() && annotation.get().requiresRestart();
         comment = annotation.isPresent() && !StringUtils.isBlank(annotation.get().comment()) ? annotation.get().comment() : null;
+        setter = ReflectionUtils.getSetterMethod(origin.getField()).<Setter<T>>map(method -> method::invoke).orElse((object, value) -> origin.getField().set(object, value));
     }
 
     protected Entry(EntryOrigin origin) {
@@ -127,13 +127,8 @@ public class Entry<T> implements DataPart, Identifiable, Translatable, TooltipSu
 
     private void set(T value) {
         try {
-            Optional<Method> writeMethod = ReflectionUtils.getWriteMethod(origin.getField());
-            if (writeMethod.isPresent()) {
-                writeMethod.get().invoke(origin.getObject(), value);
-            } else {
-                origin.getField().set(origin.getObject(), value);
-            }
-        } catch (IntrospectionException | IllegalAccessException | InvocationTargetException e) {
+            setter.set(origin.getObject(), value);
+        } catch (IllegalAccessException | InvocationTargetException e) {
             throw new RuntimeException("Failed to set entry value", e);
         }
     }
@@ -190,4 +185,11 @@ public class Entry<T> implements DataPart, Identifiable, Translatable, TooltipSu
         }
     }
 
+    @FunctionalInterface
+    private interface Setter<T> {
+
+        void set(ConfigContainer object, T value) throws IllegalAccessException, InvocationTargetException;
+
+    }
+
 }

+ 11 - 17
lib/src/main/java/me/lortseam/completeconfig/util/ReflectionUtils.java

@@ -1,24 +1,16 @@
 package me.lortseam.completeconfig.util;
 
-import com.google.common.collect.MoreCollectors;
 import com.google.common.reflect.TypeToken;
 import io.leangen.geantyref.GenericTypeReflector;
 import lombok.experimental.UtilityClass;
+import org.apache.commons.lang3.StringUtils;
 
-import java.beans.IntrospectionException;
-import java.beans.Introspector;
-import java.beans.PropertyDescriptor;
 import java.lang.reflect.*;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Map;
 import java.util.Optional;
 
 @UtilityClass
 public final class ReflectionUtils {
 
-    private static final Map<Field, Method> writeMethodsCache = new HashMap<>();
-
     public static Class<?> getTypeClass(Type type) {
         return TypeToken.of(type).getRawType();
     }
@@ -35,15 +27,17 @@ public final class ReflectionUtils {
         return constructor.newInstance();
     }
 
-    public static Optional<Method> getWriteMethod(Field field) throws IntrospectionException {
-        if (writeMethodsCache.containsKey(field)) {
-            return Optional.ofNullable(writeMethodsCache.get(field));
+    public static Optional<Method> getSetterMethod(Field field) {
+        Method method;
+        try {
+            method = field.getDeclaringClass().getDeclaredMethod("set" + StringUtils.capitalize(field.getName()), getTypeClass(getFieldType(field)));
+        } catch (NoSuchMethodException ignore) {
+            return Optional.empty();
+        }
+        if (Modifier.isStatic(field.getModifiers()) != Modifier.isStatic(method.getModifiers()) || !method.getReturnType().equals(Void.TYPE)) {
+            return Optional.empty();
         }
-        Optional<Method> writeMethod = Arrays.stream(Introspector.getBeanInfo(field.getDeclaringClass()).getPropertyDescriptors()).filter(property -> {
-            return property.getName().equals(field.getName());
-        }).collect(MoreCollectors.toOptional()).map(PropertyDescriptor::getWriteMethod);
-        writeMethodsCache.put(field, writeMethod.orElse(null));
-        return writeMethod;
+        return Optional.of(method);
     }
 
 }