From 61c2530c9184b752f723835de22aee48b070b27a Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Thu, 12 Sep 2019 10:39:19 +0300 Subject: [PATCH] Moved TaskBuilder to common. --- build.gradle.kts | 6 ++-- ...astDataNode.kt => TypeFilteredDataNode.kt} | 9 ++++-- .../kotlin/hep/dataforge/data/dataJVM.kt | 29 +++++++++++-------- .../hep/dataforge/io/TaggedEnvelopeFormat.kt | 1 - .../hep/dataforge/workspace/TaskBuilder.kt | 4 +-- 5 files changed, 28 insertions(+), 21 deletions(-) rename dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/{CastDataNode.kt => TypeFilteredDataNode.kt} (58%) rename dataforge-workspace/src/{jvmMain => commonMain}/kotlin/hep/dataforge/workspace/TaskBuilder.kt (98%) diff --git a/build.gradle.kts b/build.gradle.kts index 495d9a74..41cf03f2 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,9 +1,9 @@ plugins { - id("scientifik.mpp") version "0.1.6" apply false - id("scientifik.publish") version "0.1.6" apply false + id("scientifik.mpp") version "0.1.7-dev" apply false + id("scientifik.publish") version "0.1.7-dev" apply false } -val dataforgeVersion by extra("0.1.4-dev-1") +val dataforgeVersion by extra("0.1.4-dev-2") val bintrayRepo by extra("dataforge") val githubProject by extra("dataforge-core") diff --git a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/CastDataNode.kt b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/TypeFilteredDataNode.kt similarity index 58% rename from dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/CastDataNode.kt rename to dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/TypeFilteredDataNode.kt index 79a00075..5e90c4ed 100644 --- a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/CastDataNode.kt +++ b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/TypeFilteredDataNode.kt @@ -4,17 +4,20 @@ import hep.dataforge.names.NameToken import kotlin.reflect.KClass -class CastDataNode(val origin: DataNode, override val type: KClass) : DataNode { +/** + * A zero-copy data node wrapper that returns only children with appropriate type. + */ +class TypeFilteredDataNode(val origin: DataNode<*>, override val type: KClass) : DataNode { override val items: Map> by lazy { origin.items.mapNotNull { (key, item) -> when (item) { is DataItem.Leaf -> { - (item.value.safeCast(type))?.let { + (item.value.withType(type))?.let { key to DataItem.Leaf(it) } } is DataItem.Node -> { - key to DataItem.Node(item.value.safeCast(type)) + key to DataItem.Node(item.value.withType(type)) } } }.associate { it } 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 b2ce7bb6..395f92b1 100644 --- a/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt +++ b/dataforge-data/src/jvmMain/kotlin/hep/dataforge/data/dataJVM.kt @@ -19,28 +19,33 @@ actual fun DataNode<*>.canCast(type: KClass): Boolean = actual fun Data<*>.canCast(type: KClass): Boolean = this.type.isSubclassOf(type) - -fun Data<*>.safeCast(type: KClass): Data? = +/** + * Cast the node to given type if the cast is possible or return null + */ +fun Data<*>.withType(type: KClass): Data? = if (canCast(type)) cast(type) else null /** * 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<*>.safeCast(type: KClass): DataNode { - return if (this is CastDataNode) { - origin.safeCast(type) +fun DataNode<*>.withType(type: KClass): DataNode { + return if (canCast(type)) { + cast(type) + } else if (this is TypeFilteredDataNode) { + origin.withType(type) } else { - CastDataNode(this, type) + TypeFilteredDataNode(this, type) } } -fun DataItem<*>?.safeCast(type: KClass): DataItem? = when (this) { +/** + * Filter all elements of given data item that could be cast to given type. If no elements are available, return null. + */ +fun DataItem<*>?.withType(type: KClass): DataItem? = when (this) { null -> null - is DataItem.Node -> DataItem.Node(this.value.safeCast(type)) - is DataItem.Leaf -> DataItem.Leaf( - this.value.safeCast(type) ?: error("Can't cast data with type ${this.value.type} to $type") - ) + is DataItem.Node -> DataItem.Node(this.value.withType(type)) + is DataItem.Leaf -> this.value.withType(type)?.let { DataItem.Leaf(it) } } -inline fun DataItem<*>?.safeCast(): DataItem? = safeCast(R::class) \ No newline at end of file +inline fun DataItem<*>?.withType(): DataItem? = this@withType.withType(R::class) \ No newline at end of file diff --git a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt index 7bb04ec4..20fc8632 100644 --- a/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt +++ b/dataforge-io/src/commonMain/kotlin/hep/dataforge/io/TaggedEnvelopeFormat.kt @@ -4,7 +4,6 @@ import hep.dataforge.names.Name import hep.dataforge.names.plus import kotlinx.io.core.* - @ExperimentalUnsignedTypes object TaggedEnvelopeFormat : EnvelopeFormat { const val VERSION = "DF03" diff --git a/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt similarity index 98% rename from dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt rename to dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt index ac068a56..f999260c 100644 --- a/dataforge-workspace/src/jvmMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt +++ b/dataforge-workspace/src/commonMain/kotlin/hep/dataforge/workspace/TaskBuilder.kt @@ -41,7 +41,7 @@ class TaskBuilder(val name: String) { } fun transform( - inputType: KClass, + inputType: KClass, from: String = "", to: String = "", block: TaskEnv.(DataNode) -> DataNode @@ -49,7 +49,7 @@ class TaskBuilder(val name: String) { dataTransforms += DataTransformation(from, to) { context, model, data -> data.ensureType(inputType) val env = TaskEnv(EmptyName, model.meta, context) - env.block(data.safeCast(inputType)) + env.block(data.cast(inputType)) } }