diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonComponent.kt b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonComponent.kt new file mode 100644 index 0000000..fb239b1 --- /dev/null +++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ButtonComponent.kt @@ -0,0 +1,15 @@ +package buttondevteam.lib.architecture + +import org.bukkit.configuration.ConfigurationSection +import org.bukkit.plugin.java.JavaPlugin + +/** + * A wrapper for plugin components. This is used internally. + */ +class ButtonComponent( + val plugin: TP, + saveAction: Runnable, + config: ConfigurationSection +) { + val config = IHaveConfig(saveAction, config) +} \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/Component.kt b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/Component.kt index 40cb941..55fa8b1 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/Component.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/Component.kt @@ -16,12 +16,12 @@ import java.util.stream.Collectors * Configuration is based on class name */ @HasConfig(global = false) //Used for obtaining javadoc -abstract class Component { +abstract class Component { var isEnabled = false + private var wrapper: ButtonComponent? = null - var plugin: TP? = null - - val config = IHaveConfig(null) + val config get() = wrapper!!.config + val plugin get() = wrapper!!.plugin private val data //TODO : IHaveConfig? = null @@ -32,11 +32,11 @@ abstract class Component { .orElse(true)) fun log(message: String) { - plugin!!.logger.info("[$className] $message") + plugin.logger.info("[$className] $message") } fun logWarn(message: String) { - plugin!!.logger.warning("[$className] $message") + plugin.logger.warning("[$className] $message") } /** @@ -45,7 +45,7 @@ abstract class Component { * * @param plugin Plugin object */ - protected open fun register(plugin: JavaPlugin?) {} + protected open fun register(plugin: JavaPlugin) {} /** * Unregisters the module, when called by the JavaPlugin class. @@ -54,7 +54,7 @@ abstract class Component { * * @param plugin Plugin object */ - protected open fun unregister(plugin: JavaPlugin?) {} + protected open fun unregister(plugin: JavaPlugin) {} /** * Enables the module, when called by the JavaPlugin class. Call @@ -100,25 +100,19 @@ abstract class Component { * @param defaultProvider A mapping between config paths and config generators * @return A map containing configs */ - fun getConfigMap(key: String?, defaultProvider: Map>): Map { + fun getConfigMap(key: String, defaultProvider: Map>): Map { val c: ConfigurationSection = config.config var cs = c.getConfigurationSection(key) if (cs == null) cs = c.createSection(key) - val res = cs!!.getValues(false).entries.stream() - .filter { (_, value): Map.Entry -> value is ConfigurationSection } - .collect( - Collectors.toMap, String, IHaveConfig>( - { it.key }, - { (_, value): Map.Entry -> - val conf = IHaveConfig { plugin!!.saveConfig() } - conf.reset(value as ConfigurationSection?) - conf - }) - ) + val res = cs.getValues(false).entries.stream() + .filter { (_, value) -> value is ConfigurationSection } + .collect(Collectors.toMap( + { it.key }, + { (_, value) -> IHaveConfig(plugin::saveConfig, value as ConfigurationSection) } + )) if (res.isEmpty()) { for ((key1, value) in defaultProvider) { - val conf = IHaveConfig { plugin!!.saveConfig() } - conf.reset(cs.createSection(key1)) + val conf = IHaveConfig(plugin::saveConfig, cs.createSection(key1)) value.accept(conf) res[key1] = conf } @@ -159,7 +153,7 @@ abstract class Component { return registerUnregisterComponent(plugin, component, false) } - fun registerUnregisterComponent( + private fun registerUnregisterComponent( plugin: T, component: Component, register: Boolean @@ -184,9 +178,7 @@ abstract class Component { ) return false } - component.plugin = plugin // TODO: Perhaps construct a new object with these initialized - component.config.saveAction = Runnable { plugin.saveConfig() } - updateConfig(plugin, component) + val wrapper = ButtonComponent(plugin, { plugin.saveConfig() }, getConfigSection(plugin, component)) component.register(plugin) components[component.javaClass] = component if (plugin is ButtonPlugin) (plugin as ButtonPlugin).componentStack.push(component) @@ -250,7 +242,7 @@ abstract class Component { if (component.isEnabled == enabled) return //Don't do anything if (enabled.also { component.isEnabled = it }) { try { - updateConfig(component.plugin!!, component) + getConfigSection(component.plugin!!, component) component.enable() if (ButtonPlugin.configGenAllowed(component)) { IHaveConfig.pregenConfig(component, null) @@ -276,15 +268,13 @@ abstract class Component { } } - @JvmStatic - fun updateConfig(plugin: JavaPlugin, component: Component<*>) { - if (plugin.config != null) { //Production - var compconf = plugin.config.getConfigurationSection("components") - if (compconf == null) compconf = plugin.config.createSection("components") - var configSect = compconf!!.getConfigurationSection(component.className) - if (configSect == null) configSect = compconf.createSection(component.className) - component.config.reset(configSect) - } //Testing: it's already set + private fun getConfigSection(plugin: JavaPlugin, component: Component<*>): ConfigurationSection { + var compconf = plugin.config.getConfigurationSection("components") + if (compconf == null) compconf = plugin.config.createSection("components") + var configSect = compconf.getConfigurationSection(component.className) + if (configSect == null) configSect = compconf.createSection(component.className) + return configSect + // TODO: Support tests (provide Bukkit configuration for tests) } /** diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt index c979c3c..a893dad 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/ConfigData.kt @@ -44,8 +44,9 @@ class ConfigData internal constructor( value = null } - override fun get(): T? { - if (value != null) return value //Speed things up + override fun get(): T { + val cachedValue = value + if (cachedValue != null) return cachedValue //Speed things up val config = config?.config var `val`: Any? if (config == null || !config.isSet(path)) { @@ -54,14 +55,14 @@ class ConfigData internal constructor( } else `val` = config.get(path) //config==null: testing if (`val` == null) //If it's set to null explicitly `val` = pdef - fun convert(_val: Any?, _pdef: Any?): Any? { - return if (_pdef is Number) //If we expect a number - if (_val is Number) - ChromaUtils.convertNumber(_val as Number?, _pdef.javaClass as Class) - else _pdef //If we didn't get a number, return default (which is a number) - else if (_val is List<*> && _pdef != null && _pdef.javaClass.isArray) - _val.toTypedArray() - else _val + fun convert(cval: Any?, cpdef: Any?): Any? { + return if (cpdef is Number) //If we expect a number + if (cval is Number) + ChromaUtils.convertNumber(cval, cpdef.javaClass) + else cpdef //If we didn't get a number, return default (which is a number) + else if (cval is List<*> && cpdef != null && cpdef.javaClass.isArray) + cval.toTypedArray() + else cval } return getter.apply(convert(`val`, pdef)).also { value = it } } @@ -113,16 +114,19 @@ class ConfigData internal constructor( fun signalChange(config: IHaveConfig) { val cc = config.config val sa = config.saveAction + val root = cc.root + if (root == null) { + MainPlugin.Instance.logger.warning("Attempted to save config with no root! Name: ${config.config.name}") + return + } if (!saveTasks.containsKey(cc.root)) { synchronized(saveTasks) { saveTasks.put( - cc.root, + root, SaveTask(Bukkit.getScheduler().runTaskLaterAsynchronously(MainPlugin.Instance, { - synchronized( - saveTasks - ) { - saveTasks.remove(cc.getRoot()) - sa!!.run() + synchronized(saveTasks) { + saveTasks.remove(root) + sa.run() } }, 100), sa) ) @@ -144,8 +148,8 @@ class ConfigData internal constructor( return false } - fun builder(config: IHaveConfig, path: String): ConfigDataBuilder { - return ConfigDataBuilder(config, path) + fun builder(config: IHaveConfig, path: String, primitiveDef: Any?, getter: Function, setter: Function): ConfigDataBuilder { + return ConfigDataBuilder(config, path, primitiveDef, getter, setter) } } } \ No newline at end of file diff --git a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/IHaveConfig.kt b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/IHaveConfig.kt index eb0370f..be9d78f 100644 --- a/Chroma-Core/src/main/java/buttondevteam/lib/architecture/IHaveConfig.kt +++ b/Chroma-Core/src/main/java/buttondevteam/lib/architecture/IHaveConfig.kt @@ -43,13 +43,14 @@ class IHaveConfig( * @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 */ - fun getConfig( + @Suppress("UNCHECKED_CAST") + fun getConfig( // TODO: Remove path: String, def: T, getter: Function? = null, setter: Function? = null ): ConfigDataBuilder { - return ConfigData.builder(this, path) + return ConfigData.builder(this, path, if (setter != null) setter.apply(def) else def, getter ?: Function { it as T }, setter ?: Function { it }) } fun onConfigBuild(config: IConfigData<*>) { @@ -77,7 +78,7 @@ class IHaveConfig( setter: Function? = null, readOnly: Boolean = false ): ConfigData { - return getData(path, getter ?: Function { it as T }, setter ?: Function { it }, def) + return getData(path, getter ?: Function { it as T }, setter ?: Function { it }, def, readOnly) } /** @@ -112,7 +113,7 @@ class IHaveConfig( * @param The type of this variable (only use primitives or String) * @return The data object that can be used to get or set the value */ - fun getData(path: String, def: Supplier): ConfigData { + fun getData(path: String, def: Supplier): ConfigData { // TODO: Remove var data = datamap[path] if (data == null) { val defval = def.get()