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

commonMain.org.kodein.di.internal.DIBuilderImpl.kt Maven / Gradle / Ivy

There is a newer version: 7.23.1
Show newest version
package org.kodein.di.internal

import org.kodein.di.*
import org.kodein.di.bindings.*
import org.kodein.type.TypeToken
import org.kodein.type.erasedComp
import org.kodein.type.generic

internal open class DIBuilderImpl internal constructor(
        private val moduleName: String?,
        private val prefix: String,
        internal val importedModules: MutableSet,
        override val containerBuilder: DIContainerBuilderImpl
) : DI.Builder {

    override val contextType = TypeToken.Any

    override val scope: Scope get() = NoScope() // Recreating a new NoScope every-time *on purpose*!

    override val explicitContext: Boolean get() = false

    inner class TypeBinder internal constructor(val type: TypeToken, val tag: Any?, val overrides: Boolean?) : DI.Builder.TypeBinder {
        internal val containerBuilder get() = [email protected]

        override infix fun  with(binding: DIBinding) = containerBuilder.bind(DI.Key(binding.contextType, binding.argType, type, tag), binding, moduleName, overrides)
    }

    inner class DirectBinder internal constructor(private val _tag: Any?, private val _overrides: Boolean?) : DI.Builder.DirectBinder {
        override infix fun  from(binding: DIBinding) {
            if (binding.createdType == TypeToken.Unit) {
                throw IllegalArgumentException("Using `bind() from` with a *Unit* ${binding.factoryName()} is most likely an error. If you are sure you want to bind the Unit type, please use `bind() with ${binding.factoryName()}`.")
            }
            containerBuilder.bind(DI.Key(binding.contextType, binding.argType, binding.createdType, _tag), binding, moduleName, _overrides)
        }
    }

    inner class ConstantBinder internal constructor(private val _tag: Any, private val _overrides: Boolean?) : DI.Builder.ConstantBinder {
        @Suppress("FunctionName")
        override fun  With(valueType: TypeToken, value: T) = Bind(tag = _tag, overrides = _overrides, binding = InstanceBinding(valueType, value))
    }

    @Suppress("FunctionName")
    override fun  Bind(type: TypeToken, tag: Any?, overrides: Boolean?) = TypeBinder(type, tag, overrides)

    @Suppress("FunctionName")
    override fun  Bind(tag: Any?, overrides: Boolean?, binding: DIBinding<*, *, T>) {
        containerBuilder.bind(
            key = DI.Key(binding.contextType, binding.argType, binding.createdType, tag = tag),
            binding = binding,
            fromModule = moduleName,
            overrides = overrides,
        )
    }

    @Suppress("UNCHECKED_CAST")
    override fun  BindSet(tag: Any?, overrides: Boolean?, binding: DIBinding<*, *, T>) {
        val setType = erasedComp(Set::class, binding.createdType) as TypeToken>
        val setKey = DI.Key(binding.contextType, binding.argType, setType, tag)
        val setBinding = containerBuilder.bindingsMap[setKey]?.first() ?: throw IllegalStateException("No set binding to $setKey")

        setBinding.binding as? BaseMultiBinding<*, *, T> ?: throw IllegalStateException("$setKey is associated to a ${setBinding.binding.factoryName()} while it should be associated with bindingSet")
        (setBinding.binding.set as MutableSet>).add(binding)
    }

    @Suppress("FunctionName")
    override fun Bind(tag: Any?, overrides: Boolean?): DirectBinder = DirectBinder(tag, overrides)

    override fun constant(tag: Any, overrides: Boolean?) = ConstantBinder(tag, overrides)

    override fun import(module: DI.Module, allowOverride: Boolean) {
        val moduleName = prefix + module.name
        if (moduleName.isNotEmpty() && moduleName in importedModules) {
            throw IllegalStateException("Module \"$moduleName\" has already been imported!")
        }
        importedModules += moduleName
        DIBuilderImpl(moduleName, prefix + module.prefix, importedModules, containerBuilder.subBuilder(allowOverride, module.allowSilentOverride)).apply(module.init)
    }

    override fun importAll(modules: Iterable, allowOverride: Boolean) =
            modules.forEach { import(it, allowOverride) }

    override fun importAll(vararg modules: DI.Module, allowOverride: Boolean) =
            modules.forEach { import(it, allowOverride) }

    override fun importOnce(module: DI.Module, allowOverride: Boolean) {
        if (module.name.isEmpty())
            throw IllegalStateException("importOnce must be given a named module.")
        if (module.name !in importedModules)
            import(module, allowOverride)
    }

    override fun onReady(cb: DirectDI.() -> Unit) = containerBuilder.onReady(cb)

    override fun RegisterContextTranslator(translator: ContextTranslator<*, *>) = containerBuilder.registerContextTranslator(translator)

}

internal open class DIMainBuilderImpl(allowSilentOverride: Boolean) : DIBuilderImpl(null, "", HashSet(), DIContainerBuilderImpl(true, allowSilentOverride, HashMap(), ArrayList(), ArrayList())), DI.MainBuilder {

    override val externalSources: MutableList = ArrayList()

    override var fullDescriptionOnError: Boolean = DI.defaultFullDescriptionOnError
    override var fullContainerTreeOnError: Boolean = DI.defaultFullContainerTreeOnError

    override fun extend(di: DI, allowOverride: Boolean, copy: Copy) {
        val keys = copy.keySet(di.container.tree)

        containerBuilder.extend(di.container, allowOverride, keys)
        externalSources += di.container.tree.externalSources
        importedModules.addAll(
                containerBuilder.bindingsMap
                        .flatMap { it.value.map { it.fromModule } }
                        .filterNotNull()
        )
    }

    override fun extend(directDI: DirectDI, allowOverride: Boolean, copy: Copy) {
        val keys = copy.keySet(directDI.container.tree)

        containerBuilder.extend(directDI.container, allowOverride, keys)
        externalSources += directDI.container.tree.externalSources
        importedModules.addAll(
                containerBuilder.bindingsMap
                        .flatMap { it.value.map { it.fromModule } }
                        .filterNotNull()
        )
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy