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

commonMain.space.kscience.dataforge.data.DataSetBuilder.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.Flow
import kotlinx.coroutines.flow.collect
import space.kscience.dataforge.meta.Meta
import space.kscience.dataforge.meta.MutableMeta
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.plus
import kotlin.reflect.KType

public interface DataSetBuilder {
    public val dataType: KType

    /**
     * Remove all data items starting with [name]
     */
    public suspend fun remove(name: Name)

    public suspend fun emit(name: Name, data: Data?)

    /**
     * Set a current state of given [dataSet] into a branch [name]. Does not propagate updates
     */
    public suspend fun emit(name: Name, dataSet: DataSet) {
        //remove previous items
        if (name != Name.EMPTY) {
            remove(name)
        }

        //Set new items
        dataSet.flow().collect {
            emit(name + it.name, it.data)
        }
    }

    /**
     * Append data to node
     */
    public suspend infix fun String.put(data: Data): Unit = emit(Name.parse(this), data)

    /**
     * Append node
     */
    public suspend infix fun String.put(dataSet: DataSet): Unit = emit(Name.parse(this), dataSet)

    /**
     * Build and append node
     */
    public suspend infix fun String.put(block: suspend DataSetBuilder.() -> Unit): Unit = emit(Name.parse(this), block)
}

private class SubSetBuilder(
    private val parent: DataSetBuilder,
    private val branch: Name,
) : DataSetBuilder {
    override val dataType: KType get() = parent.dataType

    override suspend fun remove(name: Name) {
        parent.remove(branch + name)
    }

    override suspend fun emit(name: Name, data: Data?) {
        parent.emit(branch + name, data)
    }

    override suspend fun emit(name: Name, dataSet: DataSet) {
        parent.emit(branch + name, dataSet)
    }
}

public suspend fun  DataSetBuilder.emit(name: Name, block: suspend DataSetBuilder.() -> Unit) {
    SubSetBuilder(this, name).apply { block() }
}


public suspend fun  DataSetBuilder.emit(name: String, data: Data) {
    emit(Name.parse(name), data)
}

public suspend fun  DataSetBuilder.emit(name: String, set: DataSet) {
    this.emit(Name.parse(name), set)
}

public suspend fun  DataSetBuilder.emit(name: String, block: suspend DataSetBuilder.() -> Unit): Unit =
    [email protected](Name.parse(name), block)

public suspend fun  DataSetBuilder.emit(data: NamedData) {
    emit(data.name, data.data)
}

/**
 * Produce lazy [Data] and emit it into the [DataSetBuilder]
 */
public suspend inline fun  DataSetBuilder.produce(
    name: String,
    meta: Meta = Meta.EMPTY,
    noinline producer: suspend () -> T,
) {
    val data = Data(meta, block = producer)
    emit(name, data)
}

public suspend inline fun  DataSetBuilder.produce(
    name: Name,
    meta: Meta = Meta.EMPTY,
    noinline producer: suspend () -> T,
) {
    val data = Data(meta, block = producer)
    emit(name, data)
}

/**
 * Emit a static data with the fixed value
 */
public suspend inline fun  DataSetBuilder.static(
    name: String,
    data: T,
    meta: Meta = Meta.EMPTY
): Unit =
    emit(name, Data.static(data, meta))

public suspend inline fun  DataSetBuilder.static(
    name: Name,
    data: T,
    meta: Meta = Meta.EMPTY
): Unit =
    emit(name, Data.static(data, meta))

public suspend inline fun  DataSetBuilder.static(
    name: String,
    data: T,
    mutableMeta: MutableMeta.() -> Unit,
): Unit = emit(Name.parse(name), Data.static(data, Meta(mutableMeta)))

/**
 * Update data with given node data and meta with node meta.
 */
@DFExperimental
public suspend fun  DataSetBuilder.populate(tree: DataSet): Unit = coroutineScope {
    tree.flow().collect {
        //TODO check if the place is occupied
        emit(it.name, it.data)
    }
}

public suspend fun  DataSetBuilder.populate(flow: Flow>) {
    flow.collect {
        emit(it.name, it.data)
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy