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 {
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")

View File

@ -4,17 +4,20 @@ import hep.dataforge.names.NameToken
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 {
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 }

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 =
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
/**
* 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 <R : Any> DataNode<*>.safeCast(type: KClass<out R>): DataNode<R> {
return if (this is CastDataNode) {
origin.safeCast(type)
fun <R : Any> DataNode<*>.withType(type: KClass<out R>): DataNode<R> {
return if (canCast(type)) {
cast(type)
} else if (this is TypeFilteredDataNode) {
origin.withType(type)
} 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
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 <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 kotlinx.io.core.*
@ExperimentalUnsignedTypes
object TaggedEnvelopeFormat : EnvelopeFormat {
const val VERSION = "DF03"

View File

@ -41,7 +41,7 @@ class TaskBuilder(val name: String) {
}
fun <T : Any> transform(
inputType: KClass<T>,
inputType: KClass<out T>,
from: String = "",
to: String = "",
block: TaskEnv.(DataNode<T>) -> DataNode<Any>
@ -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))
}
}