Moved TaskBuilder to common.

This commit is contained in:
Alexander Nozik 2019-09-12 10:39:19 +03:00
parent c239abe6e8
commit 61c2530c91
5 changed files with 28 additions and 21 deletions

View File

@ -1,9 +1,9 @@
plugins { plugins {
id("scientifik.mpp") version "0.1.6" apply false id("scientifik.mpp") version "0.1.7-dev" apply false
id("scientifik.publish") version "0.1.6" 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 bintrayRepo by extra("dataforge")
val githubProject by extra("dataforge-core") val githubProject by extra("dataforge-core")

View File

@ -4,17 +4,20 @@ import hep.dataforge.names.NameToken
import kotlin.reflect.KClass import kotlin.reflect.KClass
class CastDataNode<out T : Any>(val origin: DataNode<Any>, override val type: KClass<out T>) : DataNode<T> { /**
* A zero-copy data node wrapper that returns only children with appropriate type.
*/
class TypeFilteredDataNode<out T : Any>(val origin: DataNode<*>, override val type: KClass<out T>) : DataNode<T> {
override val items: Map<NameToken, DataItem<T>> by lazy { override val items: Map<NameToken, DataItem<T>> by lazy {
origin.items.mapNotNull { (key, item) -> origin.items.mapNotNull { (key, item) ->
when (item) { when (item) {
is DataItem.Leaf -> { is DataItem.Leaf -> {
(item.value.safeCast(type))?.let { (item.value.withType(type))?.let {
key to DataItem.Leaf(it) key to DataItem.Leaf(it)
} }
} }
is DataItem.Node -> { is DataItem.Node -> {
key to DataItem.Node(item.value.safeCast(type)) key to DataItem.Node(item.value.withType(type))
} }
} }
}.associate { it } }.associate { it }

View File

@ -19,28 +19,33 @@ actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean =
actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean = actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean =
this.type.isSubclassOf(type) this.type.isSubclassOf(type)
/**
fun <R : Any> Data<*>.safeCast(type: KClass<out R>): Data<R>? = * Cast the node to given type if the cast is possible or return null
*/
fun <R : Any> Data<*>.withType(type: KClass<out R>): Data<R>? =
if (canCast(type)) cast(type) else null 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], * 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 * but could contain empty nodes
*/ */
fun <R : Any> DataNode<*>.safeCast(type: KClass<out R>): DataNode<R> { fun <R : Any> DataNode<*>.withType(type: KClass<out R>): DataNode<R> {
return if (this is CastDataNode) { return if (canCast(type)) {
origin.safeCast(type) cast(type)
} else if (this is TypeFilteredDataNode) {
origin.withType(type)
} else { } else {
CastDataNode(this, type) TypeFilteredDataNode(this, type)
} }
} }
fun <R : Any> DataItem<*>?.safeCast(type: KClass<out R>): DataItem<R>? = when (this) { /**
* Filter all elements of given data item that could be cast to given type. If no elements are available, return null.
*/
fun <R : Any> DataItem<*>?.withType(type: KClass<out R>): DataItem<R>? = when (this) {
null -> null null -> null
is DataItem.Node -> DataItem.Node(this.value.safeCast(type)) is DataItem.Node -> DataItem.Node(this.value.withType(type))
is DataItem.Leaf -> DataItem.Leaf( is DataItem.Leaf -> this.value.withType(type)?.let { DataItem.Leaf(it) }
this.value.safeCast(type) ?: error("Can't cast data with type ${this.value.type} to $type")
)
} }
inline fun <reified R : Any> DataItem<*>?.safeCast(): DataItem<R>? = safeCast(R::class) inline fun <reified R : Any> DataItem<*>?.withType(): DataItem<R>? = this@withType.withType(R::class)

View File

@ -4,7 +4,6 @@ import hep.dataforge.names.Name
import hep.dataforge.names.plus import hep.dataforge.names.plus
import kotlinx.io.core.* import kotlinx.io.core.*
@ExperimentalUnsignedTypes @ExperimentalUnsignedTypes
object TaggedEnvelopeFormat : EnvelopeFormat { object TaggedEnvelopeFormat : EnvelopeFormat {
const val VERSION = "DF03" const val VERSION = "DF03"

View File

@ -41,7 +41,7 @@ class TaskBuilder(val name: String) {
} }
fun <T : Any> transform( fun <T : Any> transform(
inputType: KClass<T>, inputType: KClass<out T>,
from: String = "", from: String = "",
to: String = "", to: String = "",
block: TaskEnv.(DataNode<T>) -> DataNode<Any> block: TaskEnv.(DataNode<T>) -> DataNode<Any>
@ -49,7 +49,7 @@ class TaskBuilder(val name: String) {
dataTransforms += DataTransformation(from, to) { context, model, data -> dataTransforms += DataTransformation(from, to) { context, model, data ->
data.ensureType(inputType) data.ensureType(inputType)
val env = TaskEnv(EmptyName, model.meta, context) val env = TaskEnv(EmptyName, model.meta, context)
env.block(data.safeCast(inputType)) env.block(data.cast(inputType))
} }
} }