Skip to content

Commit

Permalink
SpeziFoundation (#139)
Browse files Browse the repository at this point in the history
# SpeziFoundation

## ♻️ Current situation & Problem
*Link any open issues or pull requests (PRs) related to this PR. Please
ensure that all non-trivial PRs are first tracked and discussed in an
existing GitHub issue or discussion.*


## ⚙️ Release Notes 
*Add a bullet point list summary of the feature and possible migration
guides if this is a breaking change so this section can be added to the
release notes.*
*Include code snippets that provide examples of the feature implemented
or links to the documentation if it appends or changes the public
interface.*


## 📚 Documentation
*Please ensure that you properly document any additions in conformance
to [Spezi Documentation
Guide](https://github.com/StanfordSpezi/.github/blob/main/DOCUMENTATIONGUIDE.md).*
*You can use this section to describe your solution, but we encourage
contributors to document your reasoning and changes using in-line
documentation.*


## ✅ Testing
*Please ensure that the PR meets the testing requirements set by CodeCov
and that new functionality is appropriately tested.*
*This section describes important information about the tests and why
some elements might not be testable.*


## 📝 Code of Conduct & Contributing Guidelines 

By submitting creating this pull request, you agree to follow our [Code
of
Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md):
- [x] I agree to follow the [Code of
Conduct](https://github.com/StanfordSpezi/.github/blob/main/CODE_OF_CONDUCT.md)
and [Contributing
Guidelines](https://github.com/StanfordSpezi/.github/blob/main/CONTRIBUTING.md).
  • Loading branch information
pauljohanneskraft authored Nov 10, 2024
1 parent 5009495 commit 11ae70a
Show file tree
Hide file tree
Showing 9 changed files with 397 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package edu.stanford.spezi.core.utils.foundation

interface RepositoryAnchor
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
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<Anchor : RepositoryAnchor> {
operator fun <Value : Any> get(source: KnowledgeSource<Anchor, Value>): Value?
operator fun <Value : Any> set(source: KnowledgeSource<Anchor, Value>, value: Value?)

operator fun <Value : Any> get(
source: DefaultProvidingKnowledgeSource<Anchor, Value>,
): Value = getOrDefault(source)

fun <Value : Any> getOrDefault(
source: DefaultProvidingKnowledgeSource<Anchor, Value>,
): Value {
return get(
source as KnowledgeSource<Anchor, Value>,
) ?: source.defaultValue
}

operator fun <Value : Any> get(
source: ComputedKnowledgeSource<Anchor, Value>,
): Value = getOrComputed(source)

fun <Value : Any> getOrComputed(
source: ComputedKnowledgeSource<Anchor, Value>,
): Value {
return get(
source as KnowledgeSource<Anchor, Value>,
) ?: when (source.storagePolicy) {
is ComputedKnowledgeSourceStoragePolicy.AlwaysCompute -> {
source.compute(this)
}
is ComputedKnowledgeSourceStoragePolicy.Store -> {
val value = source.compute(this)
this[source] = value
value
}
}
}

operator fun <Value : Any> get(
source: OptionalComputedKnowledgeSource<Anchor, Value>,
): Value? = getOrOptionalComputed(source)

fun <Value : Any> getOrOptionalComputed(
source: OptionalComputedKnowledgeSource<Anchor, Value>,
): Value? {
return get(
source as KnowledgeSource<Anchor, Value>,
) ?: when (source.storagePolicy) {
ComputedKnowledgeSourceStoragePolicy.AlwaysCompute -> {
source.compute(this)
}
ComputedKnowledgeSourceStoragePolicy.Store -> {
val value = source.compute(this)
this[source] = value
value
}
}
}

fun <Value : Any> collect(allOf: KClass<Value>): List<Value>

fun <Value : Any> contains(source: KnowledgeSource<Anchor, Value>): Boolean {
return get(source) != null
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
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.concurrent.ConcurrentHashMap
import kotlin.reflect.KClass

data class ValueRepository<Anchor : RepositoryAnchor>(
internal var storage: ConcurrentHashMap<KnowledgeSource<Anchor, *>, Any> = ConcurrentHashMap(),
) : SharedRepository<Anchor>, Sequence<Map.Entry<KnowledgeSource<Anchor, *>, Any>> {
@Suppress("UNCHECKED_CAST")
override operator fun <Value : Any> get(
source: KnowledgeSource<Anchor, Value>,
): Value? = storage[source] as? Value

override operator fun <Value : Any> set(
source: KnowledgeSource<Anchor, Value>,
value: Value?,
) {
value?.let {
storage[source] = it
} ?: storage.remove(source)
}

override fun <Value : Any> collect(allOf: KClass<Value>) =
storage.values.filterIsInstance(allOf.java)

override fun iterator() = storage.iterator()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package edu.stanford.spezi.core.utils.foundation.knowledgesource

import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor
import edu.stanford.spezi.core.utils.foundation.SharedRepository

interface ComputedKnowledgeSource<Anchor : RepositoryAnchor, Value : Any> : SomeComputedKnowledgeSource<Anchor, Value> {
fun compute(repository: SharedRepository<Anchor>): Value
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package edu.stanford.spezi.core.utils.foundation.knowledgesource

import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor

interface DefaultProvidingKnowledgeSource<Anchor : RepositoryAnchor, Value : Any> : KnowledgeSource<Anchor, Value> {
val defaultValue: Value
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package edu.stanford.spezi.core.utils.foundation.knowledgesource

import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor

interface KnowledgeSource<Anchor : RepositoryAnchor, Value : Any>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package edu.stanford.spezi.core.utils.foundation.knowledgesource

import edu.stanford.spezi.core.utils.foundation.RepositoryAnchor
import edu.stanford.spezi.core.utils.foundation.SharedRepository

interface OptionalComputedKnowledgeSource<
Anchor : RepositoryAnchor,
Value : Any,
> : SomeComputedKnowledgeSource<Anchor, Value> {

fun compute(repository: SharedRepository<Anchor>): Value?
}
Original file line number Diff line number Diff line change
@@ -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<Anchor : RepositoryAnchor, Value : Any> : KnowledgeSource<Anchor, Value> {
val storagePolicy: ComputedKnowledgeSourceStoragePolicy
}
Loading

0 comments on commit 11ae70a

Please sign in to comment.