From 5923bc5821f7d517bd4a6edf74678b27da194c4b Mon Sep 17 00:00:00 2001 From: Paul Kraft Date: Fri, 8 Nov 2024 13:58:38 -0800 Subject: [PATCH 01/12] Finish up SpeziFoundation --- .../core/utils/foundation/RepositoryAnchor.kt | 3 + .../core/utils/foundation/SharedRepository.kt | 97 +++++++ .../foundation/builtin/RepositoryValue.kt | 17 ++ .../foundation/builtin/ValueRepository.kt | 36 +++ .../ComputedKnowledgeSource.kt | 12 + .../DefaultProvidingKnowledgeSource.kt | 8 + .../knowledgesource/KnowledgeSource.kt | 12 + .../OptionalComputedKnowledgeSource.kt | 12 + .../SomeComputedKnowledgeSource.kt | 12 + .../spezi/core/utils/SharedRepositoryTest.kt | 269 ++++++++++++++++++ 10 files changed, 478 insertions(+) create mode 100644 core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/RepositoryAnchor.kt create mode 100644 core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt create mode 100644 core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/RepositoryValue.kt create mode 100644 core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt create mode 100644 core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt create mode 100644 core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/DefaultProvidingKnowledgeSource.kt create mode 100644 core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/KnowledgeSource.kt create mode 100644 core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt create mode 100644 core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/SomeComputedKnowledgeSource.kt create mode 100644 core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/RepositoryAnchor.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/RepositoryAnchor.kt new file mode 100644 index 000000000..80f040bb8 --- /dev/null +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/RepositoryAnchor.kt @@ -0,0 +1,3 @@ +package edu.stanford.spezi.core.utils.foundation + +interface RepositoryAnchor diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt new file mode 100644 index 000000000..91fc558b5 --- /dev/null +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt @@ -0,0 +1,97 @@ +package edu.stanford.spezi.core.utils.foundation + +import edu.stanford.spezi.core.utils.foundation.knowledgesource.ComputedKnowledgeSource +import edu.stanford.spezi.core.utils.foundation.knowledgesource.ComputedKnowledgeSourceStoragePolicy +import edu.stanford.spezi.core.utils.foundation.knowledgesource.DefaultProvidingKnowledgeSource +import edu.stanford.spezi.core.utils.foundation.knowledgesource.KnowledgeSource +import edu.stanford.spezi.core.utils.foundation.knowledgesource.OptionalComputedKnowledgeSource +import kotlin.reflect.KClass + +@Suppress("detekt:TooManyFunctions") +interface SharedRepository { + operator fun get(source: KnowledgeSource): Value? + operator fun set(source: KnowledgeSource, value: Value?) + + operator fun get(source: KnowledgeSource, default: Value): Value = + this[source] ?: default.also { this[source] = it } + + operator fun set(source: KnowledgeSource, default: Value, value: Value) { + this[source] = value + } + + operator fun get( + source: DefaultProvidingKnowledgeSource, + ): Value = getOrDefault(source) + + fun getOrDefault( + source: DefaultProvidingKnowledgeSource, + ): Value { + return get( + source as KnowledgeSource, + ) ?: source.defaultValue + } + + operator fun get( + source: ComputedKnowledgeSource< + Anchor, + Value, + in SharedRepository, + >, + ): Value = getOrComputed(source) + + fun getOrComputed( + source: ComputedKnowledgeSource< + Anchor, + Value, + in SharedRepository, + >, + ): Value { + return get( + source as KnowledgeSource, + ) ?: when (source.storagePolicy) { + is ComputedKnowledgeSourceStoragePolicy.AlwaysCompute -> { + source.compute(this) + } + is ComputedKnowledgeSourceStoragePolicy.Store -> { + val value = source.compute(this) + this[source] = value + value + } + } + } + + operator fun get( + source: OptionalComputedKnowledgeSource< + Anchor, + Value, + in SharedRepository, + >, + ): Value? = getOrOptionalComputed(source) + + fun getOrOptionalComputed( + source: OptionalComputedKnowledgeSource< + Anchor, + Value, + in SharedRepository, + >, + ): Value? { + return get( + source as KnowledgeSource, + ) ?: when (source.storagePolicy) { + ComputedKnowledgeSourceStoragePolicy.AlwaysCompute -> { + source.compute(this) + } + ComputedKnowledgeSourceStoragePolicy.Store -> { + val value = source.compute(this) + this[source] = value + value + } + } + } + + fun collect(allOf: KClass): List + + fun contains(source: KnowledgeSource): Boolean { + return get(source) != null + } +} diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/RepositoryValue.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/RepositoryValue.kt new file mode 100644 index 000000000..3f690f7db --- /dev/null +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/RepositoryValue.kt @@ -0,0 +1,17 @@ +package edu.stanford.spezi.core.utils.foundation.builtin + +import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor +import edu.stanford.spezi.core.utils.foundation.knowledgesource.KnowledgeSource + +interface AnyRepositoryValue { + val anySource: KnowledgeSource<*, *> + val anyValue: Any +} + +data class RepositoryValue( + val source: KnowledgeSource, + val value: Value +) : AnyRepositoryValue { + override val anySource: KnowledgeSource<*, *> get() = source + override val anyValue: Any get() = value +} diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt new file mode 100644 index 000000000..fbe974cdd --- /dev/null +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt @@ -0,0 +1,36 @@ +package edu.stanford.spezi.core.utils.foundation.builtin + +import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor +import edu.stanford.spezi.core.utils.foundation.SharedRepository +import edu.stanford.spezi.core.utils.foundation.knowledgesource.KnowledgeSource +import java.util.UUID +import kotlin.reflect.KClass + +data class ValueRepository( + internal var storage: MutableMap = mutableMapOf() +) : SharedRepository, Sequence { + @Suppress("UNCHECKED_CAST") + override operator fun get( + source: KnowledgeSource, + ): Value? { + return storage[source.uuid]?.let { it.anyValue as? Value } + } + + override operator fun set( + source: KnowledgeSource, + value: Value?, + ) { + value?.let { + storage[source.uuid] = RepositoryValue(source, it) + } ?: storage.remove(source.uuid) + } + + @Suppress("UNCHECKED_CAST") + override fun collect(allOf: KClass): List { + return storage.values.mapNotNull { it.anyValue as? Value } + } + + override fun iterator(): Iterator { + return storage.values.iterator() + } +} diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt new file mode 100644 index 000000000..152453fc0 --- /dev/null +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt @@ -0,0 +1,12 @@ +package edu.stanford.spezi.core.utils.foundation.knowledgesource + +import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor + +interface ComputedKnowledgeSource< + Anchor : RepositoryAnchor, + Value, + Repository + > : SomeComputedKnowledgeSource { + + fun compute(repository: Repository): Value +} diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/DefaultProvidingKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/DefaultProvidingKnowledgeSource.kt new file mode 100644 index 000000000..56cdf9b79 --- /dev/null +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/DefaultProvidingKnowledgeSource.kt @@ -0,0 +1,8 @@ +package edu.stanford.spezi.core.utils.foundation.knowledgesource + +import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor + +interface DefaultProvidingKnowledgeSource : + KnowledgeSource { + val defaultValue: Value +} diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/KnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/KnowledgeSource.kt new file mode 100644 index 000000000..2b98c60f5 --- /dev/null +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/KnowledgeSource.kt @@ -0,0 +1,12 @@ +package edu.stanford.spezi.core.utils.foundation.knowledgesource + +import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor +import java.util.UUID + +interface KnowledgeSource { + @Suppress("detekt:VariableMinLength") + val uuid: UUID + + fun isEqualTo(other: KnowledgeSource): Boolean = + uuid == other.uuid +} diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt new file mode 100644 index 000000000..4825dd792 --- /dev/null +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt @@ -0,0 +1,12 @@ +package edu.stanford.spezi.core.utils.foundation.knowledgesource + +import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor + +interface OptionalComputedKnowledgeSource< + Anchor : RepositoryAnchor, + Value, + Repository + > : SomeComputedKnowledgeSource { + + fun compute(repository: Repository): Value? +} diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/SomeComputedKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/SomeComputedKnowledgeSource.kt new file mode 100644 index 000000000..80b228f63 --- /dev/null +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/SomeComputedKnowledgeSource.kt @@ -0,0 +1,12 @@ +package edu.stanford.spezi.core.utils.foundation.knowledgesource + +import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor + +sealed interface ComputedKnowledgeSourceStoragePolicy { + data object AlwaysCompute : ComputedKnowledgeSourceStoragePolicy + data object Store : ComputedKnowledgeSourceStoragePolicy +} + +interface SomeComputedKnowledgeSource : KnowledgeSource { + val storagePolicy: ComputedKnowledgeSourceStoragePolicy +} diff --git a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt new file mode 100644 index 000000000..1fc7ad12a --- /dev/null +++ b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt @@ -0,0 +1,269 @@ +package edu.stanford.spezi.core.utils + +import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor +import edu.stanford.spezi.core.utils.foundation.SharedRepository +import edu.stanford.spezi.core.utils.foundation.builtin.ValueRepository +import edu.stanford.spezi.core.utils.foundation.knowledgesource.ComputedKnowledgeSource +import edu.stanford.spezi.core.utils.foundation.knowledgesource.ComputedKnowledgeSourceStoragePolicy +import edu.stanford.spezi.core.utils.foundation.knowledgesource.DefaultProvidingKnowledgeSource +import edu.stanford.spezi.core.utils.foundation.knowledgesource.KnowledgeSource +import edu.stanford.spezi.core.utils.foundation.knowledgesource.OptionalComputedKnowledgeSource +import org.junit.Test +import java.util.UUID + +object TestAnchor : RepositoryAnchor + +interface TestTypes { + val value: Int +} + +data class TestDataClass(override var value: Int) : TestTypes { + companion object { + val key = object : KnowledgeSource { + override val uuid = UUID() + } + } +} + +@Suppress("detekt:UseDataClass") +class TestClass(override val value: Int) : TestTypes { + override fun hashCode(): Int { + return super.hashCode() + } + + override fun equals(other: Any?): Boolean { + return (other as? TestClass)?.value == value + } + + companion object { + val key = object : KnowledgeSource { + override val uuid = UUID() + } + } +} + +object KeyLike : KnowledgeSource { + override val uuid = UUID() +} + +data class DefaultedTestDataClass(override val value: Int) : TestTypes { + companion object { + val key = object : DefaultProvidingKnowledgeSource { + override val uuid = UUID() + override val defaultValue get() = DefaultedTestDataClass(0) + } + } +} + +data class ComputedTestDataClass(override val value: Int) : TestTypes { + companion object { + val alwaysComputeKey = object : ComputedKnowledgeSource< + TestAnchor, + ComputedTestDataClass, + SharedRepository + > { + override val uuid = UUID() + override val storagePolicy: ComputedKnowledgeSourceStoragePolicy + = ComputedKnowledgeSourceStoragePolicy.AlwaysCompute + override fun compute(repository: SharedRepository) = + ComputedTestDataClass(computedValue) + } + + val storeKey = object : ComputedKnowledgeSource< + TestAnchor, + ComputedTestDataClass, + SharedRepository + > { + override val uuid = UUID() + override val storagePolicy: ComputedKnowledgeSourceStoragePolicy + = ComputedKnowledgeSourceStoragePolicy.Store + override fun compute(repository: SharedRepository) = + ComputedTestDataClass(computedValue) + } + } +} + +data class OptionalComputedTestDataClass(override val value: Int) : TestTypes { + companion object { + const val TRUE = true + + val alwaysComputeKey = object : OptionalComputedKnowledgeSource< + TestAnchor, + OptionalComputedTestDataClass, + SharedRepository + > { + override val uuid = UUID() + override val storagePolicy: ComputedKnowledgeSourceStoragePolicy + = ComputedKnowledgeSourceStoragePolicy.AlwaysCompute + override fun compute(repository: SharedRepository): OptionalComputedTestDataClass? = + optionalComputedValue?.let { OptionalComputedTestDataClass(it) } + } + + val storeKey = object : OptionalComputedKnowledgeSource< + TestAnchor, + OptionalComputedTestDataClass, + SharedRepository + > { + override val uuid = UUID() + override val storagePolicy: ComputedKnowledgeSourceStoragePolicy + = ComputedKnowledgeSourceStoragePolicy.Store + override fun compute(repository: SharedRepository): OptionalComputedTestDataClass? = + optionalComputedValue?.let { OptionalComputedTestDataClass(it) } + } + } +} + +var computedValue: Int = 3 +var optionalComputedValue: Int? = null + +class SharedRepositoryTest { + private val repository = ValueRepository() + + @Test + fun testIteration() { + repository[TestDataClass.key] = TestDataClass(3) + + for (value in repository) { + assert(value.anySource === TestDataClass.key) + assert(value.anyValue is TestDataClass) + assert((value.anyValue as? TestDataClass) == TestDataClass(3)) + } + } + + @Test + fun testDefaultSubscript() { + repository[TestDataClass.key, TestDataClass(35)].value = 23 + + val value = repository[TestDataClass.key] + assert(value?.value == 23) + } + + @Test + fun testSetAndGet() { + val testDataClass = TestDataClass(42) + repository[TestDataClass.key] = testDataClass + val contentOfDataClass = repository[TestDataClass.key] + assert(contentOfDataClass === testDataClass) + + val newTestDataClass = TestDataClass(24) + repository[TestDataClass.key] = newTestDataClass + val newContentOfDataClass = repository[TestDataClass.key] + assert(newContentOfDataClass == newTestDataClass) + + repository[TestDataClass.key] = null + val newerContentOfDataClass = repository[TestDataClass.key] + assert(newerContentOfDataClass == null) + } + + @Test + fun testGetWithDefault() { + val testDataClass = DefaultedTestDataClass(42) + + val defaultDataClass = repository[DefaultedTestDataClass.key] + assert(defaultDataClass == DefaultedTestDataClass(0)) + + // The cast is necessary, since it would otherwise not use the non-defaulted one + val regularGet = repository[DefaultedTestDataClass.key as KnowledgeSource] ?: testDataClass + assert(regularGet == testDataClass) + } + + @Test + fun testContains() { + val testDataClass = TestDataClass(42) + assert(!repository.contains(TestDataClass.key)) + + repository[TestDataClass.key] = testDataClass + assert(repository.contains(TestDataClass.key)) + + repository[TestDataClass.key] = null + assert(!repository.contains(TestDataClass.key)) + } + + @Test + fun testGetAllThatConformTo() { + val testDataClass = TestDataClass(42) + repository[TestDataClass.key] = testDataClass + val testClass = TestClass(42) + repository[TestClass.key] = testClass + + val testTypes = repository.collect(allOf = TestTypes::class) + assert(testTypes.count() == 2) + assert(testTypes.all { it.value == 42 }) + } + + @Test + fun testMutationDataClass() { + val testDataClass = TestDataClass(42) + repository[TestDataClass.key] = testDataClass + + val contentOfDataClass = repository[TestDataClass.key] + contentOfDataClass?.value = 24 + // This is different than on iOS - here, data classes use reference semantics! + assert(testDataClass.value == 24) + assert(contentOfDataClass?.value == 24) + } + + @Test + fun testKeyLikeKnowledgeSource() { + val testClass = TestClass(42) + repository[KeyLike] = testClass + + val contentOfClass = repository[KeyLike] + assert(contentOfClass == testClass) + } + + @Test + fun testComputedKnowledgeSourceAlwaysComputePolicy() { + val value = repository[ComputedTestDataClass.alwaysComputeKey] + val optionalValue = repository[OptionalComputedTestDataClass.alwaysComputeKey] + + assert(value.value == computedValue) + assert(optionalValue?.value == optionalComputedValue) + + computedValue = 5 + optionalComputedValue = 4 + + val newValue = repository[ComputedTestDataClass.alwaysComputeKey] + val newOptionalValue = repository[OptionalComputedTestDataClass.alwaysComputeKey] + assert(newValue.value == computedValue) + assert(newOptionalValue?.value == optionalComputedValue) + } + + @Test + fun testComputedKnowledgeSourceStorePolicy() { + val value = repository[ComputedTestDataClass.storeKey] + val optionalValue = repository[OptionalComputedTestDataClass.storeKey] + + assert(value.value == computedValue) + assert(optionalValue?.value == optionalComputedValue) + + // get call bypasses the compute call, so tests if it's really stored + val getValue = repository[ComputedTestDataClass.alwaysComputeKey] + val getOptionalValue = repository[OptionalComputedTestDataClass.alwaysComputeKey] + + assert(getValue.value == computedValue) + assert(getOptionalValue?.value == optionalComputedValue) // this is nil + + // make sure computed knowledge sources with `Store` policy are not re-computed + computedValue = 5 + optionalComputedValue = 4 + + val newValue = repository[ComputedTestDataClass.alwaysComputeKey] + val newOptionalValue = repository[OptionalComputedTestDataClass.alwaysComputeKey] + + assert(newValue.value == value.value) + assert(newOptionalValue?.value == optionalComputedValue) // never stored as it was nil + + // last check if its really written now + val writtenOptionalValue = repository[OptionalComputedTestDataClass.alwaysComputeKey] + assert(writtenOptionalValue?.value == optionalComputedValue) + + // check again that it doesn't change + optionalComputedValue = null + assert(repository[OptionalComputedTestDataClass.storeKey]?.value == 4) + } + + // TODO: fun testComputedKnowledgeSourcePreferred() has not been copied from iOS due to accessing the + // operator fun get will result in ambiguity compiler error, so this behavior would not be possible anyways + +} From 9fd50d1b4adb2ef55a7e879818158aac58e527ed Mon Sep 17 00:00:00 2001 From: Paul Kraft Date: Fri, 8 Nov 2024 14:01:46 -0800 Subject: [PATCH 02/12] detekt --- .../core/utils/foundation/SharedRepository.kt | 12 ++++++------ .../foundation/builtin/RepositoryValue.kt | 2 +- .../foundation/builtin/ValueRepository.kt | 2 +- .../knowledgesource/ComputedKnowledgeSource.kt | 2 +- .../OptionalComputedKnowledgeSource.kt | 2 +- .../spezi/core/utils/SharedRepositoryTest.kt | 18 ++++++++---------- 6 files changed, 18 insertions(+), 20 deletions(-) diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt index 91fc558b5..1e644eb42 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt @@ -79,13 +79,13 @@ interface SharedRepository { source as KnowledgeSource, ) ?: when (source.storagePolicy) { ComputedKnowledgeSourceStoragePolicy.AlwaysCompute -> { - source.compute(this) - } + source.compute(this) + } ComputedKnowledgeSourceStoragePolicy.Store -> { - val value = source.compute(this) - this[source] = value - value - } + val value = source.compute(this) + this[source] = value + value + } } } diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/RepositoryValue.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/RepositoryValue.kt index 3f690f7db..2e9a9fbd4 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/RepositoryValue.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/RepositoryValue.kt @@ -10,7 +10,7 @@ interface AnyRepositoryValue { data class RepositoryValue( val source: KnowledgeSource, - val value: Value + val value: Value, ) : AnyRepositoryValue { override val anySource: KnowledgeSource<*, *> get() = source override val anyValue: Any get() = value diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt index fbe974cdd..8f3eff2c3 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt @@ -7,7 +7,7 @@ import java.util.UUID import kotlin.reflect.KClass data class ValueRepository( - internal var storage: MutableMap = mutableMapOf() + internal var storage: MutableMap = mutableMapOf(), ) : SharedRepository, Sequence { @Suppress("UNCHECKED_CAST") override operator fun get( diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt index 152453fc0..97e1e5b62 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt @@ -5,7 +5,7 @@ import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor interface ComputedKnowledgeSource< Anchor : RepositoryAnchor, Value, - Repository + Repository, > : SomeComputedKnowledgeSource { fun compute(repository: Repository): Value diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt index 4825dd792..81e7c9f21 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt @@ -5,7 +5,7 @@ import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor interface OptionalComputedKnowledgeSource< Anchor : RepositoryAnchor, Value, - Repository + Repository, > : SomeComputedKnowledgeSource { fun compute(repository: Repository): Value? diff --git a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt index 1fc7ad12a..0407ad0f9 100644 --- a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt +++ b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt @@ -9,7 +9,6 @@ import edu.stanford.spezi.core.utils.foundation.knowledgesource.DefaultProviding import edu.stanford.spezi.core.utils.foundation.knowledgesource.KnowledgeSource import edu.stanford.spezi.core.utils.foundation.knowledgesource.OptionalComputedKnowledgeSource import org.junit.Test -import java.util.UUID object TestAnchor : RepositoryAnchor @@ -63,8 +62,8 @@ data class ComputedTestDataClass(override val value: Int) : TestTypes { SharedRepository > { override val uuid = UUID() - override val storagePolicy: ComputedKnowledgeSourceStoragePolicy - = ComputedKnowledgeSourceStoragePolicy.AlwaysCompute + override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = + ComputedKnowledgeSourceStoragePolicy.AlwaysCompute override fun compute(repository: SharedRepository) = ComputedTestDataClass(computedValue) } @@ -75,8 +74,8 @@ data class ComputedTestDataClass(override val value: Int) : TestTypes { SharedRepository > { override val uuid = UUID() - override val storagePolicy: ComputedKnowledgeSourceStoragePolicy - = ComputedKnowledgeSourceStoragePolicy.Store + override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = + ComputedKnowledgeSourceStoragePolicy.Store override fun compute(repository: SharedRepository) = ComputedTestDataClass(computedValue) } @@ -93,8 +92,8 @@ data class OptionalComputedTestDataClass(override val value: Int) : TestTypes { SharedRepository > { override val uuid = UUID() - override val storagePolicy: ComputedKnowledgeSourceStoragePolicy - = ComputedKnowledgeSourceStoragePolicy.AlwaysCompute + override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = + ComputedKnowledgeSourceStoragePolicy.AlwaysCompute override fun compute(repository: SharedRepository): OptionalComputedTestDataClass? = optionalComputedValue?.let { OptionalComputedTestDataClass(it) } } @@ -105,8 +104,8 @@ data class OptionalComputedTestDataClass(override val value: Int) : TestTypes { SharedRepository > { override val uuid = UUID() - override val storagePolicy: ComputedKnowledgeSourceStoragePolicy - = ComputedKnowledgeSourceStoragePolicy.Store + override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = + ComputedKnowledgeSourceStoragePolicy.Store override fun compute(repository: SharedRepository): OptionalComputedTestDataClass? = optionalComputedValue?.let { OptionalComputedTestDataClass(it) } } @@ -265,5 +264,4 @@ class SharedRepositoryTest { // TODO: fun testComputedKnowledgeSourcePreferred() has not been copied from iOS due to accessing the // operator fun get will result in ambiguity compiler error, so this behavior would not be possible anyways - } From c260c111c12ff70d2aa94f1b76b988a3551ba6ea Mon Sep 17 00:00:00 2001 From: Paul Kraft Date: Fri, 8 Nov 2024 14:12:36 -0800 Subject: [PATCH 03/12] Use assertThat instead of assert --- .../spezi/core/utils/SharedRepositoryTest.kt | 61 +++++++++---------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt index 0407ad0f9..8719730c4 100644 --- a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt +++ b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt @@ -1,5 +1,6 @@ package edu.stanford.spezi.core.utils +import com.google.common.truth.Truth.assertThat import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor import edu.stanford.spezi.core.utils.foundation.SharedRepository import edu.stanford.spezi.core.utils.foundation.builtin.ValueRepository @@ -84,8 +85,6 @@ data class ComputedTestDataClass(override val value: Int) : TestTypes { data class OptionalComputedTestDataClass(override val value: Int) : TestTypes { companion object { - const val TRUE = true - val alwaysComputeKey = object : OptionalComputedKnowledgeSource< TestAnchor, OptionalComputedTestDataClass, @@ -123,9 +122,9 @@ class SharedRepositoryTest { repository[TestDataClass.key] = TestDataClass(3) for (value in repository) { - assert(value.anySource === TestDataClass.key) - assert(value.anyValue is TestDataClass) - assert((value.anyValue as? TestDataClass) == TestDataClass(3)) + assertThat(value.anySource).isSameInstanceAs(TestDataClass.key) + assertThat(value.anyValue is TestDataClass).isEqualTo(true) + assertThat(value.anyValue as? TestDataClass).isEqualTo(TestDataClass(3)) } } @@ -134,7 +133,7 @@ class SharedRepositoryTest { repository[TestDataClass.key, TestDataClass(35)].value = 23 val value = repository[TestDataClass.key] - assert(value?.value == 23) + assertThat(value?.value).isEqualTo(23) } @Test @@ -142,16 +141,16 @@ class SharedRepositoryTest { val testDataClass = TestDataClass(42) repository[TestDataClass.key] = testDataClass val contentOfDataClass = repository[TestDataClass.key] - assert(contentOfDataClass === testDataClass) + assertThat(contentOfDataClass).isEqualTo(testDataClass) val newTestDataClass = TestDataClass(24) repository[TestDataClass.key] = newTestDataClass val newContentOfDataClass = repository[TestDataClass.key] - assert(newContentOfDataClass == newTestDataClass) + assertThat(newContentOfDataClass).isEqualTo(newTestDataClass) repository[TestDataClass.key] = null val newerContentOfDataClass = repository[TestDataClass.key] - assert(newerContentOfDataClass == null) + assertThat(newerContentOfDataClass).isNull() } @Test @@ -159,23 +158,23 @@ class SharedRepositoryTest { val testDataClass = DefaultedTestDataClass(42) val defaultDataClass = repository[DefaultedTestDataClass.key] - assert(defaultDataClass == DefaultedTestDataClass(0)) + assertThat(defaultDataClass).isEqualTo(DefaultedTestDataClass(0)) // The cast is necessary, since it would otherwise not use the non-defaulted one val regularGet = repository[DefaultedTestDataClass.key as KnowledgeSource] ?: testDataClass - assert(regularGet == testDataClass) + assertThat(regularGet).isEqualTo(testDataClass) } @Test fun testContains() { val testDataClass = TestDataClass(42) - assert(!repository.contains(TestDataClass.key)) + assertThat(repository.contains(TestDataClass.key)).isFalse() repository[TestDataClass.key] = testDataClass - assert(repository.contains(TestDataClass.key)) + assertThat(repository.contains(TestDataClass.key)).isTrue() repository[TestDataClass.key] = null - assert(!repository.contains(TestDataClass.key)) + assertThat(!repository.contains(TestDataClass.key)).isFalse() } @Test @@ -186,8 +185,8 @@ class SharedRepositoryTest { repository[TestClass.key] = testClass val testTypes = repository.collect(allOf = TestTypes::class) - assert(testTypes.count() == 2) - assert(testTypes.all { it.value == 42 }) + assertThat(testTypes).hasSize(2) + assertThat(testTypes.all { it.value == 42 }).isTrue() } @Test @@ -198,8 +197,8 @@ class SharedRepositoryTest { val contentOfDataClass = repository[TestDataClass.key] contentOfDataClass?.value = 24 // This is different than on iOS - here, data classes use reference semantics! - assert(testDataClass.value == 24) - assert(contentOfDataClass?.value == 24) + assertThat(testDataClass.value).isEqualTo(24) + assertThat(contentOfDataClass?.value).isEqualTo(24) } @Test @@ -208,7 +207,7 @@ class SharedRepositoryTest { repository[KeyLike] = testClass val contentOfClass = repository[KeyLike] - assert(contentOfClass == testClass) + assertThat(contentOfClass).isEqualTo(testClass) } @Test @@ -216,16 +215,16 @@ class SharedRepositoryTest { val value = repository[ComputedTestDataClass.alwaysComputeKey] val optionalValue = repository[OptionalComputedTestDataClass.alwaysComputeKey] - assert(value.value == computedValue) - assert(optionalValue?.value == optionalComputedValue) + assertThat(value.value).isEqualTo(computedValue) + assertThat(optionalValue?.value).isEqualTo(optionalComputedValue) computedValue = 5 optionalComputedValue = 4 val newValue = repository[ComputedTestDataClass.alwaysComputeKey] val newOptionalValue = repository[OptionalComputedTestDataClass.alwaysComputeKey] - assert(newValue.value == computedValue) - assert(newOptionalValue?.value == optionalComputedValue) + assertThat(newValue.value).isEqualTo(computedValue) + assertThat(newOptionalValue?.value).isEqualTo(optionalComputedValue) } @Test @@ -233,15 +232,15 @@ class SharedRepositoryTest { val value = repository[ComputedTestDataClass.storeKey] val optionalValue = repository[OptionalComputedTestDataClass.storeKey] - assert(value.value == computedValue) - assert(optionalValue?.value == optionalComputedValue) + assertThat(value.value).isEqualTo(computedValue) + assertThat(optionalValue?.value).isEqualTo(optionalComputedValue) // get call bypasses the compute call, so tests if it's really stored val getValue = repository[ComputedTestDataClass.alwaysComputeKey] val getOptionalValue = repository[OptionalComputedTestDataClass.alwaysComputeKey] - assert(getValue.value == computedValue) - assert(getOptionalValue?.value == optionalComputedValue) // this is nil + assertThat(getValue.value).isEqualTo(computedValue) + assertThat(getOptionalValue?.value).isEqualTo(optionalComputedValue) // this is nil // make sure computed knowledge sources with `Store` policy are not re-computed computedValue = 5 @@ -250,16 +249,16 @@ class SharedRepositoryTest { val newValue = repository[ComputedTestDataClass.alwaysComputeKey] val newOptionalValue = repository[OptionalComputedTestDataClass.alwaysComputeKey] - assert(newValue.value == value.value) - assert(newOptionalValue?.value == optionalComputedValue) // never stored as it was nil + assertThat(newValue.value).isEqualTo(value.value) + assertThat(newOptionalValue?.value).isEqualTo(optionalComputedValue) // never stored as it was nil // last check if its really written now val writtenOptionalValue = repository[OptionalComputedTestDataClass.alwaysComputeKey] - assert(writtenOptionalValue?.value == optionalComputedValue) + assertThat(writtenOptionalValue?.value).isEqualTo(optionalComputedValue) // check again that it doesn't change optionalComputedValue = null - assert(repository[OptionalComputedTestDataClass.storeKey]?.value == 4) + assertThat(repository[OptionalComputedTestDataClass.storeKey]?.value).isEqualTo(4) } // TODO: fun testComputedKnowledgeSourcePreferred() has not been copied from iOS due to accessing the From 50e247be2280589bb32e50b4e5a2b31adebff21e Mon Sep 17 00:00:00 2001 From: Paul Kraft Date: Fri, 8 Nov 2024 14:29:35 -0800 Subject: [PATCH 04/12] fix tests --- .../edu/stanford/spezi/core/utils/SharedRepositoryTest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt index 8719730c4..dbb18d79f 100644 --- a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt +++ b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt @@ -174,7 +174,7 @@ class SharedRepositoryTest { assertThat(repository.contains(TestDataClass.key)).isTrue() repository[TestDataClass.key] = null - assertThat(!repository.contains(TestDataClass.key)).isFalse() + assertThat(repository.contains(TestDataClass.key)).isFalse() } @Test From 5c4ed7996a9194adecc70242277db926bd661635 Mon Sep 17 00:00:00 2001 From: Paul Kraft Date: Sat, 9 Nov 2024 15:40:27 -0800 Subject: [PATCH 05/12] Remove uuid property from KnowledgeSource --- .../utils/foundation/builtin/ValueRepository.kt | 8 ++++---- .../knowledgesource/ComputedKnowledgeSource.kt | 2 +- .../DefaultProvidingKnowledgeSource.kt | 2 +- .../knowledgesource/KnowledgeSource.kt | 9 +-------- .../OptionalComputedKnowledgeSource.kt | 2 +- .../SomeComputedKnowledgeSource.kt | 2 +- .../spezi/core/utils/SharedRepositoryTest.kt | 17 +++-------------- 7 files changed, 12 insertions(+), 30 deletions(-) diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt index 8f3eff2c3..516f59e09 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt @@ -7,13 +7,13 @@ import java.util.UUID import kotlin.reflect.KClass data class ValueRepository( - internal var storage: MutableMap = mutableMapOf(), + internal var storage: MutableMap = mutableMapOf(), ) : SharedRepository, Sequence { @Suppress("UNCHECKED_CAST") override operator fun get( source: KnowledgeSource, ): Value? { - return storage[source.uuid]?.let { it.anyValue as? Value } + return storage[System.identityHashCode(source)]?.let { it.anyValue as? Value } } override operator fun set( @@ -21,8 +21,8 @@ data class ValueRepository( value: Value?, ) { value?.let { - storage[source.uuid] = RepositoryValue(source, it) - } ?: storage.remove(source.uuid) + storage[System.identityHashCode(source)] = RepositoryValue(source, it) + } ?: storage.remove(System.identityHashCode(source)) } @Suppress("UNCHECKED_CAST") diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt index 97e1e5b62..c09e4d570 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt @@ -4,7 +4,7 @@ import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor interface ComputedKnowledgeSource< Anchor : RepositoryAnchor, - Value, + Value : Any, Repository, > : SomeComputedKnowledgeSource { diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/DefaultProvidingKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/DefaultProvidingKnowledgeSource.kt index 56cdf9b79..58715a0b9 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/DefaultProvidingKnowledgeSource.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/DefaultProvidingKnowledgeSource.kt @@ -2,7 +2,7 @@ package edu.stanford.spezi.core.utils.foundation.knowledgesource import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor -interface DefaultProvidingKnowledgeSource : +interface DefaultProvidingKnowledgeSource : KnowledgeSource { val defaultValue: Value } diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/KnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/KnowledgeSource.kt index 2b98c60f5..35dff4652 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/KnowledgeSource.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/KnowledgeSource.kt @@ -1,12 +1,5 @@ package edu.stanford.spezi.core.utils.foundation.knowledgesource import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor -import java.util.UUID -interface KnowledgeSource { - @Suppress("detekt:VariableMinLength") - val uuid: UUID - - fun isEqualTo(other: KnowledgeSource): Boolean = - uuid == other.uuid -} +interface KnowledgeSource diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt index 81e7c9f21..297d0518f 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt @@ -4,7 +4,7 @@ import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor interface OptionalComputedKnowledgeSource< Anchor : RepositoryAnchor, - Value, + Value : Any, Repository, > : SomeComputedKnowledgeSource { diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/SomeComputedKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/SomeComputedKnowledgeSource.kt index 80b228f63..4c9a8a8d3 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/SomeComputedKnowledgeSource.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/SomeComputedKnowledgeSource.kt @@ -7,6 +7,6 @@ sealed interface ComputedKnowledgeSourceStoragePolicy { data object Store : ComputedKnowledgeSourceStoragePolicy } -interface SomeComputedKnowledgeSource : KnowledgeSource { +interface SomeComputedKnowledgeSource : KnowledgeSource { val storagePolicy: ComputedKnowledgeSourceStoragePolicy } diff --git a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt index dbb18d79f..ad2c6a095 100644 --- a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt +++ b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt @@ -19,9 +19,7 @@ interface TestTypes { data class TestDataClass(override var value: Int) : TestTypes { companion object { - val key = object : KnowledgeSource { - override val uuid = UUID() - } + val key = object : KnowledgeSource {} } } @@ -36,20 +34,15 @@ class TestClass(override val value: Int) : TestTypes { } companion object { - val key = object : KnowledgeSource { - override val uuid = UUID() - } + val key = object : KnowledgeSource {} } } -object KeyLike : KnowledgeSource { - override val uuid = UUID() -} +object KeyLike : KnowledgeSource data class DefaultedTestDataClass(override val value: Int) : TestTypes { companion object { val key = object : DefaultProvidingKnowledgeSource { - override val uuid = UUID() override val defaultValue get() = DefaultedTestDataClass(0) } } @@ -62,7 +55,6 @@ data class ComputedTestDataClass(override val value: Int) : TestTypes { ComputedTestDataClass, SharedRepository > { - override val uuid = UUID() override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = ComputedKnowledgeSourceStoragePolicy.AlwaysCompute override fun compute(repository: SharedRepository) = @@ -74,7 +66,6 @@ data class ComputedTestDataClass(override val value: Int) : TestTypes { ComputedTestDataClass, SharedRepository > { - override val uuid = UUID() override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = ComputedKnowledgeSourceStoragePolicy.Store override fun compute(repository: SharedRepository) = @@ -90,7 +81,6 @@ data class OptionalComputedTestDataClass(override val value: Int) : TestTypes { OptionalComputedTestDataClass, SharedRepository > { - override val uuid = UUID() override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = ComputedKnowledgeSourceStoragePolicy.AlwaysCompute override fun compute(repository: SharedRepository): OptionalComputedTestDataClass? = @@ -102,7 +92,6 @@ data class OptionalComputedTestDataClass(override val value: Int) : TestTypes { OptionalComputedTestDataClass, SharedRepository > { - override val uuid = UUID() override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = ComputedKnowledgeSourceStoragePolicy.Store override fun compute(repository: SharedRepository): OptionalComputedTestDataClass? = From c4a543c18a8285a2a8be1edee1c725a27bffe4cb Mon Sep 17 00:00:00 2001 From: Paul Kraft Date: Sat, 9 Nov 2024 15:43:02 -0800 Subject: [PATCH 06/12] Readd uuid property --- .../knowledgesource/KnowledgeSource.kt | 9 ++++++++- .../spezi/core/utils/SharedRepositoryTest.kt | 17 ++++++++++++++--- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/KnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/KnowledgeSource.kt index 35dff4652..e01160fe4 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/KnowledgeSource.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/KnowledgeSource.kt @@ -1,5 +1,12 @@ package edu.stanford.spezi.core.utils.foundation.knowledgesource import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor +import java.util.UUID -interface KnowledgeSource +interface KnowledgeSource { + @Suppress("detekt:VariableMinLength") + val uuid: UUID + + fun isEqualTo(other: KnowledgeSource): Boolean = + uuid == other.uuid +} diff --git a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt index ad2c6a095..dbb18d79f 100644 --- a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt +++ b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt @@ -19,7 +19,9 @@ interface TestTypes { data class TestDataClass(override var value: Int) : TestTypes { companion object { - val key = object : KnowledgeSource {} + val key = object : KnowledgeSource { + override val uuid = UUID() + } } } @@ -34,15 +36,20 @@ class TestClass(override val value: Int) : TestTypes { } companion object { - val key = object : KnowledgeSource {} + val key = object : KnowledgeSource { + override val uuid = UUID() + } } } -object KeyLike : KnowledgeSource +object KeyLike : KnowledgeSource { + override val uuid = UUID() +} data class DefaultedTestDataClass(override val value: Int) : TestTypes { companion object { val key = object : DefaultProvidingKnowledgeSource { + override val uuid = UUID() override val defaultValue get() = DefaultedTestDataClass(0) } } @@ -55,6 +62,7 @@ data class ComputedTestDataClass(override val value: Int) : TestTypes { ComputedTestDataClass, SharedRepository > { + override val uuid = UUID() override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = ComputedKnowledgeSourceStoragePolicy.AlwaysCompute override fun compute(repository: SharedRepository) = @@ -66,6 +74,7 @@ data class ComputedTestDataClass(override val value: Int) : TestTypes { ComputedTestDataClass, SharedRepository > { + override val uuid = UUID() override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = ComputedKnowledgeSourceStoragePolicy.Store override fun compute(repository: SharedRepository) = @@ -81,6 +90,7 @@ data class OptionalComputedTestDataClass(override val value: Int) : TestTypes { OptionalComputedTestDataClass, SharedRepository > { + override val uuid = UUID() override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = ComputedKnowledgeSourceStoragePolicy.AlwaysCompute override fun compute(repository: SharedRepository): OptionalComputedTestDataClass? = @@ -92,6 +102,7 @@ data class OptionalComputedTestDataClass(override val value: Int) : TestTypes { OptionalComputedTestDataClass, SharedRepository > { + override val uuid = UUID() override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = ComputedKnowledgeSourceStoragePolicy.Store override fun compute(repository: SharedRepository): OptionalComputedTestDataClass? = From 0ac6186245adbd5259bb5ef243dd7631cdbd014f Mon Sep 17 00:00:00 2001 From: Paul Kraft Date: Sat, 9 Nov 2024 15:45:13 -0800 Subject: [PATCH 07/12] Undo change --- .../core/utils/foundation/builtin/ValueRepository.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt index 516f59e09..8f3eff2c3 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt @@ -7,13 +7,13 @@ import java.util.UUID import kotlin.reflect.KClass data class ValueRepository( - internal var storage: MutableMap = mutableMapOf(), + internal var storage: MutableMap = mutableMapOf(), ) : SharedRepository, Sequence { @Suppress("UNCHECKED_CAST") override operator fun get( source: KnowledgeSource, ): Value? { - return storage[System.identityHashCode(source)]?.let { it.anyValue as? Value } + return storage[source.uuid]?.let { it.anyValue as? Value } } override operator fun set( @@ -21,8 +21,8 @@ data class ValueRepository( value: Value?, ) { value?.let { - storage[System.identityHashCode(source)] = RepositoryValue(source, it) - } ?: storage.remove(System.identityHashCode(source)) + storage[source.uuid] = RepositoryValue(source, it) + } ?: storage.remove(source.uuid) } @Suppress("UNCHECKED_CAST") From 0ecb9dc33e679d7a61725cb4ed932df709b011fe Mon Sep 17 00:00:00 2001 From: Paul Kraft Date: Sun, 10 Nov 2024 10:57:54 -0800 Subject: [PATCH 08/12] Adapt according to feedback --- .../{SharedRepository.kt => Repository.kt} | 26 ++-------- .../foundation/builtin/RepositoryValue.kt | 17 ------ .../foundation/builtin/ValueRepository.kt | 25 ++++----- .../ComputedKnowledgeSource.kt | 10 ++-- .../DefaultProvidingKnowledgeSource.kt | 3 +- .../knowledgesource/KnowledgeSource.kt | 9 +--- .../OptionalComputedKnowledgeSource.kt | 10 ++-- ...redRepositoryTest.kt => RepositoryTest.kt} | 52 +++++-------------- 8 files changed, 37 insertions(+), 115 deletions(-) rename core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/{SharedRepository.kt => Repository.kt} (81%) delete mode 100644 core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/RepositoryValue.kt rename core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/{SharedRepositoryTest.kt => RepositoryTest.kt} (85%) diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/Repository.kt similarity index 81% rename from core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt rename to core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/Repository.kt index 1e644eb42..8e42dc69a 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/Repository.kt @@ -8,7 +8,7 @@ import edu.stanford.spezi.core.utils.foundation.knowledgesource.OptionalComputed import kotlin.reflect.KClass @Suppress("detekt:TooManyFunctions") -interface SharedRepository { +interface Repository { operator fun get(source: KnowledgeSource): Value? operator fun set(source: KnowledgeSource, value: Value?) @@ -32,19 +32,11 @@ interface SharedRepository { } operator fun get( - source: ComputedKnowledgeSource< - Anchor, - Value, - in SharedRepository, - >, + source: ComputedKnowledgeSource, ): Value = getOrComputed(source) fun getOrComputed( - source: ComputedKnowledgeSource< - Anchor, - Value, - in SharedRepository, - >, + source: ComputedKnowledgeSource, ): Value { return get( source as KnowledgeSource, @@ -61,19 +53,11 @@ interface SharedRepository { } operator fun get( - source: OptionalComputedKnowledgeSource< - Anchor, - Value, - in SharedRepository, - >, + source: OptionalComputedKnowledgeSource, ): Value? = getOrOptionalComputed(source) fun getOrOptionalComputed( - source: OptionalComputedKnowledgeSource< - Anchor, - Value, - in SharedRepository, - >, + source: OptionalComputedKnowledgeSource, ): Value? { return get( source as KnowledgeSource, diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/RepositoryValue.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/RepositoryValue.kt deleted file mode 100644 index 2e9a9fbd4..000000000 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/RepositoryValue.kt +++ /dev/null @@ -1,17 +0,0 @@ -package edu.stanford.spezi.core.utils.foundation.builtin - -import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor -import edu.stanford.spezi.core.utils.foundation.knowledgesource.KnowledgeSource - -interface AnyRepositoryValue { - val anySource: KnowledgeSource<*, *> - val anyValue: Any -} - -data class RepositoryValue( - val source: KnowledgeSource, - val value: Value, -) : AnyRepositoryValue { - override val anySource: KnowledgeSource<*, *> get() = source - override val anyValue: Any get() = value -} diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt index 8f3eff2c3..ec97c9d80 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt @@ -1,36 +1,31 @@ package edu.stanford.spezi.core.utils.foundation.builtin +import edu.stanford.spezi.core.utils.foundation.Repository import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor -import edu.stanford.spezi.core.utils.foundation.SharedRepository import edu.stanford.spezi.core.utils.foundation.knowledgesource.KnowledgeSource -import java.util.UUID +import java.util.concurrent.ConcurrentHashMap import kotlin.reflect.KClass data class ValueRepository( - internal var storage: MutableMap = mutableMapOf(), -) : SharedRepository, Sequence { + internal var storage: ConcurrentHashMap, Any> = ConcurrentHashMap(), +) : Repository, Sequence, Any>> { @Suppress("UNCHECKED_CAST") override operator fun get( source: KnowledgeSource, - ): Value? { - return storage[source.uuid]?.let { it.anyValue as? Value } - } + ): Value? = storage[source] as? Value override operator fun set( source: KnowledgeSource, value: Value?, ) { value?.let { - storage[source.uuid] = RepositoryValue(source, it) - } ?: storage.remove(source.uuid) + storage[source] = it + } ?: storage.remove(source) } @Suppress("UNCHECKED_CAST") - override fun collect(allOf: KClass): List { - return storage.values.mapNotNull { it.anyValue as? Value } - } + override fun collect(allOf: KClass) = + storage.values.mapNotNull { it as? Value } - override fun iterator(): Iterator { - return storage.values.iterator() - } + override fun iterator() = storage.iterator() } diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt index c09e4d570..c4e39edf9 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt @@ -1,12 +1,8 @@ package edu.stanford.spezi.core.utils.foundation.knowledgesource +import edu.stanford.spezi.core.utils.foundation.Repository import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor -interface ComputedKnowledgeSource< - Anchor : RepositoryAnchor, - Value : Any, - Repository, - > : SomeComputedKnowledgeSource { - - fun compute(repository: Repository): Value +interface ComputedKnowledgeSource : SomeComputedKnowledgeSource { + fun compute(repository: Repository): Value } diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/DefaultProvidingKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/DefaultProvidingKnowledgeSource.kt index 58715a0b9..7ff34b37f 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/DefaultProvidingKnowledgeSource.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/DefaultProvidingKnowledgeSource.kt @@ -2,7 +2,6 @@ package edu.stanford.spezi.core.utils.foundation.knowledgesource import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor -interface DefaultProvidingKnowledgeSource : - KnowledgeSource { +interface DefaultProvidingKnowledgeSource : KnowledgeSource { val defaultValue: Value } diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/KnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/KnowledgeSource.kt index e01160fe4..35dff4652 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/KnowledgeSource.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/KnowledgeSource.kt @@ -1,12 +1,5 @@ package edu.stanford.spezi.core.utils.foundation.knowledgesource import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor -import java.util.UUID -interface KnowledgeSource { - @Suppress("detekt:VariableMinLength") - val uuid: UUID - - fun isEqualTo(other: KnowledgeSource): Boolean = - uuid == other.uuid -} +interface KnowledgeSource diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt index 297d0518f..056432721 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt @@ -1,12 +1,8 @@ package edu.stanford.spezi.core.utils.foundation.knowledgesource +import edu.stanford.spezi.core.utils.foundation.Repository import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor -interface OptionalComputedKnowledgeSource< - Anchor : RepositoryAnchor, - Value : Any, - Repository, - > : SomeComputedKnowledgeSource { - - fun compute(repository: Repository): Value? +interface OptionalComputedKnowledgeSource : SomeComputedKnowledgeSource { + fun compute(repository: Repository): Value? } diff --git a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/RepositoryTest.kt similarity index 85% rename from core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt rename to core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/RepositoryTest.kt index dbb18d79f..0df151118 100644 --- a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt +++ b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/RepositoryTest.kt @@ -1,8 +1,8 @@ package edu.stanford.spezi.core.utils import com.google.common.truth.Truth.assertThat +import edu.stanford.spezi.core.utils.foundation.Repository import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor -import edu.stanford.spezi.core.utils.foundation.SharedRepository import edu.stanford.spezi.core.utils.foundation.builtin.ValueRepository import edu.stanford.spezi.core.utils.foundation.knowledgesource.ComputedKnowledgeSource import edu.stanford.spezi.core.utils.foundation.knowledgesource.ComputedKnowledgeSourceStoragePolicy @@ -19,9 +19,7 @@ interface TestTypes { data class TestDataClass(override var value: Int) : TestTypes { companion object { - val key = object : KnowledgeSource { - override val uuid = UUID() - } + val key = object : KnowledgeSource {} } } @@ -36,20 +34,15 @@ class TestClass(override val value: Int) : TestTypes { } companion object { - val key = object : KnowledgeSource { - override val uuid = UUID() - } + val key = object : KnowledgeSource {} } } -object KeyLike : KnowledgeSource { - override val uuid = UUID() -} +object KeyLike : KnowledgeSource data class DefaultedTestDataClass(override val value: Int) : TestTypes { companion object { val key = object : DefaultProvidingKnowledgeSource { - override val uuid = UUID() override val defaultValue get() = DefaultedTestDataClass(0) } } @@ -60,24 +53,17 @@ data class ComputedTestDataClass(override val value: Int) : TestTypes { val alwaysComputeKey = object : ComputedKnowledgeSource< TestAnchor, ComputedTestDataClass, - SharedRepository > { - override val uuid = UUID() override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = ComputedKnowledgeSourceStoragePolicy.AlwaysCompute - override fun compute(repository: SharedRepository) = + override fun compute(repository: Repository) = ComputedTestDataClass(computedValue) } - val storeKey = object : ComputedKnowledgeSource< - TestAnchor, - ComputedTestDataClass, - SharedRepository - > { - override val uuid = UUID() + val storeKey = object : ComputedKnowledgeSource { override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = ComputedKnowledgeSourceStoragePolicy.Store - override fun compute(repository: SharedRepository) = + override fun compute(repository: Repository) = ComputedTestDataClass(computedValue) } } @@ -85,27 +71,17 @@ data class ComputedTestDataClass(override val value: Int) : TestTypes { data class OptionalComputedTestDataClass(override val value: Int) : TestTypes { companion object { - val alwaysComputeKey = object : OptionalComputedKnowledgeSource< - TestAnchor, - OptionalComputedTestDataClass, - SharedRepository - > { - override val uuid = UUID() + val alwaysComputeKey = object : OptionalComputedKnowledgeSource { override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = ComputedKnowledgeSourceStoragePolicy.AlwaysCompute - override fun compute(repository: SharedRepository): OptionalComputedTestDataClass? = + override fun compute(repository: Repository): OptionalComputedTestDataClass? = optionalComputedValue?.let { OptionalComputedTestDataClass(it) } } - val storeKey = object : OptionalComputedKnowledgeSource< - TestAnchor, - OptionalComputedTestDataClass, - SharedRepository - > { - override val uuid = UUID() + val storeKey = object : OptionalComputedKnowledgeSource { override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = ComputedKnowledgeSourceStoragePolicy.Store - override fun compute(repository: SharedRepository): OptionalComputedTestDataClass? = + override fun compute(repository: Repository): OptionalComputedTestDataClass? = optionalComputedValue?.let { OptionalComputedTestDataClass(it) } } } @@ -122,9 +98,9 @@ class SharedRepositoryTest { repository[TestDataClass.key] = TestDataClass(3) for (value in repository) { - assertThat(value.anySource).isSameInstanceAs(TestDataClass.key) - assertThat(value.anyValue is TestDataClass).isEqualTo(true) - assertThat(value.anyValue as? TestDataClass).isEqualTo(TestDataClass(3)) + assertThat(value.key).isSameInstanceAs(TestDataClass.key) + assertThat(value.value is TestDataClass).isEqualTo(true) + assertThat(value.value as? TestDataClass).isEqualTo(TestDataClass(3)) } } From f480ed258b97826cceec734288747cac09f93ac7 Mon Sep 17 00:00:00 2001 From: Paul Kraft Date: Sun, 10 Nov 2024 11:11:49 -0800 Subject: [PATCH 09/12] Adaptions --- .../foundation/{Repository.kt => SharedRepository.kt} | 2 +- .../core/utils/foundation/builtin/ValueRepository.kt | 4 ++-- .../knowledgesource/ComputedKnowledgeSource.kt | 4 ++-- .../knowledgesource/OptionalComputedKnowledgeSource.kt | 10 +++++++--- .../edu/stanford/spezi/core/utils/RepositoryTest.kt | 10 +++++----- 5 files changed, 17 insertions(+), 13 deletions(-) rename core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/{Repository.kt => SharedRepository.kt} (98%) diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/Repository.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt similarity index 98% rename from core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/Repository.kt rename to core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt index 8e42dc69a..5ade5dddd 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/Repository.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt @@ -8,7 +8,7 @@ import edu.stanford.spezi.core.utils.foundation.knowledgesource.OptionalComputed import kotlin.reflect.KClass @Suppress("detekt:TooManyFunctions") -interface Repository { +interface SharedRepository { operator fun get(source: KnowledgeSource): Value? operator fun set(source: KnowledgeSource, value: Value?) diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt index ec97c9d80..8cfa9bb9b 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt @@ -1,14 +1,14 @@ package edu.stanford.spezi.core.utils.foundation.builtin -import edu.stanford.spezi.core.utils.foundation.Repository import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor +import edu.stanford.spezi.core.utils.foundation.SharedRepository import edu.stanford.spezi.core.utils.foundation.knowledgesource.KnowledgeSource import java.util.concurrent.ConcurrentHashMap import kotlin.reflect.KClass data class ValueRepository( internal var storage: ConcurrentHashMap, Any> = ConcurrentHashMap(), -) : Repository, Sequence, Any>> { +) : SharedRepository, Sequence, Any>> { @Suppress("UNCHECKED_CAST") override operator fun get( source: KnowledgeSource, diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt index c4e39edf9..6cb907c1a 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt @@ -1,8 +1,8 @@ package edu.stanford.spezi.core.utils.foundation.knowledgesource -import edu.stanford.spezi.core.utils.foundation.Repository +import edu.stanford.spezi.core.utils.foundation.SharedRepository import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor interface ComputedKnowledgeSource : SomeComputedKnowledgeSource { - fun compute(repository: Repository): Value + fun compute(repository: SharedRepository): Value } diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt index 056432721..bb044181a 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt @@ -1,8 +1,12 @@ package edu.stanford.spezi.core.utils.foundation.knowledgesource -import edu.stanford.spezi.core.utils.foundation.Repository import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor +import edu.stanford.spezi.core.utils.foundation.SharedRepository -interface OptionalComputedKnowledgeSource : SomeComputedKnowledgeSource { - fun compute(repository: Repository): Value? +interface OptionalComputedKnowledgeSource< + Anchor : RepositoryAnchor, + Value : Any + > : SomeComputedKnowledgeSource { + + fun compute(repository: SharedRepository): Value? } diff --git a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/RepositoryTest.kt b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/RepositoryTest.kt index 0df151118..07b8cccad 100644 --- a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/RepositoryTest.kt +++ b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/RepositoryTest.kt @@ -1,8 +1,8 @@ package edu.stanford.spezi.core.utils import com.google.common.truth.Truth.assertThat -import edu.stanford.spezi.core.utils.foundation.Repository import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor +import edu.stanford.spezi.core.utils.foundation.SharedRepository import edu.stanford.spezi.core.utils.foundation.builtin.ValueRepository import edu.stanford.spezi.core.utils.foundation.knowledgesource.ComputedKnowledgeSource import edu.stanford.spezi.core.utils.foundation.knowledgesource.ComputedKnowledgeSourceStoragePolicy @@ -56,14 +56,14 @@ data class ComputedTestDataClass(override val value: Int) : TestTypes { > { override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = ComputedKnowledgeSourceStoragePolicy.AlwaysCompute - override fun compute(repository: Repository) = + override fun compute(repository: SharedRepository) = ComputedTestDataClass(computedValue) } val storeKey = object : ComputedKnowledgeSource { override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = ComputedKnowledgeSourceStoragePolicy.Store - override fun compute(repository: Repository) = + override fun compute(repository: SharedRepository) = ComputedTestDataClass(computedValue) } } @@ -74,14 +74,14 @@ data class OptionalComputedTestDataClass(override val value: Int) : TestTypes { val alwaysComputeKey = object : OptionalComputedKnowledgeSource { override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = ComputedKnowledgeSourceStoragePolicy.AlwaysCompute - override fun compute(repository: Repository): OptionalComputedTestDataClass? = + override fun compute(repository: SharedRepository): OptionalComputedTestDataClass? = optionalComputedValue?.let { OptionalComputedTestDataClass(it) } } val storeKey = object : OptionalComputedKnowledgeSource { override val storagePolicy: ComputedKnowledgeSourceStoragePolicy = ComputedKnowledgeSourceStoragePolicy.Store - override fun compute(repository: Repository): OptionalComputedTestDataClass? = + override fun compute(repository: SharedRepository): OptionalComputedTestDataClass? = optionalComputedValue?.let { OptionalComputedTestDataClass(it) } } } From 0c7272d91345839d01644a41e7c5fdfbf43de05f Mon Sep 17 00:00:00 2001 From: Paul Kraft Date: Sun, 10 Nov 2024 11:17:08 -0800 Subject: [PATCH 10/12] Update --- .../utils/foundation/knowledgesource/ComputedKnowledgeSource.kt | 2 +- .../knowledgesource/OptionalComputedKnowledgeSource.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt index 6cb907c1a..7f4141bdf 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/ComputedKnowledgeSource.kt @@ -1,7 +1,7 @@ package edu.stanford.spezi.core.utils.foundation.knowledgesource -import edu.stanford.spezi.core.utils.foundation.SharedRepository import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor +import edu.stanford.spezi.core.utils.foundation.SharedRepository interface ComputedKnowledgeSource : SomeComputedKnowledgeSource { fun compute(repository: SharedRepository): Value diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt index bb044181a..e7569d47d 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/knowledgesource/OptionalComputedKnowledgeSource.kt @@ -5,7 +5,7 @@ import edu.stanford.spezi.core.utils.foundation.SharedRepository interface OptionalComputedKnowledgeSource< Anchor : RepositoryAnchor, - Value : Any + Value : Any, > : SomeComputedKnowledgeSource { fun compute(repository: SharedRepository): Value? From 35aa1b4ba24f8c58106449e55be7646f9d798080 Mon Sep 17 00:00:00 2001 From: Paul Kraft Date: Sun, 10 Nov 2024 12:01:42 -0800 Subject: [PATCH 11/12] adaptions --- .../spezi/core/utils/foundation/SharedRepository.kt | 7 ------- .../spezi/core/utils/foundation/builtin/ValueRepository.kt | 3 +-- .../utils/{RepositoryTest.kt => SharedRepositoryTest.kt} | 0 3 files changed, 1 insertion(+), 9 deletions(-) rename core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/{RepositoryTest.kt => SharedRepositoryTest.kt} (100%) diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt index 5ade5dddd..71b92fd11 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/SharedRepository.kt @@ -12,13 +12,6 @@ interface SharedRepository { operator fun get(source: KnowledgeSource): Value? operator fun set(source: KnowledgeSource, value: Value?) - operator fun get(source: KnowledgeSource, default: Value): Value = - this[source] ?: default.also { this[source] = it } - - operator fun set(source: KnowledgeSource, default: Value, value: Value) { - this[source] = value - } - operator fun get( source: DefaultProvidingKnowledgeSource, ): Value = getOrDefault(source) diff --git a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt index 8cfa9bb9b..9c1bb6f00 100644 --- a/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt +++ b/core/utils/src/main/kotlin/edu/stanford/spezi/core/utils/foundation/builtin/ValueRepository.kt @@ -23,9 +23,8 @@ data class ValueRepository( } ?: storage.remove(source) } - @Suppress("UNCHECKED_CAST") override fun collect(allOf: KClass) = - storage.values.mapNotNull { it as? Value } + storage.values.filterIsInstance(allOf.java) override fun iterator() = storage.iterator() } diff --git a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/RepositoryTest.kt b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt similarity index 100% rename from core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/RepositoryTest.kt rename to core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt From 3f4c446cb0e1371028d24f532f29c97ed864dbc8 Mon Sep 17 00:00:00 2001 From: Paul Kraft Date: Sun, 10 Nov 2024 12:14:44 -0800 Subject: [PATCH 12/12] fix test --- .../edu/stanford/spezi/core/utils/SharedRepositoryTest.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt index 07b8cccad..3a4a4b126 100644 --- a/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt +++ b/core/utils/src/test/kotlin/edu/stanford/spezi/core/utils/SharedRepositoryTest.kt @@ -106,7 +106,11 @@ class SharedRepositoryTest { @Test fun testDefaultSubscript() { - repository[TestDataClass.key, TestDataClass(35)].value = 23 + // This test is mostly just kept in here to showcase how the access is different on Android + // due to data classes having reference semantics. + val initialValue = repository[TestDataClass.key] ?: TestDataClass(35) + initialValue.value = 23 + repository[TestDataClass.key] = initialValue val value = repository[TestDataClass.key] assertThat(value?.value).isEqualTo(23)