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

main.DependencyLookup.kt Maven / Gradle / Ivy

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

import kotlin.reflect.KClass

/**
 * A lookup for mapping service class to service classes that they request for injection.
 */
class DependencyLookup internal constructor(
    superTypeLookUp: TypeLookup.ForSuperTypes,
    definitions: Map, ServiceDefinition>
) {

    /**
     * The lookup map
     *
     * It is built by the init method.
     *
     * Map Key:   A service class that other services might inject
     * Map Value: A set of services class that directly inject the key service
     */
    private val dependencies: Map, Set>>

    init {
        /**
         * Temporary map for building the lookup
         */
        val tmp = mutableMapOf, MutableSet>>()

        fun MutableMap, MutableSet>>.add(master: KClass<*>, dependsOn: KClass<*>) =
            getOrPut(master) { mutableSetOf() }.add(dependsOn)

        /**
         * Records the injected types of the given cls
         */
        val record = { def: ServiceDefinition ->

            def.producer.signature.forEach { parameter ->

                val type = parameter.type
                val paramCls = type.classifier as KClass<*>

                val candidates = when {
                    // lazy list of types
                    type.isLazyListType() -> superTypeLookUp.getAllCandidatesFor(type.getInnerInnerClass())

                    // list of lazy types
                    type.isListType() || type.isLazyServiceType() || type.isLookupType() ->
                        superTypeLookUp.getAllCandidatesFor(type.getInnerClass())

                    // default service type
                    paramCls.isServiceType() -> superTypeLookUp.getAllCandidatesFor(paramCls)

                    else -> setOf()
                }

                candidates.forEach { superType ->
                    tmp.add(superType, def.serviceCls)
                }
            }
        }

        definitions.values.forEach { record(it) }

        dependencies = tmp
    }

    /**
     * Return a set service classes that directly or indirectly depend on one of the classes given
     */
    fun getAllDependents(of: Set>): Set> {

        var current = of
        var previous = setOf>()

        // Not the best/fastest implementation ...
        while (current.size > previous.size) {

            previous = current

            val found = current.flatMap { dependencies[it] ?: setOf() }

            current = current.plus(found)
        }

        // NOTICE: we remove the initial set [of] as we really only want to know their dependents
        return current.minus(of)
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy