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
}
val dataforgeVersion by extra("0.1.3-dev-8")
val dataforgeVersion by extra("0.1.3-dev-9")
val bintrayRepo by extra("dataforge")
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
}
override fun provideTop(target: String, name: Name): Any? = null
override fun listNames(target: String): Sequence<Name> = emptySequence()
override fun provideTop(target: String): Map<Name, Any> = emptyMap()
}

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 fun provideTop(target: String, name: Name): Any? {
override fun provideTop(target: String): Map<Name, Any> {
return when(target){
Plugin.PLUGIN_TARGET -> plugins[PluginTag.fromString(name.toString())]
Value.TYPE -> properties[name]?.value
else -> null
}
}
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()
Value.TYPE -> properties.sequence().toMap()
Plugin.PLUGIN_TARGET -> plugins.sequence(true).associateBy { it.name.toName() }
else-> emptyMap()
}
}

View File

@ -17,7 +17,6 @@ package hep.dataforge.provider
import hep.dataforge.names.Name
import hep.dataforge.names.toName
import kotlin.jvm.JvmName
/**
* 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?
/**
* [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 provideTop(target: String): Map<Name, Any>
}
fun Provider.provide(path: Path, targetOverride: String? = null): Any? {
if (path.length == 0) throw IllegalArgumentException("Can't provide by empty path")
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) {
1 -> top
1 -> res
else -> {
when (top) {
null -> null
is Provider -> top.provide(path.tail!!, targetOverride = defaultChainTarget)
when (res) {
is Provider -> res.provide(path.tail!!, targetOverride = defaultChainTarget)
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? =
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> {
return listNames(target).associate {
it to (provideTop(target, it) as? T ?: error("The element $it is declared but not provided"))
return provideTop(target).mapValues {
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() {
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){
"test" -> return name
else -> super.provideTop(target, name)
}
}
override fun listNames(target: String): Sequence<Name> {
return when (target) {
"test" -> sequenceOf("a", "b", "c.d").map { it.toName() }
else -> super.listNames(target)
"test" -> listOf("a", "b", "c.d").associate { it.toName() to it.toName() }
else -> emptyMap()
}
}
}

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> {
val target = Types[T::class]
return listNames(target).associate { name ->
name to (provideByType<T>(name) ?: error("The element $name is declared but not provided"))
}
return top(target)
}
/**

View File

@ -7,7 +7,6 @@ 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
/**

View File

@ -29,27 +29,16 @@ interface Workspace : ContextAware, Provider {
*/
val tasks: Map<Name, Task<*>>
override fun provideTop(target: String, name: Name): Any? {
override fun provideTop(target: String): Map<Name, Any> {
return when (target) {
"target", Meta.TYPE -> targets[name.toString()]
Task.TYPE -> tasks[name]
Data.TYPE -> data[name]
DataNode.TYPE -> data.getNode(name)
else -> null
"target", Meta.TYPE -> targets.mapKeys { it.key.toName() }
Task.TYPE -> tasks
Data.TYPE -> data.data().toMap()
DataNode.TYPE -> data.nodes().toMap()
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
*/
@ -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 {
const val TYPE = "workspace"
}

View File

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