From 418e1c21340a95e74c308053be183ee7825aa34a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Wed, 4 Sep 2019 09:50:56 +0300 Subject: [PATCH] Refactored TaskBuilder to be more predictable --- .../kotlin/hep/dataforge/data/DataNode.kt | 4 ++- .../kotlin/hep/dataforge/data/checkType.kt | 10 ------- .../kotlin/hep/dataforge/data/dataJS.kt | 18 +++++++++++++ .../kotlin/hep/dataforge/data/CastDataNode.kt | 16 +---------- .../kotlin/hep/dataforge/data/dataJVM.kt | 18 +++++++++++-- .../hep/dataforge/workspace/TaskBuilder.kt | 27 +++++++++---------- 6 files changed, 51 insertions(+), 42 deletions(-) delete mode 100644 dataforge-data/src/jsMain/kotlin/hep/dataforge/data/checkType.kt create mode 100644 dataforge-data/src/jsMain/kotlin/hep/dataforge/data/dataJS.kt diff --git a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataNode.kt b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataNode.kt index a407b512..108d9f97 100644 --- a/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataNode.kt +++ b/dataforge-data/src/commonMain/kotlin/hep/dataforge/data/DataNode.kt @@ -227,4 +227,6 @@ fun DataNode.first(): Data? = dataSequence().first().second /** * Check that node is compatible with given type meaning that each element could be cast to the type */ -expect fun DataNode<*>.checkType(type: KClass<*>) \ No newline at end of file +expect fun DataNode<*>.checkType(type: KClass) + +//expect fun DataNode.cast(type: KClass): DataNode \ No newline at end of file diff --git a/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/checkType.kt b/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/checkType.kt deleted file mode 100644 index 56d1d0c9..00000000 --- a/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/checkType.kt +++ /dev/null @@ -1,10 +0,0 @@ -package hep.dataforge.data - -import kotlin.reflect.KClass - -/** - * Check that node is compatible with given type meaning that each element could be cast to the type - */ -actual fun DataNode<*>.checkType(type: KClass<*>) { - //Not supported in js yet -} \ No newline at end of file diff --git a/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/dataJS.kt b/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/dataJS.kt new file mode 100644 index 00000000..7706efad --- /dev/null +++ b/dataforge-data/src/jsMain/kotlin/hep/dataforge/data/dataJS.kt @@ -0,0 +1,18 @@ +package hep.dataforge.data + +import kotlin.reflect.KClass + +/** + * Check that node is compatible with given type meaning that each element could be cast to the type + */ +actual fun DataNode<*>.checkType(type: KClass) { + //Not supported in js yet +} + +///** +// * Performing +// */ +//@Suppress("UNCHECKED_CAST") +//actual fun DataNode.cast(type: KClass): DataNode{ +// return this as DataNode +//} \ No newline at end of file diff --git a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/CastDataNode.kt b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/CastDataNode.kt index 324864fc..01938ddb 100644 --- a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/CastDataNode.kt +++ b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/CastDataNode.kt @@ -8,7 +8,7 @@ import kotlin.reflect.KClass import kotlin.reflect.full.isSubclassOf @Suppress("UNCHECKED_CAST") -fun Data.safeCast(type: KClass): Data? { +private fun Data.safeCast(type: KClass): Data? { return if (this.type.isSubclassOf(type)) { return object : Data { override val meta: Meta get() = this@safeCast.meta @@ -23,20 +23,6 @@ fun Data.safeCast(type: KClass): Data? { } } -/** - * Filter a node by data and node type. Resulting node and its subnodes is guaranteed to have border type [type], - * but could contain empty nodes - */ -fun DataNode.cast(type: KClass): DataNode { - return if (this is CastDataNode) { - origin.cast(type) - } else { - CastDataNode(this, type) - } -} - -inline fun DataNode.cast(): DataNode = cast(R::class) - class CastDataNode(val origin: DataNode, override val type: KClass) : DataNode { override val items: Map> by lazy { origin.items.mapNotNull { (key, item) -> diff --git a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt index f87c4155..32bcec5f 100644 --- a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt +++ b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt @@ -12,8 +12,22 @@ fun Data.get(): T = runBlocking { await() } /** * Check that node is compatible with given type meaning that each element could be cast to the type */ -actual fun DataNode<*>.checkType(type: KClass<*>) { +actual fun DataNode<*>.checkType(type: KClass) { if (!type.isSuperclassOf(type)) { error("$type expected, but $type received") } -} \ No newline at end of file +} + +/** + * Filter a node by data and node type. Resulting node and its subnodes is guaranteed to have border type [type], + * but could contain empty nodes + */ +fun DataNode.cast(type: KClass): DataNode { + return if (this is CastDataNode) { + origin.cast(type) + } else { + CastDataNode(this, type) + } +} + +inline fun DataNode.cast(): DataNode = cast(R::class) \ No newline at end of file diff --git a/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt b/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt index 175c4d87..04e1efcc 100644 --- a/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt +++ b/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt @@ -6,6 +6,7 @@ import hep.dataforge.descriptors.NodeDescriptor import hep.dataforge.meta.Meta import hep.dataforge.meta.get import hep.dataforge.meta.string +import hep.dataforge.names.EmptyName import hep.dataforge.names.Name import hep.dataforge.names.toName import kotlin.reflect.KClass @@ -14,6 +15,7 @@ import kotlin.reflect.KClass class TaskBuilder(val name: String) { private var modelTransform: TaskModelBuilder.(Meta) -> Unit = { data("*") } var descriptor: NodeDescriptor? = null + private val dataTransforms: MutableList = ArrayList() /** * TODO will look better as extension class @@ -33,8 +35,6 @@ class TaskBuilder(val name: String) { } } - private val dataTransforms: MutableList = ArrayList(); - fun model(modelTransform: TaskModelBuilder.(Meta) -> Unit) { this.modelTransform = modelTransform } @@ -43,17 +43,19 @@ class TaskBuilder(val name: String) { inputType: KClass, from: String = "", to: String = "", - block: TaskModel.(Context, DataNode) -> DataNode + block: TaskEnv.(DataNode) -> DataNode ) { dataTransforms += DataTransformation(from, to) { context, model, data -> - block(model, context, data.cast(inputType)) + data.checkType(inputType) + val env = TaskEnv(EmptyName, model.meta, context) + env.block(data.cast(inputType)) } } inline fun transform( from: String = "", to: String = "", - noinline block: TaskModel.(Context, DataNode) -> DataNode + noinline block: TaskEnv.(DataNode) -> DataNode ) { transform(T::class, from, to, block) } @@ -64,10 +66,10 @@ class TaskBuilder(val name: String) { inline fun action( from: String = "", to: String = "", - crossinline block: Context.() -> Action + crossinline block: TaskEnv.() -> Action ) { - transform(from, to) { context, data: DataNode -> - block(context).invoke(data, meta) + transform(from, to) { data: DataNode -> + block().invoke(data, meta) } } @@ -82,7 +84,6 @@ class TaskBuilder(val name: String) { crossinline block: PipeBuilder.(Context) -> Unit ) { action(from, to) { - val context = this PipeAction( inputType = T::class, outputType = R::class @@ -99,7 +100,6 @@ class TaskBuilder(val name: String) { crossinline block: suspend TaskEnv.(T) -> R ) { action(from, to) { - val context = this PipeAction( inputType = T::class, outputType = R::class @@ -124,7 +124,7 @@ class TaskBuilder(val name: String) { JoinAction( inputType = T::class, outputType = R::class - ) { block(this@action) } + ) { block(context) } } } @@ -137,7 +137,6 @@ class TaskBuilder(val name: String) { crossinline block: suspend TaskEnv.(Map) -> R ) { action(from, to) { - val context = this JoinAction( inputType = T::class, outputType = R::class, @@ -164,7 +163,7 @@ class TaskBuilder(val name: String) { SplitAction( inputType = T::class, outputType = R::class - ) { block(this@action) } + ) { block(context) } } } @@ -187,7 +186,7 @@ class TaskBuilder(val name: String) { val model = this if (dataTransforms.isEmpty()) { //return data node as is - logger.warn("No transformation present, returning input data") + logger.warn { "No transformation present, returning input data" } data } else { val builder = DataTreeBuilder(Any::class)