aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/moe/nea/ledger/utils/DI.kt
diff options
context:
space:
mode:
authorLinnea Gräf <nea@nea.moe>2024-12-06 19:27:07 +0100
committerLinnea Gräf <nea@nea.moe>2024-12-06 19:28:23 +0100
commitf7507f384459b57460af899bf9ceae4f52f1ea21 (patch)
tree410d70c0a35de852278b03ac9243080d7e0a0490 /src/main/kotlin/moe/nea/ledger/utils/DI.kt
parent2c9132d0c755964800b710ce43c8feebd44f1299 (diff)
downloadLocalTransactionLedger-f7507f384459b57460af899bf9ceae4f52f1ea21.tar.gz
LocalTransactionLedger-f7507f384459b57460af899bf9ceae4f52f1ea21.tar.bz2
LocalTransactionLedger-f7507f384459b57460af899bf9ceae4f52f1ea21.zip
refactor: Add DI and packages
Diffstat (limited to 'src/main/kotlin/moe/nea/ledger/utils/DI.kt')
-rw-r--r--src/main/kotlin/moe/nea/ledger/utils/DI.kt63
1 files changed, 63 insertions, 0 deletions
diff --git a/src/main/kotlin/moe/nea/ledger/utils/DI.kt b/src/main/kotlin/moe/nea/ledger/utils/DI.kt
new file mode 100644
index 0000000..1114127
--- /dev/null
+++ b/src/main/kotlin/moe/nea/ledger/utils/DI.kt
@@ -0,0 +1,63 @@
+package moe.nea.ledger.utils
+
+import java.lang.reflect.AnnotatedElement
+import java.util.Collections
+import java.util.Stack
+
+@Suppress("UNCHECKED_CAST")
+class DI {
+ private fun <T : Any, C> internalProvide(type: Class<T>, element: AnnotatedElement? = null): T {
+ val provider = providers[type] as BaseDIProvider<T, C>
+ val context = if (element == null) provider.createEmptyContext() else provider.createContext(element)
+ val key = Pair(type, context)
+ val existingValue = values[key]
+ if (existingValue != null) return existingValue as T
+ if (type in injectionStack) {
+ error("Found injection cycle: ${injectionStack.joinToString(" -> ")} -> $type")
+ }
+ injectionStack.push(type)
+ val value = try {
+ provider.provideWithContext(this, context)
+ } catch (ex: Exception) {
+ throw RuntimeException("Could not create instance for type $type", ex)
+ }
+ val cycleCheckCookie = injectionStack.pop()
+ require(cycleCheckCookie == type) { "Unbalanced stack cookie: $cycleCheckCookie != $type" }
+ values[key] = value
+ return value
+ }
+
+ fun <T : Any> provide(type: Class<T>, element: AnnotatedElement? = null): T {
+ return internalProvide<T, Any>(type, element)
+ }
+
+ fun <T : Any> register(type: Class<T>, provider: BaseDIProvider<T, *>) {
+ providers[type] = provider
+ }
+
+ fun registerInjectableClasses(vararg type: Class<*>) {
+ type.forEach { internalRegisterInjectableClass(it) }
+ }
+
+ private fun <T : Any> internalRegisterInjectableClass(type: Class<T>) {
+ register(type, DIProvider.fromInjectableClass(type))
+ }
+
+ fun instantiateAll() {
+ providers.keys.forEach {
+ provide(it, null)
+ }
+ }
+
+ fun getAllInstances(): Collection<Any> =
+ Collections.unmodifiableCollection(values.values)
+
+ fun <T : Any> registerSingleton(value: T) {
+ register(value.javaClass, DIProvider.singeleton(value))
+ }
+
+ private val injectionStack: Stack<Class<*>> = Stack()
+ private val values = mutableMapOf<Pair<Class<*>, *>, Any>()
+ private val providers = mutableMapOf<Class<*>, BaseDIProvider<*, *>>()
+
+} \ No newline at end of file