Bläddra i källkod

Replace the isConfigObject method with the ConfigEntries annotation

Lortseam 4 år sedan
förälder
incheckning
47edc301a7

+ 5 - 17
src/main/java/me/lortseam/completeconfig/api/ConfigContainer.java

@@ -1,6 +1,7 @@
 package me.lortseam.completeconfig.api;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;
@@ -14,15 +15,6 @@ import java.util.List;
  */
 public interface ConfigContainer {
 
-    /**
-     * Specifies whether this class was solely created for config use.
-     *
-     * @return whether this class is a config class
-     */
-    default boolean isConfigObject() {
-        return false;
-    }
-
     default List<Class<? extends ConfigContainer>> getConfigClasses() {
         List<Class<? extends ConfigContainer>> classes = new ArrayList<>();
         Class<? extends ConfigContainer> clazz = getClass();
@@ -33,7 +25,7 @@ public interface ConfigContainer {
             }
             clazz = (Class<? extends ConfigContainer>) clazz.getSuperclass();
         }
-        return ImmutableList.copyOf(classes);
+        return Lists.reverse(ImmutableList.copyOf(classes));
     }
 
     /**
@@ -48,14 +40,11 @@ public interface ConfigContainer {
 
     /**
      * Applied to declare that a field of type {@link ConfigContainer} is transitive, which means the object will be
-     * registered the level of this container.
-     *
-     * <p>If {@link #isConfigObject()} returns {@code true}, all fields of type {@link ConfigContainer} will be
-     * resolved. Therefore, the use of this annotation is no longer needed in that case.
+     * registered at the level of this container.
      *
      * @see #getTransitives()
      */
-    @Target(ElementType.FIELD)
+    @Target({ElementType.FIELD, ElementType.TYPE})
     @Retention(RetentionPolicy.RUNTIME)
     @interface Transitive {
 
@@ -63,8 +52,7 @@ public interface ConfigContainer {
 
     /**
      * Applied to declare that a field should not be resolved as config entry.
-     *
-     * <p>Only required if {@link #isConfigObject()} returns {@code true}.
+     * This annotation is needed to exclude fields if the {@link ConfigEntries} annotation was applied to the class.
      */
     @Target(ElementType.FIELD)
     @Retention(RetentionPolicy.RUNTIME)

+ 12 - 0
src/main/java/me/lortseam/completeconfig/api/ConfigEntries.java

@@ -0,0 +1,12 @@
+package me.lortseam.completeconfig.api;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.TYPE)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ConfigEntries {
+
+}

+ 10 - 15
src/main/java/me/lortseam/completeconfig/data/EntryMap.java

@@ -1,8 +1,9 @@
 package me.lortseam.completeconfig.data;
 
 import com.google.common.base.CaseFormat;
-import me.lortseam.completeconfig.api.ConfigEntry;
 import me.lortseam.completeconfig.api.ConfigContainer;
+import me.lortseam.completeconfig.api.ConfigEntries;
+import me.lortseam.completeconfig.api.ConfigEntry;
 import me.lortseam.completeconfig.api.ConfigEntryListener;
 import me.lortseam.completeconfig.data.text.TranslationIdentifier;
 import me.lortseam.completeconfig.exception.IllegalAnnotationParameterException;
@@ -11,10 +12,10 @@ import me.lortseam.completeconfig.exception.IllegalReturnTypeException;
 
 import java.lang.reflect.Field;
 import java.lang.reflect.Modifier;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
+import java.util.function.Function;
 import java.util.regex.Pattern;
+import java.util.stream.Collectors;
 
 public class EntryMap extends DataMap<Entry> {
 
@@ -23,31 +24,28 @@ public class EntryMap extends DataMap<Entry> {
     }
 
     void resolve(ConfigContainer container) {
-        List<Entry> containerEntries = new ArrayList<>();
         for (Class<? extends ConfigContainer> clazz : container.getConfigClasses()) {
-            List<Entry> clazzEntries = new ArrayList<>();
-            Arrays.stream(clazz.getDeclaredFields()).filter(field -> {
+            putAll(Arrays.stream(clazz.getDeclaredFields()).filter(field -> {
                 if (clazz != container.getClass() && Modifier.isStatic(field.getModifiers())) {
                     return false;
                 }
-                if (container.isConfigObject()) {
+                if (clazz.isAnnotationPresent(ConfigEntries.class)) {
                     return !ConfigContainer.class.isAssignableFrom(field.getType()) && !field.isAnnotationPresent(ConfigContainer.Ignore.class);
                 }
                 return field.isAnnotationPresent(ConfigEntry.class);
-            }).forEach(field -> {
+            }).map(field -> {
                 if (Modifier.isFinal(field.getModifiers())) {
                     throw new IllegalModifierException("Entry field " + field + " must not be final");
                 }
                 Entry<?> entry = Entry.Draft.of(field, container.getClass()).build(Modifier.isStatic(field.getModifiers()) ? null : container, translation);
                 entry.resolve(field);
-                clazzEntries.add(entry);
-            });
-            containerEntries.addAll(0, clazzEntries);
+                return entry;
+            }).collect(Collectors.toMap(Entry::getID, Function.identity())));
             Arrays.stream(clazz.getDeclaredMethods()).filter(method -> {
                 if (clazz != container.getClass() && Modifier.isStatic(method.getModifiers())) {
                     return false;
                 }
-                return method.isAnnotationPresent(ConfigEntryListener.class) || container.isConfigObject() && method.getName().startsWith("set");
+                return method.isAnnotationPresent(ConfigEntryListener.class);
             }).forEach(method -> {
                 String fieldName = null;
                 Class<? extends ConfigContainer> fieldClass = clazz;
@@ -85,9 +83,6 @@ public class EntryMap extends DataMap<Entry> {
                 entry.interact(e -> e.addListener(method, Modifier.isStatic(method.getModifiers()) ? null : container));
             });
         }
-        for (Entry<?> entry : containerEntries) {
-            put(entry.getID(), entry);
-        }
     }
 
 }

+ 25 - 23
src/main/java/me/lortseam/completeconfig/data/Node.java

@@ -39,15 +39,11 @@ abstract class Node implements FlatDataPart<DataMap> {
 
     void resolve(ConfigContainer container) {
         entries.resolve(container);
-        List<ConfigContainer> containers = new ArrayList<>();
         for (Class<? extends ConfigContainer> clazz : container.getConfigClasses()) {
-            containers.addAll(Arrays.stream(clazz.getDeclaredFields()).filter(field -> {
-                if (container.isConfigObject()) {
-                    return ConfigContainer.class.isAssignableFrom(field.getType());
-                }
+            resolve(Arrays.stream(clazz.getDeclaredFields()).filter(field -> {
                 if (field.isAnnotationPresent(ConfigContainer.Transitive.class)) {
                     if (!ConfigContainer.class.isAssignableFrom(field.getType())) {
-                        throw new IllegalAnnotationTargetException("Transitive entry " + field + " must implement " + ConfigContainer.class.getSimpleName());
+                        throw new IllegalAnnotationTargetException("Transitive field " + field + " must implement " + ConfigContainer.class.getSimpleName());
                     }
                     return true;
                 }
@@ -62,27 +58,33 @@ abstract class Node implements FlatDataPart<DataMap> {
                     throw new RuntimeException(e);
                 }
             }).collect(Collectors.toList()));
-            if (container.isConfigObject()) {
-                resolve(Arrays.stream(clazz.getDeclaredClasses()).filter(nestedClass -> {
-                    return ConfigContainer.class.isAssignableFrom(nestedClass) && Modifier.isStatic(nestedClass.getModifiers());
-                }).map(nestedClass -> {
-                    try {
-                        Constructor<? extends ConfigContainer> constructor = (Constructor<? extends ConfigContainer>) nestedClass.getDeclaredConstructor();
-                        if (!constructor.isAccessible()) {
-                            constructor.setAccessible(true);
-                        }
-                        return constructor.newInstance();
-                    } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
-                        throw new RuntimeException("Failed to instantiate nested class " + nestedClass, e);
+            resolve(Arrays.stream(clazz.getDeclaredClasses()).filter(nestedClass -> {
+                if (nestedClass.isAnnotationPresent(ConfigContainer.Transitive.class)) {
+                    if (!ConfigContainer.class.isAssignableFrom(nestedClass)) {
+                        throw new IllegalAnnotationTargetException("Transitive class " + nestedClass + " must implement " + ConfigContainer.class.getSimpleName());
                     }
-                }).filter(Objects::nonNull).collect(Collectors.toList()));
-            }
+                    if (!Modifier.isStatic(nestedClass.getModifiers())) {
+                        throw new IllegalAnnotationTargetException("Transitive class " + nestedClass + " must be static");
+                    }
+                    return true;
+                }
+                return false;
+            }).map(nestedClass -> {
+                try {
+                    Constructor<? extends ConfigContainer> constructor = (Constructor<? extends ConfigContainer>) nestedClass.getDeclaredConstructor();
+                    if (!constructor.isAccessible()) {
+                        constructor.setAccessible(true);
+                    }
+                    return constructor.newInstance();
+                } catch (NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
+                    throw new RuntimeException("Failed to instantiate nested class " + nestedClass, e);
+                }
+            }).collect(Collectors.toList()));
         }
-        containers.addAll(Arrays.asList(container.getTransitives()));
-        resolve(containers);
+        resolve(Arrays.asList(container.getTransitives()));
     }
 
-    protected void resolve(java.util.Collection<ConfigContainer> containers) {
+    protected void resolve(Iterable<ConfigContainer> containers) {
         for (ConfigContainer c : containers) {
             if (c instanceof ConfigGroup) {
                 collections.resolve((ConfigGroup) c);