Use kotlinx.serialization for json configs

This commit is contained in:
Jakob K
2021-05-15 20:44:47 +02:00
parent 787428bf22
commit a00b4dd085

View File

@@ -2,12 +2,11 @@
package net.axay.kspigot.config package net.axay.kspigot.config
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import net.axay.kspigot.languageextensions.kotlinextensions.createIfNotExists import net.axay.kspigot.languageextensions.kotlinextensions.createIfNotExists
import net.axay.kspigot.main.ValueHolder.getGson
import java.io.File import java.io.File
import java.io.FileReader
import java.io.FileWriter
import kotlin.reflect.KClass
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
/** /**
@@ -27,24 +26,16 @@ import kotlin.reflect.KProperty
* @param default Optional default config, which will be * @param default Optional default config, which will be
* used if there is no config file and a new one should * used if there is no config file and a new one should
* be created. * be created.
* @param json The json instance to use for serialization.
* @throws java.io.FileNotFoundException If the file does not * @throws java.io.FileNotFoundException If the file does not
* exist and no default config is specified. * exist and no default config is specified.
*/ */
inline fun <reified T : Any> kSpigotJsonConfig( inline fun <reified T : Any> kSpigotJsonConfig(
file: File, file: File,
saveAfterLoad: Boolean = false, saveAfterLoad: Boolean = false,
json: Json = Json,
noinline default: (() -> T)? = null, noinline default: (() -> T)? = null,
) = ConfigDelegate(T::class, file, saveAfterLoad, default) ) = object : ConfigDelegate<T>(file, saveAfterLoad, default) {
/**
* @see kSpigotJsonConfig
*/
class ConfigDelegate<T : Any>(
private val configClass: KClass<T>,
private val file: File,
private val saveAfterLoad: Boolean,
private val defaultCallback: (() -> T)?,
) {
private var internalConfig: T = loadIt() private var internalConfig: T = loadIt()
var data: T var data: T
get() = internalConfig get() = internalConfig
@@ -52,35 +43,28 @@ class ConfigDelegate<T : Any>(
internalConfig = value internalConfig = value
} }
operator fun getValue(thisRef: Any?, property: KProperty<*>) = internalConfig override operator fun getValue(thisRef: Any?, property: KProperty<*>) = internalConfig
operator fun setValue(thisRef: Any?, property: KProperty<*>, config: T): Boolean { override operator fun setValue(thisRef: Any?, property: KProperty<*>, config: T): Boolean {
internalConfig = config internalConfig = config
return true return true
} }
/** override fun save() = saveIt(internalConfig)
* Saves the config object in its current state to disk.
*/
fun save() = saveIt(internalConfig)
/** override fun reload() {
* Loads the current state of the config on disk to the config object.
*/
fun reload() {
loadIt() loadIt()
} }
private fun saveIt(toSave: T) { override fun saveIt(toSave: T) {
GsonConfigManager.saveConfig(file, toSave, true) JsonConfigManager.saveConfig(file, toSave, json)
internalConfig = toSave internalConfig = toSave
} }
private fun loadIt(): T { override fun loadIt(): T {
val loaded = if (defaultCallback == null) val loaded = if (default == null)
GsonConfigManager.loadConfig(file, configClass) JsonConfigManager.loadConfig(file, json)
else else
GsonConfigManager.loadOrCreateDefault(file, configClass, true, defaultCallback) JsonConfigManager.loadOrCreateDefault(file, json, default)
if (saveAfterLoad) if (saveAfterLoad)
saveIt(loaded) saveIt(loaded)
@@ -89,28 +73,52 @@ class ConfigDelegate<T : Any>(
} }
} }
internal object GsonConfigManager { /**
fun <T : Any> loadConfig(file: File, configClass: KClass<T>): T = * @see kSpigotJsonConfig
FileReader(file).use { reader -> return getGson().fromJson(reader, configClass.java) } */
abstract class ConfigDelegate<T : Any>(
private val file: File,
private val saveAfterLoad: Boolean,
private val defaultCallback: (() -> T)?,
) {
abstract operator fun getValue(thisRef: Any?, property: KProperty<*>): T
abstract operator fun setValue(thisRef: Any?, property: KProperty<*>, config: T): Boolean
fun <T : Any> saveConfig(file: File, config: T, pretty: Boolean = true) { /**
* Saves the config object in its current state to disk.
*/
abstract fun save()
/**
* Loads the current state of the config on disk to the config object.
*/
abstract fun reload()
abstract fun saveIt(toSave: T)
protected abstract fun loadIt(): T
}
object JsonConfigManager {
inline fun <reified T : Any> loadConfig(file: File, json: Json = Json): T {
return Json.decodeFromString(file.readText())
}
inline fun <reified T : Any> saveConfig(file: File, config: T, json: Json = Json) {
file.createIfNotExists() file.createIfNotExists()
FileWriter(file).use { writer -> file.writeText(Json.encodeToString(config))
getGson(pretty).toJson(config, writer)
}
} }
fun <T : Any> loadOrCreateDefault( inline fun <reified T : Any> loadOrCreateDefault(
file: File, file: File,
configClass: KClass<T>, json: Json = Json,
pretty: Boolean = true,
default: () -> T, default: () -> T,
): T { ): T {
try { try {
return loadConfig(file, configClass) return loadConfig(file, json)
} catch (exc: Exception) { } catch (exc: Exception) {
default.invoke().let { default.invoke().let {
saveConfig(file, it, pretty) saveConfig(file, it, json)
return it return it
} }
} }