Providers provide map instead of sequence on provideAll (replaced by top).
Context task loading ambiguity solved by prepending plugin name.
This commit is contained in:
parent
f284d15ee4
commit
52fb8234fc
@ -20,5 +20,5 @@ abstract class AbstractPlugin(override val meta: Meta = EmptyMeta) : Plugin {
|
||||
|
||||
override fun provideTop(target: String, name: Name): Any? = null
|
||||
|
||||
override fun listTop(target: String): Sequence<Name> = emptySequence()
|
||||
override fun listNames(target: String): Sequence<Name> = emptySequence()
|
||||
}
|
@ -2,9 +2,10 @@ package hep.dataforge.context
|
||||
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.appendLeft
|
||||
import hep.dataforge.names.toName
|
||||
import hep.dataforge.provider.Provider
|
||||
import hep.dataforge.provider.provideAll
|
||||
import hep.dataforge.provider.top
|
||||
import hep.dataforge.values.Value
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import mu.KLogger
|
||||
@ -66,7 +67,7 @@ open class Context(final override val name: String, val parent: Context? = Globa
|
||||
}
|
||||
}
|
||||
|
||||
override fun listTop(target: String): Sequence<Name> {
|
||||
override fun listNames(target: String): Sequence<Name> {
|
||||
return when (target) {
|
||||
Plugin.PLUGIN_TARGET -> plugins.asSequence().map { it.name.toName() }
|
||||
Value.TYPE -> properties.values().map { it.first }
|
||||
@ -118,12 +119,13 @@ open class Context(final override val name: String, val parent: Context? = Globa
|
||||
/**
|
||||
* A sequences of all objects provided by plugins with given target and type
|
||||
*/
|
||||
fun Context.members(target: String): Sequence<Any> =
|
||||
plugins.asSequence().flatMap { it.provideAll(target) }
|
||||
fun Context.content(target: String): Map<Name, Any> = content<Any>(target)
|
||||
|
||||
@JvmName("typedMembers")
|
||||
inline fun <reified T : Any> Context.members(target: String) =
|
||||
members(target).filterIsInstance<T>()
|
||||
@JvmName("typedContent")
|
||||
inline fun <reified T : Any> Context.content(target: String): Map<Name, T> =
|
||||
plugins.flatMap { plugin ->
|
||||
plugin.top<T>(target).entries.map { (it.key.appendLeft(plugin.name)) to it.value }
|
||||
}.associate { it }
|
||||
|
||||
|
||||
/**
|
||||
|
@ -17,6 +17,7 @@ package hep.dataforge.provider
|
||||
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.toName
|
||||
import kotlin.jvm.JvmName
|
||||
|
||||
/**
|
||||
* A marker utility interface for providers.
|
||||
@ -51,7 +52,7 @@ interface Provider {
|
||||
* @param target
|
||||
* @return
|
||||
*/
|
||||
fun listTop(target: String): Sequence<Name>
|
||||
fun listNames(target: String): Sequence<Name>
|
||||
}
|
||||
|
||||
fun Provider.provide(path: Path, targetOverride: String? = null): Any? {
|
||||
@ -77,15 +78,23 @@ inline fun <reified T : Any> Provider.provide(path: String): T? {
|
||||
return provide(Path.parse(path)) as? T
|
||||
}
|
||||
|
||||
inline fun <reified T : Any> Provider.provide(target: String, name: String): T? {
|
||||
return provide(PathToken(name.toName(), target).toPath()) as? T
|
||||
inline fun <reified T : Any> Provider.provide(target: String, name: Name): T? {
|
||||
return provide(PathToken(name, target).toPath()) as? T
|
||||
}
|
||||
|
||||
inline fun <reified T : Any> Provider.provide(target: String, name: String): T? =
|
||||
provide(target, name.toName())
|
||||
|
||||
/**
|
||||
* [Sequence] of all elements with given target
|
||||
* A top level content with names
|
||||
*/
|
||||
fun Provider.provideAll(target: String): Sequence<Any> {
|
||||
return listTop(target).map { provideTop(target, it) ?: error("The element $it is declared but not provided") }
|
||||
fun Provider.top(target: String): Map<Name, Any> = top<Any>(target)
|
||||
|
||||
@JvmName("typedTop")
|
||||
inline fun <reified T : Any> Provider.top(target: String): Map<Name, T> {
|
||||
return listNames(target).associate {
|
||||
it to (provideTop(target, it) as? T ?: error("The element $it is declared but not provided"))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -17,10 +17,10 @@ class ContextTest {
|
||||
}
|
||||
}
|
||||
|
||||
override fun listTop(target: String): Sequence<Name> {
|
||||
override fun listNames(target: String): Sequence<Name> {
|
||||
return when (target) {
|
||||
"test" -> sequenceOf("a", "b", "c.d").map { it.toName() }
|
||||
else -> super.listTop(target)
|
||||
else -> super.listNames(target)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -28,7 +28,7 @@ class ContextTest {
|
||||
@Test
|
||||
fun testPluginManager() {
|
||||
Global.plugins.load(DummyPlugin())
|
||||
val members = Global.members<Name>("test")
|
||||
val members = Global.content<Name>("test")
|
||||
assertEquals(3, members.count())
|
||||
members.forEach {
|
||||
println(it)
|
||||
|
@ -1,11 +1,14 @@
|
||||
package hep.dataforge.provider
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.context.members
|
||||
import hep.dataforge.context.content
|
||||
import hep.dataforge.names.Name
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
object Types {
|
||||
operator fun get(cl: KClass<*>): String {
|
||||
return cl.findAnnotation<Type>()?.id ?: cl.simpleName ?: ""
|
||||
@ -24,13 +27,20 @@ inline fun <reified T : Any> Provider.provideByType(name: String): T? {
|
||||
return provide(target, name)
|
||||
}
|
||||
|
||||
inline fun <reified T : Any> Provider.provideAllByType(): Sequence<T> {
|
||||
inline fun <reified T : Any> Provider.provideByType(name: Name): T? {
|
||||
val target = Types[T::class]
|
||||
return provideAll(target).filterIsInstance<T>()
|
||||
return provide(target, name)
|
||||
}
|
||||
|
||||
inline fun <reified T : Any> Provider.top(): Map<Name, T> {
|
||||
val target = Types[T::class]
|
||||
return listNames(target).associate { name ->
|
||||
name to (provideByType<T>(name) ?: error("The element $name is declared but not provided"))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sequences of all objects provided by plugins with given target and type
|
||||
*/
|
||||
inline fun <reified T : Any> Context.members(): Sequence<T> = members<T>(Types[T::class])
|
||||
inline fun <reified T : Any> Context.content(): Map<Name, T> = content<T>(Types[T::class])
|
||||
|
||||
|
@ -102,6 +102,8 @@ operator fun Name.plus(other: Name): Name = Name(this.tokens + other.tokens)
|
||||
|
||||
operator fun Name.plus(other: String): Name = this + other.toName()
|
||||
|
||||
fun Name.appendLeft(other: String): Name = NameToken(other) + this
|
||||
|
||||
fun NameToken.asName() = Name(listOf(this))
|
||||
|
||||
val EmptyName = Name(emptyList())
|
||||
|
@ -4,11 +4,9 @@ import hep.dataforge.context.Context
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.output.Output
|
||||
import hep.dataforge.output.TextRenderer
|
||||
import hep.dataforge.output.TextRenderer.Companion.TEXT_RENDERER_TYPE
|
||||
import hep.dataforge.output.html.HtmlBuilder.Companion.HTML_CONVERTER_TYPE
|
||||
import hep.dataforge.provider.Type
|
||||
import hep.dataforge.provider.provideAll
|
||||
import hep.dataforge.provider.provideAllByType
|
||||
import hep.dataforge.provider.top
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.html.TagConsumer
|
||||
@ -29,7 +27,7 @@ class HtmlOutput<T : Any>(override val context: Context, private val consumer: T
|
||||
} else {
|
||||
val value = cache[obj::class]
|
||||
if (value == null) {
|
||||
val answer = context.provideAllByType<HtmlBuilder<*>>()
|
||||
val answer = context.top<HtmlBuilder<*>>().values
|
||||
.filter { it.type.isInstance(obj) }.firstOrNull()
|
||||
if (answer != null) {
|
||||
cache[obj::class] = answer
|
||||
|
@ -1,10 +1,10 @@
|
||||
package hep.dataforge.output
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.output.TextRenderer.Companion.TEXT_RENDERER_TYPE
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.output.TextRenderer.Companion.TEXT_RENDERER_TYPE
|
||||
import hep.dataforge.provider.Type
|
||||
import hep.dataforge.provider.provideAll
|
||||
import hep.dataforge.provider.top
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.reflect.KClass
|
||||
@ -21,8 +21,8 @@ class TextOutput(override val context: Context, private val output: kotlinx.io.c
|
||||
} else {
|
||||
val value = cache[obj::class]
|
||||
if (value == null) {
|
||||
val answer = context.provideAll(TEXT_RENDERER_TYPE).filterIsInstance<TextRenderer>()
|
||||
.filter { it.type.isInstance(obj) }.firstOrNull()
|
||||
val answer =
|
||||
context.top<TextRenderer>(TEXT_RENDERER_TYPE).values.firstOrNull { it.type.isInstance(obj) }
|
||||
if (answer != null) {
|
||||
cache[obj::class] = answer
|
||||
answer
|
||||
|
@ -8,6 +8,7 @@ import hep.dataforge.meta.MetaRepr
|
||||
import hep.dataforge.meta.buildMeta
|
||||
import hep.dataforge.names.EmptyName
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.get
|
||||
import hep.dataforge.names.isEmpty
|
||||
|
||||
/**
|
||||
@ -49,7 +50,7 @@ class AllDataDependency(val placement: Name = EmptyName) : Dependency() {
|
||||
|
||||
class TaskModelDependency(val name: String, val meta: Meta, val placement: Name = EmptyName) : Dependency() {
|
||||
override fun apply(workspace: Workspace): DataNode<Any> {
|
||||
val task = workspace.tasks[name] ?: error("Task with name ${name} is not found in the workspace")
|
||||
val task = workspace.tasks[name] ?: error("Task with name $name is not found in the workspace")
|
||||
if (task.isTerminal) TODO("Support terminal task")
|
||||
val result = workspace.run(task, meta)
|
||||
return if (placement.isEmpty()) {
|
||||
|
@ -2,9 +2,11 @@ package hep.dataforge.workspace
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.context.members
|
||||
import hep.dataforge.data.DataNode
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.toName
|
||||
import hep.dataforge.provider.top
|
||||
|
||||
|
||||
/**
|
||||
@ -16,8 +18,8 @@ class SimpleWorkspace(
|
||||
override val targets: Map<String, Meta>,
|
||||
tasks: Collection<Task<Any>>
|
||||
) : Workspace {
|
||||
override val tasks: Map<String, Task<*>> by lazy {
|
||||
(context.members<Task<*>>(Task.TYPE) + tasks).associate { it.name to it }
|
||||
override val tasks: Map<Name, Task<*>> by lazy {
|
||||
context.top<Task<*>>(Task.TYPE) + tasks.associate { it.name.toName() to it }
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -27,22 +27,22 @@ interface Workspace : ContextAware, Provider {
|
||||
/**
|
||||
* All tasks associated with the workspace
|
||||
*/
|
||||
val tasks: Map<String, Task<*>>
|
||||
val tasks: Map<Name, Task<*>>
|
||||
|
||||
override fun provideTop(target: String, name: Name): Any? {
|
||||
return when (target) {
|
||||
"target", Meta.TYPE -> targets[name.toString()]
|
||||
Task.TYPE -> tasks[name.toString()]
|
||||
Task.TYPE -> tasks[name]
|
||||
Data.TYPE -> data[name]
|
||||
DataNode.TYPE -> data.getNode(name)
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
override fun listTop(target: String): Sequence<Name> {
|
||||
override fun listNames(target: String): Sequence<Name> {
|
||||
return when (target) {
|
||||
"target", Meta.TYPE -> targets.keys.asSequence().map { it.toName() }
|
||||
Task.TYPE -> tasks.keys.asSequence().map { it.toName() }
|
||||
Task.TYPE -> tasks.keys.asSequence().map { it }
|
||||
Data.TYPE -> data.data().map { it.first }
|
||||
DataNode.TYPE -> data.nodes().map { it.first }
|
||||
else -> emptySequence()
|
||||
@ -85,10 +85,10 @@ fun Workspace.run(task: Task<*>, target: String): DataNode<Any> {
|
||||
|
||||
|
||||
fun Workspace.run(task: String, target: String) =
|
||||
tasks[task]?.let { run(it, target) } ?: error("Task with name $task not found")
|
||||
tasks[task.toName()]?.let { run(it, target) } ?: error("Task with name $task not found")
|
||||
|
||||
fun Workspace.run(task: String, meta: Meta) =
|
||||
tasks[task]?.let { run(it, meta) } ?: error("Task with name $task not found")
|
||||
tasks[task.toName()]?.let { run(it, meta) } ?: error("Task with name $task not found")
|
||||
|
||||
fun Workspace.run(task: String, block: MetaBuilder.() -> Unit = {}) =
|
||||
run(task, buildMeta(block))
|
||||
|
Loading…
Reference in New Issue
Block a user