Improved config handling, updated read-only and list configs
- The read-only configs are no longer using a separate class, it seems unnecessary - The list configs got refactored so that the entire list doesn't get recreated each time it changes - Also added support for getters/setters for the list config, just to be consistent
This commit is contained in:
parent
99958e74f9
commit
8d8708d14b
5 changed files with 240 additions and 294 deletions
|
@ -2,6 +2,7 @@ package buttondevteam.lib.architecture
|
||||||
|
|
||||||
import buttondevteam.core.MainPlugin
|
import buttondevteam.core.MainPlugin
|
||||||
import buttondevteam.lib.ChromaUtils
|
import buttondevteam.lib.ChromaUtils
|
||||||
|
import buttondevteam.lib.architecture.config.IConfigData
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.configuration.Configuration
|
import org.bukkit.configuration.Configuration
|
||||||
import org.bukkit.scheduler.BukkitTask
|
import org.bukkit.scheduler.BukkitTask
|
||||||
|
@ -14,14 +15,14 @@ import java.util.function.Function
|
||||||
* @param getter The parameter is of a primitive type as returned by [Configuration.get]
|
* @param getter The parameter is of a primitive type as returned by [Configuration.get]
|
||||||
* @param setter The result should be a primitive type or string that can be retrieved correctly later
|
* @param setter The result should be a primitive type or string that can be retrieved correctly later
|
||||||
*/
|
*/
|
||||||
open class ConfigData<T> internal constructor(
|
class ConfigData<T> internal constructor(
|
||||||
private val config: IHaveConfig?,
|
val config: IHaveConfig?,
|
||||||
val path: String,
|
override val path: String,
|
||||||
def: T?,
|
|
||||||
primitiveDef: Any?,
|
primitiveDef: Any?,
|
||||||
private val getter: Function<Any?, T>,
|
private val getter: Function<Any?, T>,
|
||||||
private val setter: Function<T, Any?>
|
private val setter: Function<T, Any?>,
|
||||||
) {
|
private val readOnly: Boolean
|
||||||
|
) : IConfigData<T> {
|
||||||
private val pdef: Any?
|
private val pdef: Any?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -30,7 +31,7 @@ open class ConfigData<T> internal constructor(
|
||||||
private var value: T? = null
|
private var value: T? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
this.pdef = primitiveDef ?: def?.let { setter.apply(it) }
|
this.pdef = primitiveDef
|
||||||
?: throw IllegalArgumentException("Either def or primitiveDef must be set. A getter and setter must be present when using primitiveDef.")
|
?: throw IllegalArgumentException("Either def or primitiveDef must be set. A getter and setter must be present when using primitiveDef.")
|
||||||
get() //Generate config automatically
|
get() //Generate config automatically
|
||||||
}
|
}
|
||||||
|
@ -39,11 +40,11 @@ open class ConfigData<T> internal constructor(
|
||||||
return "ConfigData{path='$path', value=$value}"
|
return "ConfigData{path='$path', value=$value}"
|
||||||
}
|
}
|
||||||
|
|
||||||
fun reset() {
|
override fun reset() {
|
||||||
value = null
|
value = null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun get(): T? {
|
override fun get(): T? {
|
||||||
if (value != null) return value //Speed things up
|
if (value != null) return value //Speed things up
|
||||||
val config = config?.config
|
val config = config?.config
|
||||||
var `val`: Any?
|
var `val`: Any?
|
||||||
|
@ -65,8 +66,8 @@ open class ConfigData<T> internal constructor(
|
||||||
return getter.apply(convert(`val`, pdef)).also { value = it }
|
return getter.apply(convert(`val`, pdef)).also { value = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun set(value: T?) {
|
override fun set(value: T?) {
|
||||||
if (this is ReadOnlyConfigData<*>) return //Safety for Discord channel/role data
|
if (readOnly) return //Safety for Discord channel/role data
|
||||||
val `val` = value?.let { setter.apply(value) }
|
val `val` = value?.let { setter.apply(value) }
|
||||||
setInternal(`val`)
|
setInternal(`val`)
|
||||||
this.value = value
|
this.value = value
|
||||||
|
@ -80,88 +81,30 @@ open class ConfigData<T> internal constructor(
|
||||||
|
|
||||||
private class SaveTask(val task: BukkitTask, val saveAction: Runnable)
|
private class SaveTask(val task: BukkitTask, val saveAction: Runnable)
|
||||||
|
|
||||||
class ConfigDataBuilder<T> internal constructor(private val config: IHaveConfig, private val path: String) {
|
class ConfigDataBuilder<T> internal constructor(
|
||||||
private var def: T? = null
|
private val config: IHaveConfig,
|
||||||
private var primitiveDef: Any? = null
|
private val path: String,
|
||||||
|
private val primitiveDef: Any?,
|
||||||
@Suppress("UNCHECKED_CAST")
|
private val getter: Function<Any?, T>,
|
||||||
private var getter: Function<Any?, T> = Function { it as T }
|
private val setter: Function<T, Any?>
|
||||||
private var setter: Function<T, Any?> = Function { it }
|
) {
|
||||||
|
|
||||||
/**
|
|
||||||
* The default value to use, as used in code. If not a primitive type, use the [.getter] and [.setter] methods.
|
|
||||||
* <br></br>
|
|
||||||
* To set the value as it is stored, use [.primitiveDef].
|
|
||||||
*
|
|
||||||
* @param def The default value
|
|
||||||
* @return This builder
|
|
||||||
*/
|
|
||||||
fun def(def: T): ConfigDataBuilder<T> {
|
|
||||||
this.def = def
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default value to use, as stored in yaml. Must be a primitive type. Make sure to use the [.getter] and [.setter] methods.
|
|
||||||
* <br></br>
|
|
||||||
* To set the value as used in the code, use [.def].
|
|
||||||
*
|
|
||||||
* @param primitiveDef The default value
|
|
||||||
* @return This builder
|
|
||||||
*/
|
|
||||||
fun primitiveDef(primitiveDef: Any?): ConfigDataBuilder<T> {
|
|
||||||
this.primitiveDef = primitiveDef
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A function to use to obtain the runtime object from the yaml representation (usually string).
|
|
||||||
* The [.setter] must also be set.
|
|
||||||
*
|
|
||||||
* @param getter A function that receives the primitive type and returns the runtime type
|
|
||||||
* @return This builder
|
|
||||||
*/
|
|
||||||
fun getter(getter: Function<Any?, T>): ConfigDataBuilder<T> {
|
|
||||||
this.getter = getter
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A function to use to obtain the yaml representation (usually string) from the runtime object.
|
|
||||||
* The [.getter] must also be set.
|
|
||||||
*
|
|
||||||
* @param setter A function that receives the runtime type and returns the primitive type
|
|
||||||
* @return This builder
|
|
||||||
*/
|
|
||||||
fun setter(setter: Function<T, Any?>): ConfigDataBuilder<T> {
|
|
||||||
this.setter = setter
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds a modifiable config representation. Use if you want to change the value *in code*.
|
* Builds a modifiable config representation. Use if you want to change the value *in code*.
|
||||||
*
|
*
|
||||||
* @return A ConfigData instance.
|
* @return A ConfigData instance.
|
||||||
*/
|
*/
|
||||||
fun build(): ConfigData<T> {
|
fun build(readOnly: Boolean = false): ConfigData<T> {
|
||||||
val config = ConfigData(config, path, def, primitiveDef, getter, setter)
|
val config = ConfigData(config, path, primitiveDef, getter, setter, readOnly)
|
||||||
this.config.onConfigBuild(config)
|
this.config.onConfigBuild(config)
|
||||||
return config
|
return config
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
fun buildList(readOnly: Boolean = false): ListConfigData<T> {
|
||||||
* Builds a read-only config representation. Use if you only want the value to be changed *in the config*.
|
if (primitiveDef is List<*>) {
|
||||||
*
|
val config = ListConfigData(config, path, primitiveDef, getter, setter, readOnly)
|
||||||
* @return A ReadOnlyConfigData instance.
|
this.config.onConfigBuild(config)
|
||||||
*/
|
return config
|
||||||
fun buildReadOnly(): ReadOnlyConfigData<T> {
|
}
|
||||||
val config = ReadOnlyConfigData(config, path, def, primitiveDef, getter, setter)
|
|
||||||
this.config.onConfigBuild(config)
|
|
||||||
return config
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return "ConfigData.ConfigDataBuilder(config=$config, path=$path, def=$def, primitiveDef=$primitiveDef, getter=$getter, setter=$setter)"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ package buttondevteam.lib.architecture
|
||||||
import buttondevteam.core.MainPlugin
|
import buttondevteam.core.MainPlugin
|
||||||
import buttondevteam.lib.TBMCCoreAPI
|
import buttondevteam.lib.TBMCCoreAPI
|
||||||
import buttondevteam.lib.architecture.ConfigData.ConfigDataBuilder
|
import buttondevteam.lib.architecture.ConfigData.ConfigDataBuilder
|
||||||
|
import buttondevteam.lib.architecture.config.IConfigData
|
||||||
import org.bukkit.Bukkit
|
import org.bukkit.Bukkit
|
||||||
import org.bukkit.configuration.ConfigurationSection
|
import org.bukkit.configuration.ConfigurationSection
|
||||||
import org.bukkit.plugin.java.JavaPlugin
|
import org.bukkit.plugin.java.JavaPlugin
|
||||||
|
@ -16,90 +17,72 @@ import java.util.stream.Collectors
|
||||||
/**
|
/**
|
||||||
* A config system
|
* A config system
|
||||||
* May be used in testing.
|
* May be used in testing.
|
||||||
*
|
|
||||||
* @param saveAction What to do to save the config to disk. Don't use get methods until it's non-null.
|
|
||||||
*/
|
*/
|
||||||
class IHaveConfig(var saveAction: Runnable?) { // TODO: Make non-nullable after adding component builder
|
class IHaveConfig(
|
||||||
private val datamap = HashMap<String, ConfigData<*>>()
|
/**
|
||||||
|
* The way the underlying configuration gets saved to disk
|
||||||
|
*/
|
||||||
|
val saveAction: Runnable,
|
||||||
/**
|
/**
|
||||||
* Returns the Bukkit ConfigurationSection. Use [.signalChange] after changing it.
|
* Returns the Bukkit ConfigurationSection. Use [.signalChange] after changing it.
|
||||||
*/
|
*/
|
||||||
var config: ConfigurationSection? = null // TODO: Make non-nullable after removing reset() method
|
val config: ConfigurationSection
|
||||||
|
) {
|
||||||
|
private val datamap = HashMap<String, IConfigData<*>>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a config object for the given path. The def or primitiveDef must be set. If a getter is present, a setter must be present as well.
|
* You may use this method with any data type, but always provide getters and setters that convert to primitive types
|
||||||
|
* if you're not using primitive types directly.
|
||||||
|
* These primitive types are strings, numbers, characters, booleans and lists of these things.
|
||||||
*
|
*
|
||||||
* @param path The dot-separated path relative to this config instance
|
* @param path The path in config to use
|
||||||
* @param <T> The runtime type of the config value
|
* @param def The value to use by default
|
||||||
* @return A ConfigData builder to set how to obtain the value
|
* @param getter A function that converts a primitive representation to the correct value
|
||||||
</T> */
|
* @param setter A function that converts a value to a primitive representation
|
||||||
fun <T> getConfig(path: String?): ConfigDataBuilder<T> {
|
* @param primDef Whether the default value is a primitive value that needs to be converted to the correct type using the getter
|
||||||
|
* @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 <T> getConfig(
|
||||||
|
path: String,
|
||||||
|
def: T,
|
||||||
|
getter: Function<Any?, T>? = null,
|
||||||
|
setter: Function<T, Any?>? = null
|
||||||
|
): ConfigDataBuilder<T> {
|
||||||
return ConfigData.builder(this, path)
|
return ConfigData.builder(this, path)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun onConfigBuild(config: ConfigData<*>) {
|
fun onConfigBuild(config: IConfigData<*>) {
|
||||||
datamap[config.path] = config
|
datamap[config.path] = config
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method overload should only be used with primitives or String.
|
* You may use this method with any data type, but always provide getters and setters that convert to primitive types
|
||||||
|
* if you're not using primitive types directly.
|
||||||
|
* These primitive types are strings, numbers, characters, booleans and lists of these things.
|
||||||
*
|
*
|
||||||
* @param path The path in config to use
|
* @param path The path in config to use
|
||||||
* @param def The value to use by default
|
* @param def The value to use by default
|
||||||
* @param <T> The type of this variable (only use primitives or String)
|
* @param getter A function that converts a primitive representation to the correct value
|
||||||
* @return The data object that can be used to get or set the value
|
* @param setter A function that converts a value to a primitive representation
|
||||||
</T> */
|
* @param primDef Whether the default value is a primitive value that needs to be converted to the correct type using the getter
|
||||||
fun <T> getData(path: String, def: T): ConfigData<T> {
|
|
||||||
var data = datamap[path]
|
|
||||||
if (data == null) datamap[path] = ConfigData(this, path, def, def, null, null).also { data = it }
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
return data as ConfigData<T>
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* This method overload may be used with any class.
|
|
||||||
*
|
|
||||||
* @param path The path in config to use
|
|
||||||
* @param def The 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 <T> The type of this variable (can be any class)
|
||||||
* @return The data object that can be used to get or set the value
|
* @return The data object that can be used to get or set the value
|
||||||
</T> */
|
</T> */
|
||||||
fun <T> getData(path: String, def: T, getter: Function<Any?, T>?, setter: Function<T, Any?>): ConfigData<T> {
|
@Suppress("UNCHECKED_CAST")
|
||||||
var data = datamap[path]
|
fun <T> getData(
|
||||||
if (data == null) datamap[path] =
|
|
||||||
ConfigData(this, path, def, setter.apply(def), getter, setter).also { data = it }
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
return data as ConfigData<T>
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 **primitive** 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
|
|
||||||
</T> */
|
|
||||||
fun <T> getDataPrimDef(
|
|
||||||
path: String,
|
path: String,
|
||||||
primitiveDef: Any?,
|
def: T,
|
||||||
getter: Function<Any?, T>,
|
getter: Function<Any?, T>? = null,
|
||||||
setter: Function<T, Any?>?
|
setter: Function<T, Any?>? = null,
|
||||||
|
readOnly: Boolean = false
|
||||||
): ConfigData<T> {
|
): ConfigData<T> {
|
||||||
var data = datamap[path]
|
return getData(path, getter ?: Function { it as T }, setter ?: Function { it }, def)
|
||||||
if (data == null) datamap[path] =
|
|
||||||
ConfigData(this, path, getter.apply(primitiveDef), primitiveDef, getter, setter).also { data = it }
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
return data as ConfigData<T>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method overload may be used with any class. The given default value will be run through the getter.
|
* You may use this method with any data type and provide a primitive default value.
|
||||||
|
* These primitive types are strings, numbers, characters, booleans and lists of these things.
|
||||||
*
|
*
|
||||||
* @param path The path in config to use
|
* @param path The path in config to use
|
||||||
* @param primitiveDef The **primitive** value to use by default
|
* @param primitiveDef The **primitive** value to use by default
|
||||||
|
@ -108,17 +91,17 @@ class IHaveConfig(var saveAction: Runnable?) { // TODO: Make non-nullable after
|
||||||
* @param <T> The type of this variable (can be any class)
|
* @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
|
* @return The data object that can be used to get or set the value
|
||||||
</T> */
|
</T> */
|
||||||
fun <T> getReadOnlyDataPrimDef(
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
fun <T> getData(
|
||||||
path: String,
|
path: String,
|
||||||
primitiveDef: Any?,
|
|
||||||
getter: Function<Any?, T>,
|
getter: Function<Any?, T>,
|
||||||
setter: Function<T, Any?>?
|
setter: Function<T, Any?>,
|
||||||
): ReadOnlyConfigData<T> {
|
primitiveDef: Any?,
|
||||||
var data = datamap[path]
|
readOnly: Boolean = false
|
||||||
if (data == null) datamap[path] =
|
): ConfigData<T> {
|
||||||
ReadOnlyConfigData(this, path, getter.apply(primitiveDef), primitiveDef, getter, setter).also { data = it }
|
val data =
|
||||||
@Suppress("UNCHECKED_CAST")
|
datamap[path] ?: ConfigData(this, path, primitiveDef, getter, setter, readOnly).also { datamap[path] = it }
|
||||||
return data as ReadOnlyConfigData<T>
|
return data as ConfigData<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -139,31 +122,6 @@ class IHaveConfig(var saveAction: Runnable?) { // TODO: Make non-nullable after
|
||||||
return data as ConfigData<T>
|
return data as ConfigData<T>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* This method overload may be used with any class.
|
|
||||||
*
|
|
||||||
* @param path The path in config to use
|
|
||||||
* @param def The 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
|
|
||||||
</T> */
|
|
||||||
fun <T> getData(
|
|
||||||
path: String,
|
|
||||||
def: Supplier<T>,
|
|
||||||
getter: Function<Any?, T>?,
|
|
||||||
setter: Function<T, Any?>
|
|
||||||
): ConfigData<T> {
|
|
||||||
var data = datamap[path]
|
|
||||||
if (data == null) {
|
|
||||||
val defval = def.get()
|
|
||||||
datamap[path] = ConfigData(this, path, defval, setter.apply(defval), getter, setter).also { data = it }
|
|
||||||
}
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
return data as ConfigData<T>
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method overload should only be used with primitves or String.
|
* This method overload should only be used with primitves or String.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,124 +1,172 @@
|
||||||
package buttondevteam.lib.architecture;
|
package buttondevteam.lib.architecture
|
||||||
|
|
||||||
import lombok.val;
|
import buttondevteam.lib.architecture.config.IConfigData
|
||||||
import org.jetbrains.annotations.NotNull;
|
import java.util.function.Function
|
||||||
|
import java.util.function.Predicate
|
||||||
|
import java.util.function.UnaryOperator
|
||||||
|
import kotlin.collections.List as KList
|
||||||
|
|
||||||
import java.util.ArrayList;
|
class ListConfigData<T> internal constructor(
|
||||||
import java.util.Collection;
|
config: IHaveConfig?,
|
||||||
import java.util.Comparator;
|
path: String,
|
||||||
import java.util.function.Predicate;
|
primitiveDef: kotlin.collections.List<*>,
|
||||||
import java.util.function.UnaryOperator;
|
private val elementGetter: Function<Any?, T>,
|
||||||
|
private val elementSetter: Function<T, Any?>,
|
||||||
|
readOnly: Boolean
|
||||||
|
) : IConfigData<ListConfigData<T>.List> {
|
||||||
|
val listConfig: ConfigData<List> =
|
||||||
|
ConfigData(config, path, primitiveDef, { List((it as KList<*>).toMutableList()) }, { it }, readOnly)
|
||||||
|
|
||||||
public class ListConfigData<T> extends ConfigData<ListConfigData.List<T>> {
|
override val path: String get() = listConfig.path
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
ListConfigData(IHaveConfig config, String path, List<T> def) {
|
|
||||||
super(config, path, def, new ArrayList<>(def), list -> {
|
|
||||||
var l = new List<>((ArrayList<T>) list);
|
|
||||||
l.listConfig = def.listConfig;
|
|
||||||
return l;
|
|
||||||
}, ArrayList::new);
|
|
||||||
def.listConfig = this; //Can't make the List class non-static or pass this in the super() constructor
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class List<T> extends ArrayList<T> {
|
override fun reset() {
|
||||||
private ListConfigData<T> listConfig;
|
listConfig.reset()
|
||||||
|
}
|
||||||
|
|
||||||
public List(@NotNull Collection<? extends T> c) {
|
override fun get(): List? {
|
||||||
super(c);
|
return listConfig.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
public List() {
|
override fun set(value: List?) {
|
||||||
}
|
listConfig.set(value)
|
||||||
|
}
|
||||||
|
|
||||||
private void update() {
|
inner class List(backingList: MutableList<Any?>) : MutableList<T> {
|
||||||
listConfig.set(this); //Update the config model and start save task if needed
|
private val primitiveList = backingList
|
||||||
}
|
override val size: Int get() = primitiveList.size
|
||||||
|
private fun update() {
|
||||||
|
val config = listConfig.config
|
||||||
|
if (config != null) {
|
||||||
|
ConfigData.signalChange(config) //Update the config model and start save task if needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
override fun set(index: Int, element: T): T {
|
||||||
public T set(int index, T element) {
|
val ret = primitiveList.set(index, elementSetter.apply(element))
|
||||||
T ret = super.set(index, element);
|
update()
|
||||||
update();
|
return elementGetter.apply(ret)
|
||||||
return ret;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
override fun add(element: T): Boolean {
|
||||||
public boolean add(T t) {
|
val ret = primitiveList.add(elementSetter.apply(element))
|
||||||
val ret = super.add(t);
|
update()
|
||||||
update();
|
return ret
|
||||||
return ret;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
override fun add(index: Int, element: T) {
|
||||||
public void add(int index, T element) {
|
primitiveList.add(index, elementSetter.apply(element))
|
||||||
super.add(index, element);
|
update()
|
||||||
update();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
override fun removeAt(index: Int): T {
|
||||||
public T remove(int index) {
|
val ret = primitiveList.removeAt(index)
|
||||||
T ret = super.remove(index);
|
update()
|
||||||
update();
|
return elementGetter.apply(ret)
|
||||||
return ret;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
override fun subList(fromIndex: Int, toIndex: Int): MutableList<T> =
|
||||||
public boolean remove(Object o) {
|
List(primitiveList.subList(fromIndex, toIndex))
|
||||||
val ret = super.remove(o);
|
|
||||||
update();
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
override fun remove(element: T): Boolean {
|
||||||
public boolean addAll(Collection<? extends T> c) {
|
val ret = primitiveList.remove(elementSetter.apply(element))
|
||||||
val ret = super.addAll(c);
|
update()
|
||||||
update();
|
return ret
|
||||||
return ret;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
override fun addAll(elements: Collection<T>): Boolean {
|
||||||
public boolean addAll(int index, Collection<? extends T> c) {
|
val ret = primitiveList.addAll(elements.map { elementSetter.apply(it) })
|
||||||
val ret = super.addAll(index, c);
|
update()
|
||||||
update();
|
return ret
|
||||||
return ret;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
override fun addAll(index: Int, elements: Collection<T>): Boolean {
|
||||||
protected void removeRange(int fromIndex, int toIndex) {
|
val ret = primitiveList.addAll(index, elements.map { elementSetter.apply(it) })
|
||||||
super.removeRange(fromIndex, toIndex);
|
update()
|
||||||
update();
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
override fun removeAll(elements: Collection<T>): Boolean {
|
||||||
public boolean removeAll(Collection<?> c) {
|
val ret = primitiveList.removeAll(elements.map { elementSetter.apply(it) })
|
||||||
val ret = super.removeAll(c);
|
update()
|
||||||
update();
|
return ret
|
||||||
return ret;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
override fun retainAll(elements: Collection<T>): Boolean {
|
||||||
public boolean retainAll(Collection<?> c) {
|
val ret = primitiveList.retainAll(elements.map { elementSetter.apply(it) })
|
||||||
val ret = super.retainAll(c);
|
update()
|
||||||
update();
|
return ret
|
||||||
return ret;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
override fun removeIf(filter: Predicate<in T>): Boolean {
|
||||||
public boolean removeIf(Predicate<? super T> filter) {
|
val ret = primitiveList.removeIf { filter.test(elementGetter.apply(it)) }
|
||||||
val ret = super.removeIf(filter);
|
update()
|
||||||
update();
|
return ret
|
||||||
return ret;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
override fun replaceAll(operator: UnaryOperator<T>) {
|
||||||
public void replaceAll(UnaryOperator<T> operator) {
|
primitiveList.replaceAll { elementSetter.apply(operator.apply(elementGetter.apply(it))) }
|
||||||
super.replaceAll(operator);
|
update()
|
||||||
update();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
override fun sort(c: Comparator<in T>) {
|
||||||
public void sort(Comparator<? super T> c) {
|
primitiveList.sortWith { o1, o2 -> c.compare(elementGetter.apply(o1), elementGetter.apply(o2)) }
|
||||||
super.sort(c);
|
update()
|
||||||
update();
|
}
|
||||||
}
|
|
||||||
}
|
override fun clear() {
|
||||||
|
primitiveList.clear()
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun get(index: Int): T = elementGetter.apply(primitiveList[index])
|
||||||
|
override fun isEmpty(): Boolean = primitiveList.isEmpty()
|
||||||
|
|
||||||
|
override fun lastIndexOf(element: T): Int = primitiveList.lastIndexOf(elementSetter.apply(element))
|
||||||
|
override fun indexOf(element: T): Int = primitiveList.indexOf(elementSetter.apply(element))
|
||||||
|
override fun containsAll(elements: Collection<T>): Boolean =
|
||||||
|
primitiveList.containsAll(elements.map { elementSetter.apply(it) })
|
||||||
|
|
||||||
|
override fun contains(element: T): Boolean = primitiveList.contains(elementSetter.apply(element))
|
||||||
|
override fun iterator(): MutableIterator<T> {
|
||||||
|
return object : MutableIterator<T> {
|
||||||
|
private val iterator = primitiveList.iterator()
|
||||||
|
override fun hasNext(): Boolean = iterator.hasNext()
|
||||||
|
override fun next(): T = elementGetter.apply(iterator.next())
|
||||||
|
override fun remove() {
|
||||||
|
iterator.remove()
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun listIterator(): MutableListIterator<T> {
|
||||||
|
return listIterator(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun listIterator(index: Int): MutableListIterator<T> {
|
||||||
|
return object : MutableListIterator<T> {
|
||||||
|
private val iterator = primitiveList.listIterator(index)
|
||||||
|
override fun hasNext(): Boolean = iterator.hasNext()
|
||||||
|
override fun next(): T = elementGetter.apply(iterator.next())
|
||||||
|
override fun remove() {
|
||||||
|
iterator.remove()
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hasPrevious(): Boolean = iterator.hasPrevious()
|
||||||
|
override fun nextIndex(): Int = iterator.nextIndex()
|
||||||
|
override fun previous(): T = elementGetter.apply(iterator.previous())
|
||||||
|
override fun previousIndex(): Int = iterator.previousIndex()
|
||||||
|
override fun add(element: T) {
|
||||||
|
iterator.add(elementSetter.apply(element))
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun set(element: T) {
|
||||||
|
iterator.set(elementSetter.apply(element))
|
||||||
|
update()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
package buttondevteam.lib.architecture
|
|
||||||
|
|
||||||
import java.util.function.Function
|
|
||||||
|
|
||||||
class ReadOnlyConfigData<T> internal constructor(
|
|
||||||
config: IHaveConfig?,
|
|
||||||
path: String,
|
|
||||||
def: T?,
|
|
||||||
primitiveDef: Any?,
|
|
||||||
getter: Function<Any?, T>,
|
|
||||||
setter: Function<T, Any?>
|
|
||||||
) : ConfigData<T>(config, path, def, primitiveDef, getter, setter)
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
package buttondevteam.lib.architecture.config
|
||||||
|
|
||||||
|
interface IConfigData<T> {
|
||||||
|
fun reset()
|
||||||
|
fun get(): T?
|
||||||
|
fun set(value: T?)
|
||||||
|
|
||||||
|
val path: String
|
||||||
|
}
|
Loading…
Reference in a new issue