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.lib.ChromaUtils
|
||||
import buttondevteam.lib.architecture.config.IConfigData
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.configuration.Configuration
|
||||
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 setter The result should be a primitive type or string that can be retrieved correctly later
|
||||
*/
|
||||
open class ConfigData<T> internal constructor(
|
||||
private val config: IHaveConfig?,
|
||||
val path: String,
|
||||
def: T?,
|
||||
class ConfigData<T> internal constructor(
|
||||
val config: IHaveConfig?,
|
||||
override val path: String,
|
||||
primitiveDef: Any?,
|
||||
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?
|
||||
|
||||
/**
|
||||
|
@ -30,7 +31,7 @@ open class ConfigData<T> internal constructor(
|
|||
private var value: T? = null
|
||||
|
||||
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.")
|
||||
get() //Generate config automatically
|
||||
}
|
||||
|
@ -39,11 +40,11 @@ open class ConfigData<T> internal constructor(
|
|||
return "ConfigData{path='$path', value=$value}"
|
||||
}
|
||||
|
||||
fun reset() {
|
||||
override fun reset() {
|
||||
value = null
|
||||
}
|
||||
|
||||
fun get(): T? {
|
||||
override fun get(): T? {
|
||||
if (value != null) return value //Speed things up
|
||||
val config = config?.config
|
||||
var `val`: Any?
|
||||
|
@ -65,8 +66,8 @@ open class ConfigData<T> internal constructor(
|
|||
return getter.apply(convert(`val`, pdef)).also { value = it }
|
||||
}
|
||||
|
||||
fun set(value: T?) {
|
||||
if (this is ReadOnlyConfigData<*>) return //Safety for Discord channel/role data
|
||||
override fun set(value: T?) {
|
||||
if (readOnly) return //Safety for Discord channel/role data
|
||||
val `val` = value?.let { setter.apply(value) }
|
||||
setInternal(`val`)
|
||||
this.value = value
|
||||
|
@ -80,88 +81,30 @@ open class ConfigData<T> internal constructor(
|
|||
|
||||
private class SaveTask(val task: BukkitTask, val saveAction: Runnable)
|
||||
|
||||
class ConfigDataBuilder<T> internal constructor(private val config: IHaveConfig, private val path: String) {
|
||||
private var def: T? = null
|
||||
private var primitiveDef: Any? = null
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private var getter: Function<Any?, T> = Function { it as T }
|
||||
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
|
||||
}
|
||||
|
||||
class ConfigDataBuilder<T> internal constructor(
|
||||
private val config: IHaveConfig,
|
||||
private val path: String,
|
||||
private val primitiveDef: Any?,
|
||||
private val getter: Function<Any?, T>,
|
||||
private val setter: Function<T, Any?>
|
||||
) {
|
||||
/**
|
||||
* Builds a modifiable config representation. Use if you want to change the value *in code*.
|
||||
*
|
||||
* @return A ConfigData instance.
|
||||
*/
|
||||
fun build(): ConfigData<T> {
|
||||
val config = ConfigData(config, path, def, primitiveDef, getter, setter)
|
||||
fun build(readOnly: Boolean = false): ConfigData<T> {
|
||||
val config = ConfigData(config, path, primitiveDef, getter, setter, readOnly)
|
||||
this.config.onConfigBuild(config)
|
||||
return config
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a read-only config representation. Use if you only want the value to be changed *in the config*.
|
||||
*
|
||||
* @return A ReadOnlyConfigData instance.
|
||||
*/
|
||||
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)"
|
||||
fun buildList(readOnly: Boolean = false): ListConfigData<T> {
|
||||
if (primitiveDef is List<*>) {
|
||||
val config = ListConfigData(config, path, primitiveDef, getter, setter, readOnly)
|
||||
this.config.onConfigBuild(config)
|
||||
return config
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ package buttondevteam.lib.architecture
|
|||
import buttondevteam.core.MainPlugin
|
||||
import buttondevteam.lib.TBMCCoreAPI
|
||||
import buttondevteam.lib.architecture.ConfigData.ConfigDataBuilder
|
||||
import buttondevteam.lib.architecture.config.IConfigData
|
||||
import org.bukkit.Bukkit
|
||||
import org.bukkit.configuration.ConfigurationSection
|
||||
import org.bukkit.plugin.java.JavaPlugin
|
||||
|
@ -16,90 +17,72 @@ import java.util.stream.Collectors
|
|||
/**
|
||||
* A config system
|
||||
* 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
|
||||
private val datamap = HashMap<String, ConfigData<*>>()
|
||||
|
||||
class IHaveConfig(
|
||||
/**
|
||||
* The way the underlying configuration gets saved to disk
|
||||
*/
|
||||
val saveAction: Runnable,
|
||||
/**
|
||||
* 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 <T> The runtime type of the config value
|
||||
* @return A ConfigData builder to set how to obtain the value
|
||||
</T> */
|
||||
fun <T> getConfig(path: String?): ConfigDataBuilder<T> {
|
||||
* @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 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)
|
||||
}
|
||||
|
||||
fun onConfigBuild(config: ConfigData<*>) {
|
||||
fun onConfigBuild(config: IConfigData<*>) {
|
||||
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 def The value to use by default
|
||||
* @param <T> The type of this variable (only use primitives or String)
|
||||
* @return The data object that can be used to get or set the value
|
||||
</T> */
|
||||
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 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 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
|
||||
</T> */
|
||||
fun <T> getData(path: String, def: T, getter: Function<Any?, T>?, setter: Function<T, Any?>): ConfigData<T> {
|
||||
var data = datamap[path]
|
||||
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(
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T> getData(
|
||||
path: String,
|
||||
primitiveDef: Any?,
|
||||
getter: Function<Any?, T>,
|
||||
setter: Function<T, Any?>?
|
||||
def: T,
|
||||
getter: Function<Any?, T>? = null,
|
||||
setter: Function<T, Any?>? = null,
|
||||
readOnly: Boolean = false
|
||||
): ConfigData<T> {
|
||||
var data = datamap[path]
|
||||
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>
|
||||
return getData(path, getter ?: Function { it as T }, setter ?: Function { it }, def)
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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)
|
||||
* @return The data object that can be used to get or set the value
|
||||
</T> */
|
||||
fun <T> getReadOnlyDataPrimDef(
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun <T> getData(
|
||||
path: String,
|
||||
primitiveDef: Any?,
|
||||
getter: Function<Any?, T>,
|
||||
setter: Function<T, Any?>?
|
||||
): ReadOnlyConfigData<T> {
|
||||
var data = datamap[path]
|
||||
if (data == null) datamap[path] =
|
||||
ReadOnlyConfigData(this, path, getter.apply(primitiveDef), primitiveDef, getter, setter).also { data = it }
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return data as ReadOnlyConfigData<T>
|
||||
setter: Function<T, Any?>,
|
||||
primitiveDef: Any?,
|
||||
readOnly: Boolean = false
|
||||
): ConfigData<T> {
|
||||
val data =
|
||||
datamap[path] ?: ConfigData(this, path, primitiveDef, getter, setter, readOnly).also { datamap[path] = it }
|
||||
return data as ConfigData<T>
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -139,31 +122,6 @@ class IHaveConfig(var saveAction: Runnable?) { // TODO: Make non-nullable after
|
|||
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.
|
||||
*
|
||||
|
|
|
@ -1,124 +1,172 @@
|
|||
package buttondevteam.lib.architecture;
|
||||
package buttondevteam.lib.architecture
|
||||
|
||||
import lombok.val;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import buttondevteam.lib.architecture.config.IConfigData
|
||||
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;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.UnaryOperator;
|
||||
class ListConfigData<T> internal constructor(
|
||||
config: IHaveConfig?,
|
||||
path: String,
|
||||
primitiveDef: kotlin.collections.List<*>,
|
||||
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>> {
|
||||
@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
|
||||
}
|
||||
override val path: String get() = listConfig.path
|
||||
|
||||
public static class List<T> extends ArrayList<T> {
|
||||
private ListConfigData<T> listConfig;
|
||||
override fun reset() {
|
||||
listConfig.reset()
|
||||
}
|
||||
|
||||
public List(@NotNull Collection<? extends T> c) {
|
||||
super(c);
|
||||
}
|
||||
override fun get(): List? {
|
||||
return listConfig.get()
|
||||
}
|
||||
|
||||
public List() {
|
||||
}
|
||||
override fun set(value: List?) {
|
||||
listConfig.set(value)
|
||||
}
|
||||
|
||||
private void update() {
|
||||
listConfig.set(this); //Update the config model and start save task if needed
|
||||
}
|
||||
inner class List(backingList: MutableList<Any?>) : MutableList<T> {
|
||||
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
|
||||
public T set(int index, T element) {
|
||||
T ret = super.set(index, element);
|
||||
update();
|
||||
return ret;
|
||||
}
|
||||
override fun set(index: Int, element: T): T {
|
||||
val ret = primitiveList.set(index, elementSetter.apply(element))
|
||||
update()
|
||||
return elementGetter.apply(ret)
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T t) {
|
||||
val ret = super.add(t);
|
||||
update();
|
||||
return ret;
|
||||
}
|
||||
override fun add(element: T): Boolean {
|
||||
val ret = primitiveList.add(elementSetter.apply(element))
|
||||
update()
|
||||
return ret
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int index, T element) {
|
||||
super.add(index, element);
|
||||
update();
|
||||
}
|
||||
override fun add(index: Int, element: T) {
|
||||
primitiveList.add(index, elementSetter.apply(element))
|
||||
update()
|
||||
}
|
||||
|
||||
@Override
|
||||
public T remove(int index) {
|
||||
T ret = super.remove(index);
|
||||
update();
|
||||
return ret;
|
||||
}
|
||||
override fun removeAt(index: Int): T {
|
||||
val ret = primitiveList.removeAt(index)
|
||||
update()
|
||||
return elementGetter.apply(ret)
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
val ret = super.remove(o);
|
||||
update();
|
||||
return ret;
|
||||
}
|
||||
override fun subList(fromIndex: Int, toIndex: Int): MutableList<T> =
|
||||
List(primitiveList.subList(fromIndex, toIndex))
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends T> c) {
|
||||
val ret = super.addAll(c);
|
||||
update();
|
||||
return ret;
|
||||
}
|
||||
override fun remove(element: T): Boolean {
|
||||
val ret = primitiveList.remove(elementSetter.apply(element))
|
||||
update()
|
||||
return ret
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends T> c) {
|
||||
val ret = super.addAll(index, c);
|
||||
update();
|
||||
return ret;
|
||||
}
|
||||
override fun addAll(elements: Collection<T>): Boolean {
|
||||
val ret = primitiveList.addAll(elements.map { elementSetter.apply(it) })
|
||||
update()
|
||||
return ret
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeRange(int fromIndex, int toIndex) {
|
||||
super.removeRange(fromIndex, toIndex);
|
||||
update();
|
||||
}
|
||||
override fun addAll(index: Int, elements: Collection<T>): Boolean {
|
||||
val ret = primitiveList.addAll(index, elements.map { elementSetter.apply(it) })
|
||||
update()
|
||||
return ret
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(Collection<?> c) {
|
||||
val ret = super.removeAll(c);
|
||||
update();
|
||||
return ret;
|
||||
}
|
||||
override fun removeAll(elements: Collection<T>): Boolean {
|
||||
val ret = primitiveList.removeAll(elements.map { elementSetter.apply(it) })
|
||||
update()
|
||||
return ret
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(Collection<?> c) {
|
||||
val ret = super.retainAll(c);
|
||||
update();
|
||||
return ret;
|
||||
}
|
||||
override fun retainAll(elements: Collection<T>): Boolean {
|
||||
val ret = primitiveList.retainAll(elements.map { elementSetter.apply(it) })
|
||||
update()
|
||||
return ret
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeIf(Predicate<? super T> filter) {
|
||||
val ret = super.removeIf(filter);
|
||||
update();
|
||||
return ret;
|
||||
}
|
||||
override fun removeIf(filter: Predicate<in T>): Boolean {
|
||||
val ret = primitiveList.removeIf { filter.test(elementGetter.apply(it)) }
|
||||
update()
|
||||
return ret
|
||||
}
|
||||
|
||||
@Override
|
||||
public void replaceAll(UnaryOperator<T> operator) {
|
||||
super.replaceAll(operator);
|
||||
update();
|
||||
}
|
||||
override fun replaceAll(operator: UnaryOperator<T>) {
|
||||
primitiveList.replaceAll { elementSetter.apply(operator.apply(elementGetter.apply(it))) }
|
||||
update()
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sort(Comparator<? super T> c) {
|
||||
super.sort(c);
|
||||
update();
|
||||
}
|
||||
}
|
||||
override fun sort(c: Comparator<in T>) {
|
||||
primitiveList.sortWith { o1, o2 -> c.compare(elementGetter.apply(o1), elementGetter.apply(o2)) }
|
||||
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