diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/config/profile/delegate/types/RedirectDelegateTest.kt b/src/integration-test/kotlin/de/bixilon/minosoft/config/profile/delegate/types/RedirectDelegateTest.kt new file mode 100644 index 000000000..fd6b08e8b --- /dev/null +++ b/src/integration-test/kotlin/de/bixilon/minosoft/config/profile/delegate/types/RedirectDelegateTest.kt @@ -0,0 +1,104 @@ +/* + * Minosoft + * Copyright (C) 2020-2023 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.config.profile.delegate.types + +import com.fasterxml.jackson.databind.InjectableValues +import com.fasterxml.jackson.databind.node.ObjectNode +import com.fasterxml.jackson.module.kotlin.convertValue +import de.bixilon.kutil.concurrent.lock.Lock +import de.bixilon.kutil.json.JsonObject +import de.bixilon.minosoft.config.profile.ProfileLock +import de.bixilon.minosoft.config.profile.profiles.Profile +import de.bixilon.minosoft.config.profile.storage.ProfileStorage +import de.bixilon.minosoft.util.json.Jackson +import org.testng.Assert.assertEquals +import org.testng.annotations.Test + +@Test(groups = ["profiles"]) +class RedirectDelegateTest { + private val jacksonType by lazy { Jackson.MAPPER.typeFactory.constructType(TestProfile::class.java) } + private val reader by lazy { Jackson.MAPPER.readerFor(jacksonType) } + + private fun create(): TestProfile { + return TestProfile() + } + + private fun TestProfile.update(data: JsonObject) { + val tree = Jackson.MAPPER.convertValue(data) + + + val injectable = InjectableValues.Std() + injectable.addValue(TestProfile::class.java, this) + reader + .withValueToUpdate(this) + .with(injectable) + .readValue(tree) + } + + private fun TestProfile.serialize(): JsonObject { + return Jackson.MAPPER.convertValue(this, Jackson.JSON_MAP_TYPE) + } + + fun setup() { + reader + val profile = create() + } + + fun `update with just the normal property`() { + val profile = create() + assertEquals(profile.config.normal, "test") + profile.update(mapOf("config" to mapOf("normal" to "abc"))) + assertEquals(profile.config.normal, "abc") + } + + fun `update redirect property`() { + val profile = create() + assertEquals(profile.config.prop, null) + profile.update(mapOf("config" to mapOf("normal" to 12))) + assertEquals(profile.config.prop, Boxed(12, false)) + } + + fun `assign redirect property`() { + val profile = create() + profile.config.prop = Boxed(123, true) + } + + fun `serialize redirect property`() { + val profile = create() + profile.config.prop = Boxed(123, true) + val data = profile.serialize() + assertEquals(data, mapOf("config" to mapOf("prop" to 123, "normal" to "test"))) + } + + + class TestProfile( + override var storage: ProfileStorage? = null, + override val lock: Lock = ProfileLock(), + ) : Profile { + val config = TestConfig(this) + } + + class TestConfig(profile: Profile) { + var prop by RedirectDelegate(profile, { it?.value }, { it?.let { Boxed(it, false) } }) + var normal by StringDelegate(profile, "test") + } + + class Boxed(val value: Int, val unused: Boolean) { + + override fun equals(other: Any?): Boolean { + if (other !is Boxed) return false + return other.value == this.value + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/config/profile/delegate/types/RedirectDelegate.kt b/src/main/java/de/bixilon/minosoft/config/profile/delegate/types/RedirectDelegate.kt new file mode 100644 index 000000000..19561ac56 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/config/profile/delegate/types/RedirectDelegate.kt @@ -0,0 +1,36 @@ +/* + * Minosoft + * Copyright (C) 2020-2023 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.config.profile.delegate.types + +import de.bixilon.kutil.observer.DataObserver +import de.bixilon.minosoft.config.profile.delegate.AbstractProfileDelegate +import de.bixilon.minosoft.config.profile.profiles.Profile +import kotlin.reflect.KProperty + +class RedirectDelegate( + override val profile: Profile, + val serializer: (V?) -> S?, + val lookup: (S?) -> V?, +) : DataObserver(null), AbstractProfileDelegate { + + + override fun setValue(thisRef: Any, property: KProperty<*>, value: V?) { + super.setValue(thisRef, property, value) + invalidate() + } + + // fun setValue(thisRef: Any, property: KProperty<*>, value: S?) { +// setValue(thisRef, property, lookup(value)) +// } +} diff --git a/src/main/java/de/bixilon/minosoft/config/profile/profiles/account/AccountProfile.kt b/src/main/java/de/bixilon/minosoft/config/profile/profiles/account/AccountProfile.kt index ce85dc408..ffc52dade 100644 --- a/src/main/java/de/bixilon/minosoft/config/profile/profiles/account/AccountProfile.kt +++ b/src/main/java/de/bixilon/minosoft/config/profile/profiles/account/AccountProfile.kt @@ -13,15 +13,11 @@ package de.bixilon.minosoft.config.profile.profiles.account -import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonInclude -import com.fasterxml.jackson.annotation.JsonProperty -import de.bixilon.kutil.delegates.BackingDelegate -import de.bixilon.kutil.observer.DataObserver.Companion.observe import de.bixilon.minosoft.config.profile.ProfileLock import de.bixilon.minosoft.config.profile.ProfileType import de.bixilon.minosoft.config.profile.delegate.primitive.BooleanDelegate -import de.bixilon.minosoft.config.profile.delegate.types.NullableStringDelegate +import de.bixilon.minosoft.config.profile.delegate.types.RedirectDelegate import de.bixilon.minosoft.config.profile.delegate.types.StringDelegate import de.bixilon.minosoft.config.profile.delegate.types.map.MapDelegate import de.bixilon.minosoft.config.profile.profiles.Profile @@ -62,19 +58,7 @@ class AccountProfile( var entries: MutableMap by MapDelegate(this, mutableMapOf()) private set - /** - * The current id of the selected account - */ - @get:JsonInclude(JsonInclude.Include.NON_NULL) - @get:JsonProperty("selected") - private var _selected: String? by NullableStringDelegate(this, null) - - @get:JsonIgnore - var selected: Account? by BackingDelegate(get = { entries[_selected] }, set = { _selected = it?.id }) - - init { - this::_selected.observe(this) { this.selected = entries[it] } - } + var selected: Account? by RedirectDelegate(this, { it?.id }, { entries[it] }) override fun toString(): String { return storage?.toString() ?: super.toString() diff --git a/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/server/entries/ErosServer.kt b/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/server/entries/ErosServer.kt index 28417571e..7422599e9 100644 --- a/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/server/entries/ErosServer.kt +++ b/src/main/java/de/bixilon/minosoft/config/profile/profiles/eros/server/entries/ErosServer.kt @@ -14,16 +14,12 @@ package de.bixilon.minosoft.config.profile.profiles.eros.server.entries import com.fasterxml.jackson.annotation.JacksonInject -import com.fasterxml.jackson.annotation.JsonIgnore import com.fasterxml.jackson.annotation.JsonInclude -import com.fasterxml.jackson.annotation.JsonProperty -import de.bixilon.kutil.cast.CastUtil.unsafeCast -import de.bixilon.kutil.delegates.BackingDelegate -import de.bixilon.kutil.observer.DataObserver.Companion.observe import de.bixilon.minosoft.assets.util.HashTypes import de.bixilon.minosoft.config.profile.delegate.SimpleDelegate import de.bixilon.minosoft.config.profile.delegate.primitive.BooleanDelegate import de.bixilon.minosoft.config.profile.delegate.types.NullableStringDelegate +import de.bixilon.minosoft.config.profile.delegate.types.RedirectDelegate import de.bixilon.minosoft.config.profile.delegate.types.map.MapDelegate import de.bixilon.minosoft.config.profile.profiles.eros.ErosProfile import de.bixilon.minosoft.data.registries.identified.ResourceLocation @@ -67,16 +63,8 @@ class ErosServer( @get:JsonInclude(JsonInclude.Include.NON_EMPTY) override var profiles: MutableMap by MapDelegate(profile, profiles) - @get:JsonProperty("forced_version") @get:JsonInclude(JsonInclude.Include.NON_NULL) - private var _forcedVersion by NullableStringDelegate(profile, forcedVersion.unsafeCast()?.name) - - @get:JsonIgnore - override var forcedVersion by BackingDelegate(get = { Versions[_forcedVersion] }, set = { _forcedVersion = it?.name }) - - init { - this::_forcedVersion.observe(this) { this.forcedVersion = Versions[it] } - } + override var forcedVersion: Version? by RedirectDelegate(profile, { it?.name }, { Versions[it] }) @get:JsonInclude(JsonInclude.Include.NON_DEFAULT) override var faviconHash: String? by NullableStringDelegate(profile, null) { if (it != null) check(it.length == HashTypes.SHA256.length) { "Not a valid sha256 hash!" } } diff --git a/src/main/java/de/bixilon/minosoft/gui/eros/dialog/profiles/ProfileCreateDialog.kt b/src/main/java/de/bixilon/minosoft/gui/eros/dialog/profiles/ProfileCreateDialog.kt index 433719b62..84e621570 100644 --- a/src/main/java/de/bixilon/minosoft/gui/eros/dialog/profiles/ProfileCreateDialog.kt +++ b/src/main/java/de/bixilon/minosoft/gui/eros/dialog/profiles/ProfileCreateDialog.kt @@ -14,9 +14,9 @@ package de.bixilon.minosoft.gui.eros.dialog.profiles import de.bixilon.kutil.cast.CastUtil.unsafeCast +import de.bixilon.minosoft.config.profile.ProfileUtil.isValidName import de.bixilon.minosoft.config.profile.manager.ProfileManagers import de.bixilon.minosoft.config.profile.profiles.Profile -import de.bixilon.minosoft.config.profile.storage.ProfileIOUtil.isValidName import de.bixilon.minosoft.config.profile.storage.StorageProfileManager import de.bixilon.minosoft.data.registries.identified.ResourceLocation import de.bixilon.minosoft.gui.eros.controller.JavaFXWindowController