package io.gitlab.jfronny.libjf.config.impl.reflect; import io.gitlab.jfronny.commons.reflect.Reflect; import io.gitlab.jfronny.commons.throwable.ThrowingConsumer; import io.gitlab.jfronny.libjf.LibJf; import io.gitlab.jfronny.libjf.config.api.v1.*; import io.gitlab.jfronny.libjf.config.api.v1.dsl.CategoryBuilder; import io.gitlab.jfronny.libjf.config.api.v1.dsl.ConfigBuilder; import io.gitlab.jfronny.libjf.config.api.v1.reflect.ReflectiveConfigBuilder; import io.gitlab.jfronny.libjf.config.impl.AuxiliaryMetadata; import io.gitlab.jfronny.libjf.config.impl.dsl.DslEntryInfo; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.Objects; public class ReflectiveConfigBuilderImpl implements ReflectiveConfigBuilder { public static final String CONFIG_PRESET_DEFAULT = "libjf-config-v1.default"; private final AuxiliaryMetadata rootMeta; private final Class rootClass; public ReflectiveConfigBuilderImpl(String id, Class klazz) { this.rootClass = Objects.requireNonNull(klazz); this.rootMeta = AuxiliaryMetadata.of(klazz.getAnnotation(JfConfig.class)) .merge(AuxiliaryMetadata.forMod(id)); } @Override public ConfigBuilder apply(ConfigBuilder builder) { return applyCategory(builder, rootClass, rootMeta); } private static > T applyCategory(T builder, Class configClass, AuxiliaryMetadata meta) { meta.applyTo(builder); for (Field field : configClass.getFields()) { if (field.isAnnotationPresent(Entry.class)) { builder.value(DslEntryInfo.ofField(field)); } } builder.addPreset(CONFIG_PRESET_DEFAULT, ConfigCategory::reset); for (Method method : configClass.getMethods()) { try { if (method.isAnnotationPresent(Preset.class)) { builder.addPreset(builder.getTranslationPrefix() + method.getName(), ReflectiveConfigBuilderImpl.staticToConsumer(configClass, method).addHandler(e -> LibJf.LOGGER.error("Could not apply preset", e))); } else if (method.isAnnotationPresent(Verifier.class)) { builder.addVerifier(ReflectiveConfigBuilderImpl.staticToConsumer(configClass, method).addHandler(e -> LibJf.LOGGER.error("Could not run verifier", e))); } } catch (Throwable t) { LibJf.LOGGER.error("Could not process method " + method.getName() + " of config class " + configClass.getName()); } } for (Class categoryClass : configClass.getClasses()) { if (categoryClass.isAnnotationPresent(Category.class)) { String name = categoryClass.getSimpleName(); name = Character.toLowerCase(name.charAt(0)) + name.substring(1); // camelCase builder.category(name, builder1 -> applyCategory(builder1, categoryClass, AuxiliaryMetadata.of(categoryClass.getAnnotation(Category.class)))); } } return builder; } public static ThrowingConsumer staticToConsumer(Class klazz, Method method) throws Throwable { Runnable rn = Reflect.staticProcedure(klazz, method.getName()); return c -> rn.run(); } }