commonMain.org.kodein.di.Copy.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of kodein-di-js Show documentation
Show all versions of kodein-di-js Show documentation
KODEIN Dependency Injection Core
package org.kodein.di
/**
* Defines which bindings are to be copied from a parent DI to a child DI.
*
* @property all Whether the specs are describing multiple matching bindings or only one.
*/
public class CopySpecs(public val all: Boolean) : SearchSpecs()
/**
* Simple interface that returns a the keys to copy from a container.
*/
public interface Copy {
/**
* The keys to copy from the given tree, according to the rules defined in this object.
*
* @param tree The tree that contains bindings to copy.
*/
public fun keySet(tree: DITree): Set>
/**
* A [Copy] spec that copies all bindings.
*/
public object All: Copy {
override fun keySet(tree: DITree): Set> = tree.bindings.keys
}
/**
* A [Copy] spec that copies no bindings.
*/
public object None: Copy {
override fun keySet(tree: DITree): Set> = emptySet>()
}
/**
* A [Copy] spec that copies only the bindings that retain no status / reference.
*/
public object NonCached: Copy {
override fun keySet(tree: DITree): Set> = tree.bindings.filter { it.value.first().binding.copier == null } .keys
}
public companion object {
/**
* Creates copy specs where the DSL defines which bindings are to be [copied][BaseDSL.copy].
*/
public operator fun invoke(f: DSL.() -> Unit): DSL = DSL().apply(f)
/**
* Creates copy specs where all bindings are copied by default, and the DSL defines which bindings are to be [ignored][BaseDSL.ignore].
*/
public fun allBut(f: AllButDSL.() -> Unit): AllButDSL = AllButDSL().apply(f)
internal fun specsToKeys(tree: DITree, it: CopySpecs): List> {
val list = tree.find(it)
if (list.isEmpty()) {
throw DI.NoResultException(it, "No binding found that match this search: $it")
}
if (!it.all && list.size > 1) {
throw DI.NoResultException(it, "There were ${list.size} matches for this search: $it\n${list.associate { it.first to it.second }.description(false)}")
}
return list.map { it.first }
}
}
/**
* Base class for the Copy DSL.
*/
public abstract class BaseDSL : SearchDSL(), Copy {
internal val copySpecs = ArrayList()
internal val ignoreSpecs = ArrayList()
/**
* Second half of the sentence `[copy|ignore] the` and `[copy|ignore] all`
*/
public class Sentence(private val specs: MutableList) {
/**
* Defines that this spec will only correspond to **one** matching binding.
*
* @param binding The binding it should match.
* @return The binding itself to configure it (e.g. `copy the binding() with context()`).
*/
public infix fun the(binding: Binding): SearchSpecs {
return CopySpecs(all = false).also { binding.apply(it) ; specs += it }
}
/**
* Defines that this spec will only correspond to **all** matching binding.
*
* @param spec The specs of the search.
* @return The binding itself to configure it (e.g. `copy all context() with tag("whatever")`).
*/
public infix fun all(spec: Spec): SearchSpecs {
return CopySpecs(all = true).also { spec.apply(it) ; specs += it }
}
}
/**
* Beginning of the following DSLs: `copy the ...` and `copy all ...`.
*/
public val copy: Sentence = Sentence(copySpecs)
/**
* Beginning of the following DSLs: `ignore the ...` and `ignore all ...`.
*/
public val ignore: Sentence = Sentence(ignoreSpecs)
}
/**
* [Copy] DSL.
*/
public class DSL : BaseDSL() {
override fun keySet(tree: DITree): Set> {
val ignored = ignoreSpecs.flatMap { specsToKeys(tree, it) }
return copySpecs
.flatMap { specsToKeys(tree, it) }
.minus(ignored)
.toSet()
}
}
/**
* [Copy.allBut] DSL
*/
public class AllButDSL : BaseDSL() {
override fun keySet(tree: DITree): Set> {
val kept = copySpecs.flatMap { specsToKeys(tree, it) }
val ignored = ignoreSpecs
.flatMap { specsToKeys(tree, it) }
.minus(kept)
return tree.bindings.keys.minus(ignored)
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy