aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/at/hannibal2/skyhanni/events/ConfigMigrationEvent.kt
blob: b4a2667f668b34b9360fb5ac9ea27239633da9cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package at.hannibal2.skyhanni.events

import at.hannibal2.skyhanni.config.migration.LoadResult
import at.hannibal2.skyhanni.config.migration.MigratingConfigLoader
import at.hannibal2.skyhanni.config.migration.ResolutionPath
import com.google.gson.JsonElement
import com.google.gson.JsonObject
import java.lang.reflect.Field
import java.lang.reflect.Type
import kotlin.reflect.KProperty1


data class ConfigMigrationEvent(
    val loader: MigratingConfigLoader,
    val resolutionPath: ResolutionPath,
    val objectHierarchy: List<JsonElement?>,
    val type: Type,
    var value: LoadResult<*>
) : LorenzEvent() {
    val property = (resolutionPath as? ResolutionPath.FieldChild)?.field


    fun use(value: Any?) {
        this.value = LoadResult.Instance(value)
    }

    fun isFailing(): Boolean {
        return value is LoadResult.Failure || value is LoadResult.Invalid
    }

    fun useDefault() {
        this.value = LoadResult.UseDefault
    }

    data class MigrateContext(val hierarchy: List<JsonElement?>) {
        fun parent(n: Int = 1): MigrateContext = MigrateContext(hierarchy.dropLast(n))
        fun child(name: String) = MigrateContext(hierarchy + (hierarchy.last() as? JsonObject)?.get(name))
        fun root(): MigrateContext = MigrateContext(hierarchy.take(1))
    }

    inline fun <reified T, V> migrate(prop: KProperty1<T, V>, noinline block: MigrateContext.() -> MigrateContext) {
        if (prop.name != property?.name) return
        val field = try {
            T::class.java.getDeclaredField(prop.name)
        } catch (e: NoSuchFieldException) {
            return
        }
        migrate(field, block)
    }

    inline fun <reified T, V> migrate(
        prop: KProperty1<T, V>,
        noinline block: MigrateContext.() -> MigrateContext,
        oldType: Type,
        noinline mapper: (Any?) -> T?
    ) {
        if (prop.name != property?.name) return
        val field = try {
            T::class.java.getDeclaredField(prop.name)
        } catch (e: NoSuchFieldException) {
            return
        }
        migrate(field, block, oldType, mapper)
    }

    fun migrate(prop: Field, block: MigrateContext.() -> MigrateContext) = migrate(prop, block, type) { it }
    fun migrate(prop: Field, block: MigrateContext.() -> MigrateContext, oldType: Type, mapper: (Any?) -> Any?) {
        if (prop != property) return
        this.value =
            loader.loadElement(resolutionPath, MigrateContext(objectHierarchy).let(block).hierarchy, oldType)
                .map(mapper)
    }
}