Added support for config map gen

#59
Hopefully
Also added support for setting the path automatically
This commit is contained in:
Norbi Peti 2019-04-29 12:53:26 +02:00
parent ce29422177
commit 4dade43f82
4 changed files with 54 additions and 25 deletions

View file

@ -42,7 +42,7 @@ public abstract class ButtonPlugin extends JavaPlugin {
@Override
public final void onEnable() {
loadConfig();
IHaveConfig.pregenConfig(this, iConfig);
IHaveConfig.pregenConfig(this, null);
try {
pluginEnable();
} catch (Exception e) {

View file

@ -85,7 +85,7 @@ public abstract class Component<TP extends JavaPlugin> {
}
component.plugin = plugin;
updateConfig(plugin, component);
IHaveConfig.pregenConfig(component, component.config);
IHaveConfig.pregenConfig(component, null);
component.register(plugin);
components.put(component.getClass(), component);
if (plugin instanceof ButtonPlugin)

View file

@ -5,7 +5,7 @@ import buttondevteam.lib.ThorpeUtils;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.bukkit.Bukkit;
import org.bukkit.configuration.Configuration;
import org.bukkit.configuration.ConfigurationSection;
@ -20,9 +20,8 @@ import java.util.function.Function;
/**
* Use the getter/setter constructor if {@link T} isn't a primitive type or String.<br>
* Use {@link Component#getConfig()} or {@link ButtonPlugin#getIConfig()} then {@link IHaveConfig#getData(String, Object)} to get an instance.
* Use {@link Component#getConfig()} or {@link ButtonPlugin#getIConfig()} then {@link IHaveConfig#getData(String, Object)} to get an instance.
*/
@RequiredArgsConstructor(access = AccessLevel.PACKAGE)
//@AllArgsConstructor(access = AccessLevel.PACKAGE)
public class ConfigData<T> {
private static final HashMap<Configuration, SaveTask> saveTasks = new HashMap<>();
@ -31,7 +30,8 @@ public class ConfigData<T> {
*/
private final ConfigurationSection config;
@Getter
private final String path;
@Setter(AccessLevel.PACKAGE)
private String path;
private final T def;
private final Object primitiveDef;
private final Runnable saveAction;
@ -54,14 +54,23 @@ public class ConfigData<T> {
private boolean saved = false;
//This constructor is needed because it sets the getter and setter
public ConfigData(ConfigurationSection config, String path, T def, Object primitiveDef, Function<Object, T> getter, Function<T, Object> setter, Runnable saveAction) {
ConfigData(ConfigurationSection config, String path, T def, Object primitiveDef, Function<Object, T> getter, Function<T, Object> setter, Runnable saveAction) {
this.config = config;
this.path = path;
this.def = def;
this.primitiveDef = primitiveDef;
this.getter = getter;
this.setter = setter;
this.saveAction=saveAction;
this.saveAction = saveAction;
}
@java.beans.ConstructorProperties({"config", "path", "def", "primitiveDef", "saveAction"})
ConfigData(ConfigurationSection config, String path, T def, Object primitiveDef, Runnable saveAction) {
this.config = config;
this.path = path;
this.def = def;
this.primitiveDef = primitiveDef;
this.saveAction = saveAction;
}
@Override
@ -106,7 +115,7 @@ public class ConfigData<T> {
else val = value;
if (config != null) {
config.set(path, val);
if(!saveTasks.containsKey(config.getRoot())) {
if (!saveTasks.containsKey(config.getRoot())) {
synchronized (saveTasks) {
saveTasks.put(config.getRoot(), new SaveTask(Bukkit.getScheduler().runTaskLaterAsynchronously(MainPlugin.Instance, () -> {
synchronized (saveTasks) {

View file

@ -6,9 +6,12 @@ import lombok.Getter;
import lombok.val;
import org.bukkit.configuration.ConfigurationSection;
import java.util.HashMap;
import javax.annotation.Nullable;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collectors;
/**
* A config system
@ -26,7 +29,7 @@ public final class IHaveConfig {
*/
IHaveConfig(ConfigurationSection section, Runnable saveAction) {
config = section;
this.saveAction=saveAction;
this.saveAction = saveAction;
}
/**
@ -65,11 +68,11 @@ public final class IHaveConfig {
/**
* This method overload may be used with any class. The given default value will be run through the getter.
*
* @param path The path in config to use
* @param primitiveDef The <b>primitive</b> value to use by default
* @param getter A function that converts a primitive representation to the correct value
* @param setter A function that converts a value to a primitive representation
* @param <T> The type of this variable (can be any class)
* @param path The path in config to use
* @param primitiveDef The <b>primitive</b> value to use by default
* @param getter A function that converts a primitive representation to the correct value
* @param setter A function that converts a value to a primitive representation
* @param <T> The type of this variable (can be any class)
* @return The data object that can be used to get or set the value
*/
@SuppressWarnings("unchecked")
@ -121,22 +124,39 @@ public final class IHaveConfig {
/**
* Generates the config YAML.
*
* @param obj The object which has config methods
* @param config The config that holds the values
* @param obj The object which has config methods
* @param configMap The result from {@link Component#getConfigMap(String, Map)}. May be null.
*/
public static void pregenConfig(Object obj, IHaveConfig config) {
public static void pregenConfig(Object obj, @Nullable Map<String, IHaveConfig> configMap) {
val ms = obj.getClass().getDeclaredMethods();
for (val m : ms) {
if (!m.getReturnType().getName().equals(ConfigData.class.getName())) continue;
try {
m.setAccessible(true);
List<ConfigData<?>> configList;
if (m.getParameterCount() == 0) {
m.setAccessible(true);
ConfigData<?> c = (ConfigData<?>) m.invoke(obj);
if (!c.getPath().equals(m.getName()))
MainPlugin.Instance.getLogger().warning("Config name does not match: " + c.getPath() + " instead of " + m.getName()); //TODO: Set it here
configList = Collections.singletonList((ConfigData<?>) m.invoke(obj));
} else if (m.getParameterCount() == 1 && m.getParameterTypes()[0] == IHaveConfig.class) {
if (configMap == null) continue; //Hope it will get called with the param later
configList = configMap.entrySet().stream().map(kv ->
{
try {
return (ConfigData<?>) m.invoke(obj, kv.getValue());
} catch (IllegalAccessException | InvocationTargetException e) {
TBMCCoreAPI.SendException("Failed to pregenerate " + m.getName() + " for " + obj + " using config " + kv.getKey() + "!", e);
return null;
}
}).filter(Objects::nonNull).collect(Collectors.toList());
} else {
MainPlugin.Instance.getLogger().warning("Method " + m.getName() + " returns a config but its parameters are unknown: " + Arrays.toString(m.getParameterTypes()));
continue;
}
for (val c : configList) {
if (c.getPath().length() == 0)
c.setPath(m.getName());
else if (!c.getPath().equals(m.getName()))
MainPlugin.Instance.getLogger().warning("Config name does not match: " + c.getPath() + " instead of " + m.getName());
c.get(); //Saves the default value if needed - also checks validity
} else if (m.getParameterCount() == 1) {
//TODO: Config map
}
} catch (Exception e) {
TBMCCoreAPI.SendException("Failed to pregenerate " + m.getName() + " for " + obj + "!", e);