K2: Add ability identify DI components by string key instead of KClass

It allows having several the same typed-component in the container
This commit is contained in:
Denis.Zharkov
2023-01-04 11:14:15 +01:00
committed by Space Team
parent 58c1b5dd1f
commit dab50daf56
4 changed files with 37 additions and 18 deletions
@@ -24,6 +24,10 @@ abstract class FirSession @PrivateSessionConstructor constructor(
return generateAccessor(T::class)
}
inline fun <reified T : FirSessionComponent> sessionComponentAccessor(id: String): ArrayMapAccessor<FirSessionComponent, FirSessionComponent, T> {
return generateAccessor(id)
}
inline fun <reified T : FirSessionComponent> nullableSessionComponentAccessor(): NullableArrayMapAccessor<FirSessionComponent, FirSessionComponent, T> {
return generateNullableAccessor(T::class)
}
@@ -38,6 +42,11 @@ abstract class FirSession @PrivateSessionConstructor constructor(
registerComponent(tClass, value)
}
@SessionConfiguration
fun register(keyQualifiedName: String, value: FirSessionComponent) {
registerComponent(keyQualifiedName, value)
}
override fun toString(): String {
val moduleData = nullableModuleData ?: return "Libraries session"
return "Source session for module ${moduleData.name}"
@@ -19,7 +19,6 @@ abstract class AbstractArrayMapOwner<K : Any, V : Any> : Iterable<V> {
protected abstract val typeRegistry: TypeRegistry<K, V>
abstract class AbstractArrayMapAccessor<K : Any, V : Any, T : V>(
protected val key: KClass<out K>,
protected val id: Int
) {
protected fun extractValue(thisRef: AbstractArrayMapOwner<K, V>): T? {
@@ -28,7 +27,11 @@ abstract class AbstractArrayMapOwner<K : Any, V : Any> : Iterable<V> {
}
}
protected abstract fun registerComponent(tClass: KClass<out K>, value: V)
protected abstract fun registerComponent(keyQualifiedName: String, value: V)
protected fun registerComponent(tClass: KClass<out K>, value: V) {
registerComponent(tClass.qualifiedName!!, value)
}
final override fun iterator(): Iterator<V> = arrayMap.iterator()
@@ -40,21 +43,20 @@ abstract class AbstractArrayMapOwner<K : Any, V : Any> : Iterable<V> {
}
class ArrayMapAccessor<K : Any, V : Any, T : V>(
key: KClass<out K>,
private val keyQualifiedName: String,
id: Int,
val default: T? = null
) : AbstractArrayMapOwner.AbstractArrayMapAccessor<K, V, T>(key, id), ReadOnlyProperty<AbstractArrayMapOwner<K, V>, V> {
) : AbstractArrayMapOwner.AbstractArrayMapAccessor<K, V, T>(id), ReadOnlyProperty<AbstractArrayMapOwner<K, V>, V> {
override fun getValue(thisRef: AbstractArrayMapOwner<K, V>, property: KProperty<*>): T {
return extractValue(thisRef)
?: default
?: error("No '$key'($id) in array owner: $thisRef")
?: error("No '$keyQualifiedName'($id) in array owner: $thisRef")
}
}
class NullableArrayMapAccessor<K : Any, V : Any, T : V>(
key: KClass<out K>,
id: Int
) : AbstractArrayMapOwner.AbstractArrayMapAccessor<K, V, T>(key, id), ReadOnlyProperty<AbstractArrayMapOwner<K, V>, V?> {
) : AbstractArrayMapOwner.AbstractArrayMapAccessor<K, V, T>(id), ReadOnlyProperty<AbstractArrayMapOwner<K, V>, V?> {
override fun getValue(thisRef: AbstractArrayMapOwner<K, V>, property: KProperty<*>): T? {
return extractValue(thisRef)
}
@@ -65,19 +67,27 @@ abstract class TypeRegistry<K : Any, V : Any> {
private val idCounter = AtomicInteger(0)
fun <T : V, KK : K> generateAccessor(kClass: KClass<KK>, default: T? = null): ArrayMapAccessor<K, V, T> {
return ArrayMapAccessor(kClass, getId(kClass), default)
return ArrayMapAccessor(kClass.qualifiedName!!, getId(kClass), default)
}
fun <T : V> generateAccessor(keyQualifiedName: String, default: T? = null): ArrayMapAccessor<K, V, T> {
return ArrayMapAccessor(keyQualifiedName, getId(keyQualifiedName), default)
}
fun <T : V, KK : K> generateNullableAccessor(kClass: KClass<KK>): NullableArrayMapAccessor<K, V, T> {
return NullableArrayMapAccessor(kClass, getId(kClass))
return NullableArrayMapAccessor(getId(kClass))
}
fun <KK : K> generateAnyNullableAccessor(kClass: KClass<KK>): NullableArrayMapAccessor<K, V, *> {
return NullableArrayMapAccessor(kClass, getId(kClass))
return NullableArrayMapAccessor(getId(kClass))
}
fun <T : K> getId(kClass: KClass<T>): Int {
return idPerType.customComputeIfAbsent(kClass.qualifiedName!!) { idCounter.getAndIncrement() }
return getId(kClass.qualifiedName!!)
}
fun getId(keyQualifiedName: String): Int {
return idPerType.customComputeIfAbsent(keyQualifiedName) { idCounter.getAndIncrement() }
}
/*
@@ -25,8 +25,8 @@ abstract class AttributeArrayOwner<K : Any, T : Any> protected constructor(
@Suppress("UNCHECKED_CAST")
constructor() : this(EmptyArrayMap as ArrayMap<T>)
final override fun registerComponent(tClass: KClass<out K>, value: T) {
val id = typeRegistry.getId(tClass)
final override fun registerComponent(keyQualifiedName: String, value: T) {
val id = typeRegistry.getId(keyQualifiedName)
when (arrayMap.size) {
0 -> {
arrayMap = OneElementArrayMap(value, id)
@@ -15,12 +15,12 @@ abstract class ComponentArrayOwner<K : Any, V : Any> : AbstractArrayMapOwner<K,
final override val arrayMap: ArrayMap<V> =
ArrayMapImpl()
final override fun registerComponent(tClass: KClass<out K>, value: V) {
val id = typeRegistry.getId(tClass)
final override fun registerComponent(keyQualifiedName: String, value: V) {
val id = typeRegistry.getId(keyQualifiedName)
try {
arrayMap[id] = value
} catch (e: Exception) {
throw RuntimeException(createDiagnosticMessage(id, tClass), e)
throw RuntimeException(createDiagnosticMessage(id, keyQualifiedName), e)
}
}
@@ -29,10 +29,10 @@ abstract class ComponentArrayOwner<K : Any, V : Any> : AbstractArrayMapOwner<K,
return arrayMap[id] ?: error("No '$key'($id) component in array: $this")
}
private fun createDiagnosticMessage(id: Int, tClass: KClass<*>): String = buildString {
private fun createDiagnosticMessage(id: Int, keyQualifiedName: String): String = buildString {
appendLine("Error occurred during registration of component in array")
appendLine("Currently registered")
appendLine(" $id: $tClass")
appendLine(" $id: $keyQualifiedName")
appendLine("Registrar:")
for ((kClass, x) in typeRegistry.allValuesThreadUnsafeForRendering()) {
appendLine(" $x: $kClass")