Simplified Provider API

This commit is contained in:
Alexander Nozik 2019-07-05 18:49:36 +03:00
parent 5b053d60a2
commit da4a9ebe9d
9 changed files with 32 additions and 94 deletions

View File

@ -3,7 +3,7 @@ plugins {
id("scientifik.publish") apply false id("scientifik.publish") apply false
} }
val dataforgeVersion by extra("0.1.3-dev-8") val dataforgeVersion by extra("0.1.3-dev-9")
val bintrayRepo by extra("dataforge") val bintrayRepo by extra("dataforge")
val vcs by extra("https://github.com/mipt-npm/dataforge-core") val vcs by extra("https://github.com/mipt-npm/dataforge-core")

View File

@ -18,7 +18,5 @@ abstract class AbstractPlugin(override val meta: Meta = EmptyMeta) : Plugin {
this._context = null this._context = null
} }
override fun provideTop(target: String, name: Name): Any? = null override fun provideTop(target: String): Map<Name, Any> = emptyMap()
override fun listNames(target: String): Sequence<Name> = emptySequence()
} }

View File

@ -59,19 +59,11 @@ open class Context(final override val name: String, val parent: Context? = Globa
override val defaultTarget: String get() = Plugin.PLUGIN_TARGET override val defaultTarget: String get() = Plugin.PLUGIN_TARGET
override fun provideTop(target: String, name: Name): Any? { override fun provideTop(target: String): Map<Name, Any> {
return when (target) { return when(target){
Plugin.PLUGIN_TARGET -> plugins[PluginTag.fromString(name.toString())] Value.TYPE -> properties.sequence().toMap()
Value.TYPE -> properties[name]?.value Plugin.PLUGIN_TARGET -> plugins.sequence(true).associateBy { it.name.toName() }
else -> null else-> emptyMap()
}
}
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 }
else -> emptySequence()
} }
} }

View File

@ -17,7 +17,6 @@ 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.
@ -42,29 +41,21 @@ interface Provider {
/** /**
* Provide a top level element for this [Provider] or return null if element is not present * A map of direct children for specific target
*/ */
fun provideTop(target: String, name: Name): Any? fun provideTop(target: String): Map<Name, Any>
/**
* [Sequence] of available names with given target. Only top level names are listed, no chain path.
*
* @param target
* @return
*/
fun listNames(target: String): Sequence<Name>
} }
fun Provider.provide(path: Path, targetOverride: String? = null): Any? { fun Provider.provide(path: Path, targetOverride: String? = null): Any? {
if (path.length == 0) throw IllegalArgumentException("Can't provide by empty path") if (path.length == 0) throw IllegalArgumentException("Can't provide by empty path")
val first = path.first() val first = path.first()
val top = provideTop(targetOverride ?: first.target ?: defaultTarget, first.name) val target = targetOverride ?: first.target ?: defaultTarget
val res = provideTop(target)[first.name] ?: return null
return when (path.length) { return when (path.length) {
1 -> top 1 -> res
else -> { else -> {
when (top) { when (res) {
null -> null is Provider -> res.provide(path.tail!!, targetOverride = defaultChainTarget)
is Provider -> top.provide(path.tail!!, targetOverride = defaultChainTarget)
else -> throw IllegalStateException("Chain path not supported: child is not a provider") else -> throw IllegalStateException("Chain path not supported: child is not a provider")
} }
} }
@ -85,16 +76,12 @@ inline fun <reified T : Any> Provider.provide(target: String, name: Name): T? {
inline fun <reified T : Any> Provider.provide(target: String, name: String): T? = inline fun <reified T : Any> Provider.provide(target: String, name: String): T? =
provide(target, name.toName()) provide(target, name.toName())
fun Provider.top(target: String): Map<Name, Any> = top<Any>(target)
/** /**
* A top level content with names * Typed top level content
*/ */
@JvmName("typedTop")
inline fun <reified T : Any> Provider.top(target: String): Map<Name, T> { inline fun <reified T : Any> Provider.top(target: String): Map<Name, T> {
return listNames(target).associate { return provideTop(target).mapValues {
it to (provideTop(target, it) as? T ?: error("The element $it is declared but not provided")) it.value as? T ?: error("The type of element $it is ${it::class} but ${T::class} is expected")
} }
} }

View File

@ -12,17 +12,10 @@ class ContextTest {
class DummyPlugin : AbstractPlugin() { class DummyPlugin : AbstractPlugin() {
override val tag get() = PluginTag("test") override val tag get() = PluginTag("test")
override fun provideTop(target: String, name: Name): Any? { override fun provideTop(target: String): Map<Name, Any> {
return when (target) { return when(target){
"test" -> return name "test" -> listOf("a", "b", "c.d").associate { it.toName() to it.toName() }
else -> super.provideTop(target, name) else -> emptyMap()
}
}
override fun listNames(target: String): Sequence<Name> {
return when (target) {
"test" -> sequenceOf("a", "b", "c.d").map { it.toName() }
else -> super.listNames(target)
} }
} }
} }

View File

@ -34,9 +34,7 @@ inline fun <reified T : Any> Provider.provideByType(name: Name): T? {
inline fun <reified T : Any> Provider.top(): Map<Name, T> { inline fun <reified T : Any> Provider.top(): Map<Name, T> {
val target = Types[T::class] val target = Types[T::class]
return listNames(target).associate { name -> return top(target)
name to (provideByType<T>(name) ?: error("The element $name is declared but not provided"))
}
} }
/** /**

View File

@ -7,7 +7,6 @@ import hep.dataforge.data.DataNode
import hep.dataforge.meta.Meta import hep.dataforge.meta.Meta
import hep.dataforge.names.Name import hep.dataforge.names.Name
import hep.dataforge.names.toName import hep.dataforge.names.toName
import hep.dataforge.provider.top
/** /**

View File

@ -29,27 +29,16 @@ interface Workspace : ContextAware, Provider {
*/ */
val tasks: Map<Name, Task<*>> val tasks: Map<Name, Task<*>>
override fun provideTop(target: String, name: Name): Any? { override fun provideTop(target: String): Map<Name, Any> {
return when (target) { return when (target) {
"target", Meta.TYPE -> targets[name.toString()] "target", Meta.TYPE -> targets.mapKeys { it.key.toName() }
Task.TYPE -> tasks[name] Task.TYPE -> tasks
Data.TYPE -> data[name] Data.TYPE -> data.data().toMap()
DataNode.TYPE -> data.getNode(name) DataNode.TYPE -> data.nodes().toMap()
else -> null else -> emptyMap()
} }
} }
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 }
Data.TYPE -> data.data().map { it.first }
DataNode.TYPE -> data.nodes().map { it.first }
else -> emptySequence()
}
}
/** /**
* Invoke a task in the workspace utilizing caching if possible * Invoke a task in the workspace utilizing caching if possible
*/ */
@ -64,15 +53,6 @@ interface Workspace : ContextAware, Provider {
} }
} }
// /**
// * Invoke a task in the workspace utilizing caching if possible
// */
// operator fun <R : Any> Task<R>.invoke(targetName: String): DataNode<R> {
// val target = targets[targetName] ?: error("A target with name $targetName not found in ${this@Workspace}")
// context.logger.info { "Running ${this.name} on $target" }
// return invoke(target)
// }
companion object { companion object {
const val TYPE = "workspace" const val TYPE = "workspace"
} }

View File

@ -10,19 +10,10 @@ import hep.dataforge.names.toName
abstract class WorkspacePlugin : AbstractPlugin() { abstract class WorkspacePlugin : AbstractPlugin() {
abstract val tasks: Collection<Task<*>> abstract val tasks: Collection<Task<*>>
override fun provideTop(target: String, name: Name): Any? { override fun provideTop(target: String): Map<Name, Any> {
return if (target == Task.TYPE) { return when(target){
tasks.find { it.name == name.toString() } Task.TYPE -> tasks.associateBy { it.name.toName() }
} else { else -> emptyMap()
super.provideTop(target, name)
}
}
override fun listNames(target: String): Sequence<Name> {
return if (target == Task.TYPE) {
tasks.asSequence().map { it.name.toName() }
} else {
return super.listNames(target)
} }
} }
} }