Skip to content

Commit 1c15fd1

Browse files
committed
Refactor: LoadedConfiguration API
1 parent a43e0ab commit 1c15fd1

File tree

7 files changed

+252
-304
lines changed

7 files changed

+252
-304
lines changed

bukkit/src/main/kotlin/io/github/rothes/esu/bukkit/module/SocialFilterModule.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ object SocialFilterModule: BukkitModule<BaseModuleConfiguration, SocialFilterMod
4444
super.onReload()
4545
filters = ConfigLoader.loadMulti(
4646
moduleFolder.resolve("filters"),
47-
ConfigLoader.LoaderSettingsMulti<Filter>(
47+
ConfigLoader.LoaderSettingsMulti(
4848
initializeConfigs = listOf("example")
4949
)
5050
)

core/src/main/kotlin/io/github/rothes/esu/core/configuration/ConfigLoader.kt

Lines changed: 119 additions & 196 deletions
Large diffs are not rendered by default.
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package io.github.rothes.esu.core.configuration
2+
3+
import io.github.rothes.esu.core.module.configuration.EmptyConfiguration
4+
import io.github.rothes.esu.lib.configurate.ConfigurationNode
5+
import io.github.rothes.esu.lib.configurate.yaml.YamlConfigurationLoader
6+
import java.nio.file.Path
7+
8+
data class LoadedConfiguration(
9+
val context: LoaderContext,
10+
val path: Path,
11+
val node: ConfigurationNode,
12+
val resourceNode: ConfigurationNode?,
13+
) {
14+
15+
fun save() {
16+
var root = node
17+
while (node.parent() != null) {
18+
root = root.parent()!!
19+
}
20+
context.loader.save(root)
21+
}
22+
23+
fun <T> getAs(clazz: Class<T>): T {
24+
if (context.mergeResources && resourceNode != null) {
25+
node.mergeFrom(resourceNode)
26+
}
27+
if (clazz.isInstance(EmptyConfiguration)) return clazz.cast(EmptyConfiguration)
28+
else if (clazz.isInstance(Unit)) return clazz.cast(Unit)
29+
30+
val instance = node.require(clazz)
31+
node.set(instance)
32+
return instance
33+
}
34+
35+
fun node(vararg path: Any): LoadedConfiguration {
36+
return LoadedConfiguration(
37+
this.context,
38+
this.path,
39+
this.node.node(*path),
40+
this.resourceNode?.node(*path),
41+
)
42+
}
43+
44+
data class LoaderContext(
45+
val loader: YamlConfigurationLoader,
46+
val mergeResources: Boolean,
47+
)
48+
49+
}

core/src/main/kotlin/io/github/rothes/esu/core/module/CommonFeature.kt

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ abstract class CommonFeature<C, L> : Feature<C, L> {
2323
private set
2424
final override var parent: Feature<*, *>? = null
2525
private set
26-
protected var internalModule: Module<*, *>? = null
26+
private var _module: Module<*, *>? = null
2727
override val module: Module<*, *>
28-
get() = internalModule ?: error("Feature $name is not attached to a module")
28+
get() = _module ?: error("Feature $name is not attached to a module")
2929

3030
final override val configClass: Class<C>
3131
final override val langClass: Class<L>
@@ -55,11 +55,13 @@ abstract class CommonFeature<C, L> : Feature<C, L> {
5555
langClass = actualTypeArguments[1].actualClass() as Class<L>
5656
}
5757

58-
private var configValue: C? = null
58+
private var _config: C? = null
59+
private var _lang: MultiLangConfiguration<L>? = null
5960

6061
final override val config: C
61-
get() = configValue ?: error("Config is not loaded for feature $name")
62-
final override val lang: MultiLangConfiguration<L> = MultiLangConfiguration(mutableMapOf())
62+
get() = _config ?: error("Config is not loaded for feature $name")
63+
final override val lang: MultiLangConfiguration<L>
64+
get() = _lang ?: error("Lang is not loaded for feature $name")
6365

6466
override val permissionNode: String by lazy { (parent?.permissionNode ?: EsuCore.instance.basePermissionNode) + "." + name.lowercase() }
6567

@@ -68,7 +70,11 @@ abstract class CommonFeature<C, L> : Feature<C, L> {
6870
}
6971

7072
final override fun setConfigInstance(instance: C) {
71-
configValue = instance
73+
_config = instance
74+
}
75+
76+
override fun setLangInstance(instance: MultiLangConfiguration<L>) {
77+
_lang = instance
7278
}
7379

7480
final override fun setEnabled(value: Boolean) {
@@ -85,7 +91,7 @@ abstract class CommonFeature<C, L> : Feature<C, L> {
8591
if (temp !is Module<*, *>) {
8692
temp = null
8793
}
88-
internalModule = temp
94+
_module = temp
8995
}
9096

9197
protected val children = linkedMapOf<String, Feature<*, *>>()

core/src/main/kotlin/io/github/rothes/esu/core/module/CommonModule.kt

Lines changed: 69 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,11 @@ package io.github.rothes.esu.core.module
22

33
import io.github.rothes.esu.core.EsuCore
44
import io.github.rothes.esu.core.configuration.ConfigLoader
5+
import io.github.rothes.esu.core.configuration.ConfigLoader.forEachValue
6+
import io.github.rothes.esu.core.configuration.ConfigLoader.map
7+
import io.github.rothes.esu.core.configuration.LoadedConfiguration
8+
import io.github.rothes.esu.core.configuration.MultiConfiguration
59
import io.github.rothes.esu.core.configuration.MultiLangConfiguration
6-
import io.github.rothes.esu.core.module.configuration.FeatureNodeMapper
7-
import io.github.rothes.esu.core.module.configuration.FeatureNodeMapper.Companion.nodeMapper
810
import io.github.rothes.esu.core.module.configuration.FeatureToggle
911
import io.github.rothes.esu.core.user.User
1012
import io.github.rothes.esu.lib.configurate.yaml.YamlConfigurationLoader
@@ -25,31 +27,7 @@ abstract class CommonModule<C, L> : CommonFeature<C, L>(), Module<C, L> {
2527
}
2628

2729
override fun doReload() {
28-
ConfigLoader.load(
29-
configPath,
30-
configClass,
31-
ConfigLoader.LoaderSettings(
32-
yamlLoader = { buildConfigLoader(it); it },
33-
nodeMapper = nodeMapper(FeatureNodeMapper.TargetClass.CONFIG)
34-
)
35-
)
36-
fun clearLang(feature: Feature<*, *>) {
37-
val map = feature.lang.configs as MutableMap
38-
map.clear()
39-
for (feature in feature.getFeatures()) {
40-
clearLang(feature)
41-
}
42-
}
43-
clearLang(this)
44-
ConfigLoader.loadMulti<MultiLangConfiguration<L>, L>(
45-
langPath,
46-
langClass,
47-
ConfigLoader.LoaderSettingsMulti(
48-
"en_us",
49-
yamlLoader = { buildLangLoader(it); it },
50-
nodeMapper = nodeMapper(FeatureNodeMapper.TargetClass.LANG)
51-
)
52-
)
30+
ModuleConfigurationsLoader.load(this)
5331
super.doReload()
5432
}
5533

@@ -67,4 +45,68 @@ abstract class CommonModule<C, L> : CommonFeature<C, L>(), Module<C, L> {
6745
return hasPermission(perm(shortPerm))
6846
}
6947

48+
private object ModuleConfigurationsLoader {
49+
50+
fun load(root: CommonModule<*, *>) {
51+
with(root) {
52+
val configNode = ConfigLoader.loadConfiguration(
53+
configPath,
54+
ConfigLoader.LoaderSettings(
55+
yamlLoader = { buildConfigLoader(it); it },
56+
),
57+
configClass,
58+
)
59+
val langNodes = ConfigLoader.loadConfigurationMulti(
60+
langPath,
61+
MultiLangConfiguration::class.java,
62+
langClass,
63+
ConfigLoader.LoaderSettingsMulti(
64+
"en_us",
65+
yamlLoader = { buildLangLoader(it); it },
66+
)
67+
)
68+
loadConfig(root, configNode)
69+
loadLang(root, langNodes)
70+
configNode.save()
71+
langNodes.forEachValue { it.save() }
72+
}
73+
}
74+
75+
fun <C, L> loadConfig(feature: Feature<C, L>, node: LoadedConfiguration) {
76+
feature.setConfigInstance(node.getAs(feature.configClass))
77+
78+
feature.forEachChild { child, configPath ->
79+
loadConfig(child, node.node(configPath))
80+
}
81+
}
82+
83+
fun <C, L> loadLang(feature: Feature<C, L>, nodes: MultiConfiguration<LoadedConfiguration>) {
84+
feature.setLangInstance(nodes.map { node -> node.getAs(feature.langClass) })
85+
86+
feature.forEachChild { child, configPath ->
87+
loadLang(child, nodes.map { node -> node.node(configPath) })
88+
}
89+
}
90+
91+
private fun Feature<*, *>.forEachChild(scope: (child: Feature<*, *>, configPath: String) -> Unit) {
92+
for (child in getFeatures()) {
93+
val name = child.name
94+
val path = buildString(name.length + 4) {
95+
append(name.firstOrNull()?.lowercaseChar() ?: return@buildString)
96+
var i = 1
97+
while (i < name.length) {
98+
if (name[i].isUpperCase()) {
99+
append('-')
100+
append(name[i].lowercaseChar())
101+
} else {
102+
append(name[i])
103+
}
104+
i++
105+
}
106+
}
107+
scope(child, path)
108+
}
109+
}
110+
}
111+
70112
}

core/src/main/kotlin/io/github/rothes/esu/core/module/Feature.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ interface Feature<C, L> {
2323
val permissionNode: String
2424

2525
fun setConfigInstance(instance: C) {}
26+
fun setLangInstance(instance: MultiLangConfiguration<L>) {}
2627
fun setEnabled(value: Boolean) {
2728
// Notify children
2829
for (feature in getFeatures().let { if (enabled) it else it.reversed() }) {

core/src/main/kotlin/io/github/rothes/esu/core/module/configuration/FeatureNodeMapper.kt

Lines changed: 0 additions & 73 deletions
This file was deleted.

0 commit comments

Comments
 (0)