net.bjoernpetersen.musicbot.api.config.Config.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of musicbot Show documentation
Show all versions of musicbot Show documentation
Core library of MusicBot, which plays music from various providers.
package net.bjoernpetersen.musicbot.api.config
import mu.KotlinLogging
import net.bjoernpetersen.musicbot.api.config.Config.BooleanEntry
import net.bjoernpetersen.musicbot.api.config.Config.SerializedEntry
import net.bjoernpetersen.musicbot.spi.config.ConfigChecker
import net.bjoernpetersen.musicbot.spi.config.ConfigStorageAdapter
/**
* A configuration view for a specific config scope.
* There are many instances of Config per bot-instance for various scopes.
*
* The actual config location is determined by the [storage adapter][adapter].
*
* At the root, every config entry is stored as a string. You can create entries for other types
* by providing a serializer/deserializer to [SerializedEntry] though.
* For the common case of boolean values, [BooleanEntry] is already predefined.
*/
class Config internal constructor(
private val adapter: ConfigStorageAdapter,
private val scope: ConfigScope) {
private val logger = KotlinLogging.logger {}
private val entries: MutableMap = adapter.load(scope).toMutableMap()
private fun getValue(key: String): String? {
return entries[key]?.let {
if (it.isBlank()) null
else it
}
}
private fun setValue(key: String, value: String?) {
val old = getValue(key)
if (old != value) {
logger.debug {
"Config[$scope] entry '$key' changed"
}
if (value.isNullOrBlank()) {
entries.remove(key)
} else {
entries[key] = value
}
adapter.store(scope, entries)
}
}
/**
* Base class for config entries.
*
* @param key the unique (in scope) entry key
* @param description a description of what the entry does
* @param uiNode a visual representation of the config entry, not needed for state
*/
abstract inner class Entry internal constructor(
val key: String,
val description: String,
val uiNode: UiNode?) {
abstract fun getWithoutDefault(): T?
abstract fun get(): T?
abstract fun set(value: T?)
abstract fun checkError(): String?
}
/**
* A string config entry.
*
* @param key the unique (in scope) entry key
* @param description a description of what the entry does
* @param configChecker a validator for entry values
* @param uiNode a visual representation of the config entry, not needed for state
* @param default a default value
*/
inner class StringEntry @JvmOverloads constructor(
key: String,
description: String,
private val configChecker: ConfigChecker,
uiNode: UiNode? = null,
val default: String? = null) : Entry(key, description, uiNode) {
override fun getWithoutDefault(): String? {
return getValue(key)
}
/**
* Gets the value of this entry, or the default value if there is none.
*/
override fun get(): String? {
return getWithoutDefault() ?: default
}
/**
* Sets the value for this entry. Note that blank values are handled like `null`.
*/
override fun set(value: String?) {
setValue(key, value)
}
override fun checkError(): String? = configChecker(get())
}
/**
* A config entry accepting a non-string type.
*
* @param key the unique (in scope) entry key
* @param description a description of what the entry does
* @param serializer a config serializer to convert from/to string
* @param configChecker a validator for entry values
* @param uiNode a visual representation of the config entry, not needed for state
* @param default a default value
*/
open inner class SerializedEntry @JvmOverloads constructor(
key: String,
description: String,
private val serializer: ConfigSerializer,
private val configChecker: ConfigChecker,
uiNode: UiNode? = null,
val default: T? = null) : Entry(key, description, uiNode) {
override fun getWithoutDefault(): T? = try {
getValue(key)?.let { serializer.deserialize(it) }
} catch (e: SerializationException) {
logger.error(e) { "Deserialization failure" }
setValue(key, null)
null
}
override fun get(): T? = getWithoutDefault() ?: default
override fun set(value: T?) {
setValue(key, value?.let { serializer.serialize(it) })
}
override fun checkError(): String? = configChecker(get())
}
/**
* A boolean config entry.
*
* @param key the unique (in scope) entry key
* @param description a description of what the entry does
* @param default a default value
*/
inner class BooleanEntry(
key: String,
description: String,
default: Boolean) :
SerializedEntry(key, description, BooleanSerializer, { null }, CheckBox, default) {
override fun get(): Boolean = super.get()!!
}
}
private object BooleanSerializer : ConfigSerializer {
override fun serialize(obj: Boolean): String = obj.toString()
override fun deserialize(string: String): Boolean = string.toBoolean()
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy