All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.space.kscience.dataforge.data.StaticDataTree.kt Maven / Gradle / Ivy

There is a newer version: 0.7.0
Show newest version
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