
commonMain.space.kscience.dataforge.data.StaticDataTree.kt Maven / Gradle / Ivy
package space.kscience.dataforge.data
import kotlinx.coroutines.coroutineScope
import kotlinx.coroutines.flow.collect
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.*
import kotlin.reflect.KType
import kotlin.reflect.typeOf
@PublishedApi
internal class StaticDataTree(
override val dataType: KType,
) : DataSetBuilder, DataTree {
private val items: MutableMap> = HashMap()
override suspend fun items(): Map> = items.filter { !it.key.body.startsWith("@") }
override suspend fun remove(name: Name) {
when (name.length) {
0 -> error("Can't remove root tree node")
1 -> items.remove(name.firstOrNull()!!)
else -> (items[name.firstOrNull()!!].tree as? StaticDataTree)?.remove(name.cutFirst())
}
}
private fun getOrCreateNode(name: Name): StaticDataTree = when (name.length) {
0 -> this
1 -> {
val itemName = name.firstOrNull()!!
(items[itemName].tree as? StaticDataTree) ?: StaticDataTree(dataType).also {
items[itemName] = DataTreeItem.Node(it)
}
}
else -> getOrCreateNode(name.cutLast()).getOrCreateNode(name.lastOrNull()!!.asName())
}
private suspend fun set(name: Name, item: DataTreeItem?) {
if (name.isEmpty()) error("Can't set top level tree node")
if (item == null) {
remove(name)
} else {
getOrCreateNode(name.cutLast()).items[name.lastOrNull()!!] = item
}
}
override suspend fun emit(name: Name, data: Data?) {
set(name, data?.let { DataTreeItem.Leaf(it) })
}
override suspend fun emit(name: Name, dataSet: DataSet) {
if (dataSet is StaticDataTree) {
set(name, DataTreeItem.Node(dataSet))
} else {
coroutineScope {
dataSet.flow().collect {
emit(name + it.name, it.data)
}
}
}
}
}
@Suppress("FunctionName")
public suspend fun DataTree(
dataType: KType,
block: suspend DataSetBuilder.() -> Unit,
): DataTree = StaticDataTree(dataType).apply { block() }
@Suppress("FunctionName")
public suspend inline fun DataTree(
noinline block: suspend DataSetBuilder.() -> Unit,
): DataTree = DataTree(typeOf(), block)
@OptIn(DFExperimental::class)
public suspend fun DataSet.seal(): DataTree = DataTree(dataType){
populate(this@seal)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy