All Downloads are FREE. Search and download functionalities are using the official Maven repository.

main.Kontainer.kt Maven / Gradle / Ivy

There is a newer version: 0.77.0
Show newest version
package de.peekandpoke.ultra.kontainer

import de.peekandpoke.ultra.common.Lookup
import kotlin.reflect.KClass

/**
 * The container
 */
@Suppress("Detekt.TooManyFunctions")
class Kontainer internal constructor(
    private val factory: ServiceProviderFactory,
) : KontainerAware {
    /**
     * Tools for debugging the kontainer and more
     */
    val tools: KontainerTools = KontainerTools(this)

    /**
     * The blueprint for this kontainer
     */
    val blueprint: KontainerBlueprint = factory.blueprint

    /**
     * Implementing [KontainerAware]
     */
    override val kontainer: Kontainer = this

    /**
     * The root context is used, when services are directly requested from the Kontainer
     */
    private val rootContext: InjectionContext = InjectionContext.kontainerRoot

    /**
     * Get the underlying [ServiceProviderFactory].
     */
    fun getServiceProviderFactory(): ServiceProviderFactory = factory

    // Cloning the kontainer ///////////////////////////////////////////////////////////////////////////////////////////

    /**
     * Create a new fresh instance of this [Kontainer].
     *
     * This will reset all dynamic services, just like creating a new kontainer from a [KontainerBlueprint].
     */
    fun clone(): Kontainer = factory.newKontainer()

    // getting services ////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * Get all service classes that would satisfy the given [cls]
     */
    fun  getCandidates(cls: KClass): Set> = blueprint.superTypeLookup.getAllCandidatesFor(cls)

    /**
     * Get a service for the given class
     */
    inline fun  get() = get(T::class)

    /**
     * Get a service for the given class
     */
    fun  get(cls: KClass): T = get(cls, rootContext)

    /**
     * Get a service for the given [cls] or null if no service can be provided
     */
    fun  getOrNull(cls: KClass): T? = getOrNull(cls, rootContext)

    /**
     * Get a service for the given [cls], and when it is present run the [block] on it.
     *
     * When the service is not present null is returned.
     * Otherwise, the result of the [block] is returned.
     */
    inline fun  use(cls: KClass, block: T.() -> R?): R? {

        val type = blueprint.superTypeLookup.getDistinctForOrNull(cls) ?: return null

        return get(type).block()
    }

    /**
     * Get all services that are a super type of the given class
     */
    fun  getAll(cls: KClass): List = getAll(cls, rootContext)

    /**
     * Get all services that are a super type of the given class as a [Lookup]
     */
    fun  getLookup(cls: KClass): LazyServiceLookup = getLookup(cls, rootContext)

    /**
     * Get a provider for the given service class
     */
    inline fun  getProvider(): ServiceProvider = getProvider(T::class)

    /**
     * Get a provider for the given service class
     */
    fun  getProvider(cls: KClass): ServiceProvider {

        val type = blueprint.superTypeLookup.getDistinctFor(cls)

        return factory.getProvider(type)
    }

    // getting parameters //////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * Check if there is a config value with the given [id] that is of the given [type]
     */
    fun hasConfig(id: String, type: KClass<*>): Boolean {
        return blueprint.configValues[id].let { it != null && it::class == type }
    }

    /**
     * Get a config value by its [id]
     */
    @Suppress("UNCHECKED_CAST")
    fun  getConfig(id: String): T = blueprint.configValues[id] as T

    // internal helpers ////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * Internally gets a [service] for the given [context]
     */
    internal fun  get(service: KClass, context: InjectionContext): T {
        @Suppress("UNCHECKED_CAST")
        return getProvider(service).provide(this, context) as T
    }

    /**
     * Internally gets a [service] or null for the given [context]
     */
    internal fun  getOrNull(service: KClass, context: InjectionContext): T? {

        val type = blueprint.superTypeLookup.getDistinctForOrNull(service) ?: return null

        return get(type, context)
    }

    /**
     * Internally gets all super type services of [cls] as a [List]
     */
    internal fun  getAll(cls: KClass, context: InjectionContext): List {
        @Suppress("UNCHECKED_CAST")
        return blueprint.superTypeLookup.getAllCandidatesFor(cls).map { get(it, context) as T }
    }

    /**
     * Internally gets all super type services of [cls] as a [Lookup]
     */
    internal fun  getLookup(cls: KClass, context: InjectionContext): LazyServiceLookup {
        @Suppress("UNCHECKED_CAST")
        return blueprint.superTypeLookup.getLookupBlueprint(cls).with(this, context) as LazyServiceLookup
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy