e.ultra.kontainer.0.77.0.source-code.TypeLookup.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kontainer Show documentation
Show all versions of kontainer Show documentation
"Kotlin Depdency Injection Framework"
The newest version!
package de.peekandpoke.ultra.kontainer
import kotlin.reflect.KClass
/**
* Helpers for looking up base and super types.
*/
abstract class TypeLookup {
/**
* Get all matching types for the given [type]
*/
abstract fun getAllCandidatesFor(type: KClass<*>): Set>
/**
* Gets a distinct candidate for the given [type]
*
* If there is no super type or more than one found, a [ServiceNotFound] is thrown.
*/
fun getDistinctFor(type: KClass<*>): KClass<*> {
// TODO: we should have the cache layer at this point and not in the subsclasses
val candidates = getAllCandidatesFor(type)
if (candidates.isEmpty()) {
throw ServiceNotFound("Service ${type.qualifiedName} was not found")
}
if (candidates.size > 1) {
throw ServiceAmbiguous(
"Service ${type.qualifiedName} is ambiguous. It has multiple candidates: " +
candidates.map { it.qualifiedName }.joinToString(", ")
)
}
return candidates.first()
}
/**
* Helper class for finding [baseTypes] of a given super type
*
* Result to calls of [getAllCandidatesFor] and cached internally for future reuse.
*/
data class ForBaseTypes(val baseTypes: Set>) : TypeLookup() {
/**
* Internal cache map from classes to their base types
*/
private val cache = mutableMapOf, Set>>()
/**
* Gets all [baseTypes] that are base types of the given super [type]
*/
override fun getAllCandidatesFor(type: KClass<*>): Set> =
cache.getOrPut(type) {
baseTypes.filter { baseType ->
baseType.java.isAssignableFrom(type.java)
}.toSet()
}
}
/**
* Helper class for finding [superTypes] of given base type
*
* Result to calls of [getAllCandidatesFor] and cached internally for future reuse.
*/
data class ForSuperTypes(val superTypes: Set>) : TypeLookup() {
/**
* Internal cache map from classes to their super types
*/
private val candidatesCache = mutableMapOf, Set>>()
/**
* Internal cache map from classes to [LazyServiceLookupBlueprint]
*/
private val lookupBlueprintCache = mutableMapOf, LazyServiceLookupBlueprint<*>>()
/**
* Gets all [superTypes] for the given base [type]
*/
override fun getAllCandidatesFor(type: KClass<*>): Set> =
candidatesCache.getOrPut(type) {
superTypes
.filter { superType -> type.java.isAssignableFrom(superType.java) }
.toSet()
}
/**
* Get all [superTypes] for the given base [type] as a [LazyServiceLookupBlueprint]
*/
fun getLookupBlueprint(type: KClass<*>): LazyServiceLookupBlueprint<*> =
lookupBlueprintCache.getOrPut(type) {
val map = getAllCandidatesFor(type)
.associateWith {
{ kontainer: Kontainer, context: InjectionContext ->
kontainer.get(it, context)
}
}
LazyServiceLookupBlueprint(map)
}
/**
* Get a distinct super type of the given [type] or null if there is none or multiple candidates
*/
fun getDistinctForOrNull(type: KClass): KClass? {
@Suppress("UNCHECKED_CAST")
return getAllCandidatesFor(type).firstOrNull() as KClass?
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy