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