From 66ce15ae6d90d1fce9648748a73a9959274dc436 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Sun, 4 Feb 2024 13:54:08 +0300 Subject: [PATCH 01/26] Hot-fix for scheme initialization --- build.gradle.kts | 2 +- .../kscience/dataforge/data/ActionsTest.kt | 2 +- dataforge-meta/api/dataforge-meta.api | 9 ++++- .../kscience/dataforge/meta/MutableMeta.kt | 5 +++ .../space/kscience/dataforge/meta/Scheme.kt | 40 +++++++++---------- .../meta/descriptors/MetaDescriptorBuilder.kt | 3 -- .../meta/descriptors/schemeDescriptor.kt | 9 +++-- .../kscience/dataforge/meta/SchemeTest.kt | 23 ++++++++++- 8 files changed, 61 insertions(+), 32 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index b9349868..8be3a7b0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { allprojects { group = "space.kscience" - version = "0.8.0" + version = "0.8.1" } subprojects { diff --git a/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt b/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt index 4aa6e6d4..f6eae12c 100644 --- a/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt +++ b/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt @@ -42,7 +42,7 @@ internal class ActionsTest { source.wrap(it.toString(), it) } - delay(10) + delay(20) source.close() result.awaitClose() diff --git a/dataforge-meta/api/dataforge-meta.api b/dataforge-meta/api/dataforge-meta.api index 49f28259..f9834c54 100644 --- a/dataforge-meta/api/dataforge-meta.api +++ b/dataforge-meta/api/dataforge-meta.api @@ -433,6 +433,7 @@ public final class space/kscience/dataforge/meta/MutableMetaDelegateKt { public final class space/kscience/dataforge/meta/MutableMetaKt { public static final fun ObservableMutableMeta ()Lspace/kscience/dataforge/meta/ObservableMutableMeta; public static final fun ObservableMutableMeta (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; + public static final fun ObservableMutableMeta (Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; public static synthetic fun ObservableMutableMeta$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; public static final fun append (Lspace/kscience/dataforge/meta/MutableMeta;Ljava/lang/String;Lspace/kscience/dataforge/meta/Meta;)V public static final fun append (Lspace/kscience/dataforge/meta/MutableMeta;Ljava/lang/String;Lspace/kscience/dataforge/meta/Value;)V @@ -538,6 +539,8 @@ public final class space/kscience/dataforge/meta/RegexItemTransformationRule : s public class space/kscience/dataforge/meta/Scheme : space/kscience/dataforge/meta/Configurable, space/kscience/dataforge/meta/MetaRepr, space/kscience/dataforge/meta/MutableMetaProvider, space/kscience/dataforge/meta/descriptors/Described { public fun <init> ()V + public fun <init> (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)V + public synthetic fun <init> (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILkotlin/jvm/internal/DefaultConstructorMarker;)V public synthetic fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; public fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMeta; public final fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; @@ -555,6 +558,10 @@ public final class space/kscience/dataforge/meta/SchemeKt { public static final fun copy (Lspace/kscience/dataforge/meta/Scheme;Lspace/kscience/dataforge/meta/SchemeSpec;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/Scheme; public static synthetic fun copy$default (Lspace/kscience/dataforge/meta/Scheme;Lspace/kscience/dataforge/meta/SchemeSpec;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/Scheme; public static final fun invoke (Lspace/kscience/dataforge/meta/Scheme;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/Scheme; + public static final fun listOfScheme (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/SchemeSpec;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static final fun listOfScheme (Lspace/kscience/dataforge/meta/Scheme;Lspace/kscience/dataforge/meta/SchemeSpec;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun listOfScheme$default (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/SchemeSpec;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun listOfScheme$default (Lspace/kscience/dataforge/meta/Scheme;Lspace/kscience/dataforge/meta/SchemeSpec;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun scheme (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/SchemeSpec;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static final fun scheme (Lspace/kscience/dataforge/meta/Scheme;Lspace/kscience/dataforge/meta/SchemeSpec;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; public static synthetic fun scheme$default (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/SchemeSpec;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; @@ -837,7 +844,6 @@ public final class space/kscience/dataforge/meta/descriptors/MetaDescriptorBuild public final fun getDefault ()Lspace/kscience/dataforge/meta/Value; public final fun getDescription ()Ljava/lang/String; public final fun getIndexKey ()Ljava/lang/String; - public final fun getInfo ()Ljava/lang/String; public final fun getMultiple ()Z public final fun getValueRestriction ()Lspace/kscience/dataforge/meta/descriptors/ValueRestriction; public final fun getValueTypes ()Ljava/util/List; @@ -847,7 +853,6 @@ public final class space/kscience/dataforge/meta/descriptors/MetaDescriptorBuild public final fun setDefault (Lspace/kscience/dataforge/meta/Value;)V public final fun setDescription (Ljava/lang/String;)V public final fun setIndexKey (Ljava/lang/String;)V - public final fun setInfo (Ljava/lang/String;)V public final fun setMultiple (Z)V public final fun setValueRestriction (Lspace/kscience/dataforge/meta/descriptors/ValueRestriction;)V public final fun setValueTypes (Ljava/util/List;)V diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt index 231f9e54..d3453c4d 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt @@ -378,6 +378,11 @@ public fun Meta.asMutableMeta(): MutableMeta = (this as? MutableMeta) ?: toMutab @JsName("newObservableMutableMeta") public fun ObservableMutableMeta(): ObservableMutableMeta = MutableMetaImpl(null) +/** + * Create a pre-filled [ObservableMutableMeta] + */ +public fun ObservableMutableMeta(content: Meta): ObservableMutableMeta = ObservableMutableMeta { update(content) } + /** * Build a [MutableMeta] using given transformation */ diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt index 2e9edc1d..c330de99 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt @@ -13,32 +13,28 @@ import kotlin.reflect.KProperty1 /** * A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [MetaSpec]. - * Default item provider and [MetaDescriptor] are optional + * + * @param prototype default values provided by this scheme */ -public open class Scheme : Described, MetaRepr, MutableMetaProvider, Configurable { +public open class Scheme( + private var prototype: Meta? = null, + descriptor: MetaDescriptor? = null +) : Described, MetaRepr, MutableMetaProvider, Configurable { /** * Meta to be mutated by this scheme */ - private var target: MutableMeta? = null - get() { - // automatic initialization of target if it is missing - if (field == null) { - field = MutableMeta() - } - return field - } + internal var target: MutableMeta = MutableMeta() /** - * Default values provided by this scheme + * A descriptor of this scheme */ - private var prototype: Meta? = null + final override var descriptor: MetaDescriptor? = descriptor + private set + final override val meta: ObservableMutableMeta = SchemeMeta(Name.EMPTY) - final override var descriptor: MetaDescriptor? = null - private set - /** * This method must be called before the scheme could be used */ @@ -90,7 +86,7 @@ public open class Scheme : Described, MetaRepr, MutableMetaProvider, Configurabl ?: descriptor?.get(pathName)?.defaultValue set(value) { val oldValue = target[pathName]?.value - target!![pathName] = value + target[pathName] = value if (oldValue != value) { invalidate(Name.EMPTY) } @@ -126,7 +122,7 @@ public open class Scheme : Described, MetaRepr, MutableMetaProvider, Configurabl override fun hashCode(): Int = Meta.hashCode(this) override fun set(name: Name, node: Meta?) { - target!![name] = node + target[name] = node invalidate(name) } @@ -176,15 +172,19 @@ public open class SchemeSpec<T : Scheme>( it.initialize(MutableMeta(), source, descriptor) } + /** + * Write changes made to the [Scheme] to target [MutableMeta]. If the empty [Scheme] contains any data it is copied to the target. + */ public fun write(target: MutableMeta): T = empty().also { + target.update(it.meta) it.initialize(target, Meta.EMPTY, descriptor) } /** - * Generate an empty object + * Generate a blank object. The object could contain some elements if they are defined in a constructor */ public fun empty(): T = builder().also { - it.initialize(MutableMeta(), Meta.EMPTY, descriptor) + it.initialize(MutableMeta(), it.target, descriptor) } override fun convert(obj: T): Meta = obj.meta @@ -269,7 +269,6 @@ public fun <T : Scheme> Scheme.schemeOrNull( * If children are mutable, the changes in list elements are reflected on them. * The list is a snapshot of children state, so change in structure is not reflected on its composition. */ -@DFExperimental public fun <T : Scheme> MutableMeta.listOfScheme( spec: SchemeSpec<T>, key: Name? = null, @@ -286,7 +285,6 @@ public fun <T : Scheme> MutableMeta.listOfScheme( } -@DFExperimental public fun <T : Scheme> Scheme.listOfScheme( spec: SchemeSpec<T>, key: Name? = null, diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt index 5d4d81ad..2291e3d3 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt @@ -11,9 +11,6 @@ import kotlin.collections.set public class MetaDescriptorBuilder @PublishedApi internal constructor() { public var description: String? = null - @Deprecated("Replace by description", ReplaceWith("description")) - public var info: String? by ::description - public var children: MutableMap<String, MetaDescriptorBuilder> = linkedMapOf() public var multiple: Boolean = false public var valueRestriction: ValueRestriction = ValueRestriction.NONE diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/schemeDescriptor.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/schemeDescriptor.kt index a2a77182..c7b73508 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/schemeDescriptor.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/schemeDescriptor.kt @@ -3,11 +3,12 @@ package space.kscience.dataforge.meta.descriptors import space.kscience.dataforge.meta.Scheme import space.kscience.dataforge.meta.SchemeSpec import space.kscience.dataforge.meta.ValueType -import space.kscience.dataforge.misc.DFExperimental import kotlin.reflect.KProperty1 import kotlin.reflect.typeOf -@DFExperimental +/** + * Add a value item to a [MetaDescriptor] inferring some of its properties from the type + */ public inline fun <S : Scheme, reified T> MetaDescriptorBuilder.value( property: KProperty1<S, T>, noinline block: MetaDescriptorBuilder.() -> Unit = {}, @@ -39,7 +40,9 @@ public inline fun <S : Scheme, reified T> MetaDescriptorBuilder.value( else -> node(property.name, block) } -@DFExperimental +/** + * Add a schem-based branch to a [MetaDescriptor] + */ public inline fun <S : Scheme, reified T : Scheme> MetaDescriptorBuilder.scheme( property: KProperty1<S, T>, spec: SchemeSpec<T>, diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SchemeTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SchemeTest.kt index bb2736ce..eaa766d8 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SchemeTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SchemeTest.kt @@ -5,7 +5,18 @@ import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertNotNull -@DFExperimental + +private class SchemeWithInit: Scheme(){ + init { + set("initial", "initialValue") + } + + var initial by string() + companion object: SchemeSpec<SchemeWithInit>(::SchemeWithInit) +} + + + class SchemeTest { @Test fun testSchemeWrappingBeforeEdit() { @@ -15,6 +26,7 @@ class SchemeTest { assertEquals(29, config["a"].int) } + @OptIn(DFExperimental::class) @Test fun testSchemeWrappingAfterEdit() { val scheme = TestScheme.empty() @@ -46,4 +58,13 @@ class SchemeTest { scheme.v = ListValue(1.0, 2.0, 3.0) assertNotNull(value) } + + + @Test + fun testSchemeWithInit(){ + val scheme = SchemeWithInit() + assertEquals("initialValue", scheme.initial) + scheme.initial = "none" + assertEquals("none", scheme.initial) + } } \ No newline at end of file From 78641f6f877b1e521e662e6596192e9da214f6e0 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Sun, 4 Feb 2024 13:54:44 +0300 Subject: [PATCH 02/26] Roll-back version --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 8be3a7b0..b9349868 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { allprojects { group = "space.kscience" - version = "0.8.1" + version = "0.8.0" } subprojects { From 0e5a31db9f2b232baed5b475cdd5052f1923cad1 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Tue, 6 Feb 2024 10:21:05 +0300 Subject: [PATCH 03/26] Hot fix for observable meta wrapper --- .../space/kscience/dataforge/meta/ObservableMetaWrapper.kt | 4 ++-- .../space/kscience/dataforge/meta/ObservableMetaTest.kt | 2 ++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMetaWrapper.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMetaWrapper.kt index 71e15aa9..abd2deb6 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMetaWrapper.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMetaWrapper.kt @@ -15,9 +15,9 @@ private class ObservableMetaWrapper( val listeners: MutableSet<MetaListener>, ) : ObservableMutableMeta { override val items: Map<NameToken, ObservableMutableMeta> - get() = root.items.keys.associateWith { + get() = root[nodeName]?.items?.keys?.associateWith { ObservableMetaWrapper(root, nodeName + it, listeners) - } + } ?: emptyMap() override fun get(name: Name): ObservableMutableMeta? = if (root[nodeName + name] == null) { null diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/ObservableMetaTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/ObservableMetaTest.kt index 4681ec12..2d6cc36f 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/ObservableMetaTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/ObservableMetaTest.kt @@ -17,6 +17,8 @@ class ObservableMetaTest { } }.asObservable() + println(meta) + assertEquals("scatter", meta["data.type"].string) } From 4197b4bb6165f5847d1d84359a67702894b337a6 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Tue, 6 Feb 2024 14:36:20 +0300 Subject: [PATCH 04/26] Add ordering to name indices --- CHANGELOG.md | 2 ++ build.gradle.kts | 2 +- .../kscience/dataforge/io/EnvelopeParts.kt | 3 +- .../dataforge/meta/MutableMetaDelegate.kt | 3 +- .../space/kscience/dataforge/meta/Scheme.kt | 7 ++--- .../dataforge/names/NameIndexComparator.kt | 30 +++++++++++++++++++ .../dataforge/meta/ObservableMetaTest.kt | 2 -- 7 files changed, 40 insertions(+), 9 deletions(-) create mode 100644 dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/NameIndexComparator.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index b9d3b6a9..e5d85a2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased ### Added +- Name index comparator ### Changed @@ -11,6 +12,7 @@ ### Removed ### Fixed +- `listOfScheme` and `listOfConvertable` delegates provides correct items order ### Security diff --git a/build.gradle.kts b/build.gradle.kts index b9349868..d41918ac 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { allprojects { group = "space.kscience" - version = "0.8.0" + version = "0.8.1-dev-1" } subprojects { diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeParts.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeParts.kt index 183e7b03..88231899 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeParts.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeParts.kt @@ -11,6 +11,7 @@ import space.kscience.dataforge.io.PartDescriptor.Companion.PARTS_KEY import space.kscience.dataforge.io.PartDescriptor.Companion.SEPARATOR_KEY import space.kscience.dataforge.meta.* import space.kscience.dataforge.names.asName +import space.kscience.dataforge.names.getIndexedList import space.kscience.dataforge.names.plus private class PartDescriptor : Scheme() { @@ -84,7 +85,7 @@ public fun EnvelopeBuilder.envelopes( public fun Envelope.parts(): EnvelopeParts { if (data == null) return emptyList() //TODO add zip folder reader - val parts = meta.getIndexed(PARTS_KEY).values.map { + val parts = meta.getIndexedList(PARTS_KEY).map { PartDescriptor.read(it) } return if (parts.isEmpty()) { diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt index f6e96109..70c4aceb 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt @@ -4,6 +4,7 @@ import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName +import space.kscience.dataforge.names.getIndexedList import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty @@ -65,7 +66,7 @@ public fun <T> MutableMeta.listOfConvertable( ): ReadWriteProperty<Any?, List<T>> = object : ReadWriteProperty<Any?, List<T>> { override fun getValue(thisRef: Any?, property: KProperty<*>): List<T> { val name = key ?: property.name.asName() - return getIndexed(name).values.map { converter.read(it) } + return getIndexedList(name).map { converter.read(it) } } override fun setValue(thisRef: Any?, property: KProperty<*>, value: List<T>) { diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt index c330de99..96b6df49 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt @@ -18,7 +18,7 @@ import kotlin.reflect.KProperty1 */ public open class Scheme( private var prototype: Meta? = null, - descriptor: MetaDescriptor? = null + descriptor: MetaDescriptor? = null, ) : Described, MetaRepr, MutableMetaProvider, Configurable { /** @@ -187,7 +187,7 @@ public open class SchemeSpec<T : Scheme>( it.initialize(MutableMeta(), it.target, descriptor) } - override fun convert(obj: T): Meta = obj.meta + override fun convert(obj: T): Meta = obj.meta /** * A convenience method to use specifications in builders @@ -197,7 +197,6 @@ public open class SchemeSpec<T : Scheme>( } - /** * Update a [MutableMeta] using given specification */ @@ -275,7 +274,7 @@ public fun <T : Scheme> MutableMeta.listOfScheme( ): ReadWriteProperty<Any?, List<T>> = object : ReadWriteProperty<Any?, List<T>> { override fun getValue(thisRef: Any?, property: KProperty<*>): List<T> { val name = key ?: property.name.asName() - return getIndexed(name).values.map { spec.write(it as MutableMeta) } + return getIndexedList(name).map { spec.write(it as MutableMeta) } } override fun setValue(thisRef: Any?, property: KProperty<*>, value: List<T>) { diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/NameIndexComparator.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/NameIndexComparator.kt new file mode 100644 index 00000000..742f8ebb --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/NameIndexComparator.kt @@ -0,0 +1,30 @@ +package space.kscience.dataforge.names + +import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.meta.getIndexed + + +/** + * A comparator for indices in a [Name]. If both indices are integers, compare them as integers. + * Null always stays "before" non-null index. + */ +public object NameIndexComparator : Comparator<String?> { + override fun compare(a: String?, b: String?): Int { + if (a == b) return 0 + if (a == null) return 1 + if (b == null) return -1 + val aInt = a.toIntOrNull() + val bInt = b.toIntOrNull() + return if (aInt != null && bInt != null) { + aInt.compareTo(bInt) + } else { + a.compareTo(b) + } + } + +} + +public fun Meta.getIndexedList(name: Name): List<Meta> = getIndexed(name).entries.sortedWith( + //sort by index + compareBy(space.kscience.dataforge.names.NameIndexComparator) { it.key } +).map{it.value} \ No newline at end of file diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/ObservableMetaTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/ObservableMetaTest.kt index 2d6cc36f..4681ec12 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/ObservableMetaTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/ObservableMetaTest.kt @@ -17,8 +17,6 @@ class ObservableMetaTest { } }.asObservable() - println(meta) - assertEquals("scatter", meta["data.type"].string) } From e850ca4145535ce8b230e888c303c4346ca1d55d Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Sun, 18 Feb 2024 18:34:26 +0300 Subject: [PATCH 05/26] minor refactoring --- .../dataforge/actions/AbstractAction.kt | 14 ++++---- .../kscience/dataforge/actions/MapAction.kt | 4 +-- .../kscience/dataforge/actions/SplitAction.kt | 4 +-- .../kscience/dataforge/data/NamedData.kt | 2 +- .../kscience/dataforge/meta/MutableMeta.kt | 33 +++++++++++++++---- .../kscience/dataforge/meta/SealedMeta.kt | 4 ++- .../space/kscience/dataforge/meta/MetaTest.kt | 29 ++++++++++++++++ gradle/wrapper/gradle-wrapper.properties | 2 +- 8 files changed, 72 insertions(+), 20 deletions(-) diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/AbstractAction.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/AbstractAction.kt index 7cd1ced5..1802e488 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/AbstractAction.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/AbstractAction.kt @@ -37,21 +37,23 @@ public abstract class AbstractAction<T : Any, R : Any>( * Update part of the data set using provided data * * @param source the source data tree in case we need several data items to update + * @param meta the metadata used for the whole data tree + * @param updatedData an updated item */ protected open fun DataSink<R>.update( source: DataTree<T>, meta: Meta, - namedData: NamedData<T>, - ){ + updatedData: NamedData<T>, + ) { //by default regenerate the whole data set - generate(source,meta) + generate(source, meta) } @OptIn(DFInternal::class) override fun execute( dataSet: DataTree<T>, meta: Meta, - ): DataTree<R> = if(dataSet.isObservable()) { + ): DataTree<R> = if (dataSet.isObservable()) { MutableDataTree<R>(outputType, dataSet.updatesScope).apply { generate(dataSet, meta) dataSet.updates().onEach { @@ -64,8 +66,8 @@ public abstract class AbstractAction<T : Any, R : Any>( close() } } - } else{ - DataTree(outputType){ + } else { + DataTree(outputType) { generate(dataSet, meta) } } diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt index 1f40ed73..fafb2d55 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt @@ -86,8 +86,8 @@ internal class MapAction<T : Any, R : Any>( data.forEach { mapOne(it.name, it.data, meta) } } - override fun DataSink<R>.update(source: DataTree<T>, meta: Meta, namedData: NamedData<T>) { - mapOne(namedData.name, namedData.data, namedData.meta) + override fun DataSink<R>.update(source: DataTree<T>, meta: Meta, updatedData: NamedData<T>) { + mapOne(updatedData.name, updatedData.data, updatedData.meta) } } diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/SplitAction.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/SplitAction.kt index 057419a7..cacbf1ee 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/SplitAction.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/SplitAction.kt @@ -77,8 +77,8 @@ internal class SplitAction<T : Any, R : Any>( data.forEach { splitOne(it.name, it.data, meta) } } - override fun DataSink<R>.update(source: DataTree<T>, meta: Meta, namedData: NamedData<T>) { - splitOne(namedData.name, namedData.data, namedData.meta) + override fun DataSink<R>.update(source: DataTree<T>, meta: Meta, updatedData: NamedData<T>) { + splitOne(updatedData.name, updatedData.data, updatedData.meta) } } diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/NamedData.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/NamedData.kt index 63e36a3f..bf65292c 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/NamedData.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/NamedData.kt @@ -10,7 +10,7 @@ public interface NamedData<out T> : Named, Data<T> { } public operator fun NamedData<*>.component1(): Name = name -public operator fun <T: Any> NamedData<T>.component2(): Data<T> = data +public operator fun <T> NamedData<T>.component2(): Data<T> = data private class NamedDataImpl<T>( override val name: Name, diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt index d3453c4d..6e4a5daa 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt @@ -19,6 +19,10 @@ public annotation class MetaBuilderMarker public interface MutableMetaProvider : MetaProvider, MutableValueProvider { override fun get(name: Name): MutableMeta? public operator fun set(name: Name, node: Meta?) + + /** + * Set value with the given name. Does nothing if value is not changed. + */ override fun setValue(name: Name, value: Value?) } @@ -48,11 +52,13 @@ public interface MutableMeta : Meta, MutableMetaProvider { } override fun setValue(name: Name, value: Value?) { - getOrCreate(name).value = value + if (value != getValue(name)) { + getOrCreate(name).value = value + } } /** - * Get existing node or create a new one + * Get an existing node or create a new one */ public fun getOrCreate(name: Name): MutableMeta @@ -198,10 +204,8 @@ public operator fun MutableMetaProvider.set(key: String, metas: Iterable<Meta>): /** - * Update existing mutable node with another node. The rules are following: - * * value replaces anything - * * node updates node and replaces anything but node - * * node list updates node list if number of nodes in the list is the same and replaces anything otherwise + * Update the existing mutable node with another node. + * Values that are present in the current provider and are missing in [meta] are kept. */ public fun MutableMetaProvider.update(meta: Meta) { meta.valueSequence().forEach { (name, value) -> @@ -222,7 +226,7 @@ public fun <M : MutableTypedMeta<M>> MutableTypedMeta<M>.edit(name: Name, builde getOrCreate(name).apply(builder) /** - * Set a value at a given [name]. If node does not exist, create it. + * Set a value at a given [name]. If a node does not exist, create it. */ public operator fun <M : MutableTypedMeta<M>> MutableTypedMeta<M>.set(name: Name, value: Value?) { edit(name) { @@ -367,6 +371,21 @@ public fun MutableMeta.append(name: Name, value: Value): Unit = append(name, Met public fun MutableMeta.append(key: String, value: Value): Unit = append(Name.parse(key), value) +/** + * Update all items that exist in the [newMeta] and remove existing items that are missing in [newMeta]. + * This produces the same result as clearing all items and updating blank meta with a [newMeta], but does not + * produce unnecessary invalidation events (if they are supported). + */ +public fun MutableMeta.reset(newMeta: Meta) { + //remove old items + (items.keys - newMeta.items.keys).forEach { + remove(it.asName()) + } + newMeta.items.forEach { (token, item)-> + set(token, item) + } +} + /** * Create a mutable copy of this meta. The copy is created even if the Meta is already mutable */ diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/SealedMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/SealedMeta.kt index e842b990..b3fdf062 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/SealedMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/SealedMeta.kt @@ -76,6 +76,8 @@ internal class MetaBuilder( override fun set(name: Name, node: Meta?) { + //skip setting if value has not changed + if(node == get(name)) return when (name.length) { 0 -> error("Can't set a meta with empty name") 1 -> { @@ -89,7 +91,7 @@ internal class MetaBuilder( } else -> { - getOrCreate(name.first().asName()).set(name.cutFirst(), node) + getOrCreate(name.first().asName())[name.cutFirst()] = node } } } diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MetaTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MetaTest.kt index 85db7bd6..78b5cdb4 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MetaTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MetaTest.kt @@ -61,4 +61,33 @@ class MetaTest { assertEquals(null, indexed["8"]) assertEquals(12, indexed["12"].int) } + + @Test + fun reset() { + val oldMeta = MutableMeta { + "a" put { + "value" put "aValue" + } + "b" put { + "value" put "bValue" + } + "c" put { + "value" put "cValue" + } + } + val newMeta = Meta { + "a" put { + "value" put "aValue" + } + "b" put { + "value" put "bValue" + } + "d" put { + "value" put "dValue" + } + } + oldMeta.reset(newMeta) + println(oldMeta) + assertEquals(setOf("a", "b", "d"), oldMeta.items.keys.map { it.toString() }.toSet()) + } } \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index e411586a..17655d0e 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists From aa4c745819fd0e216df833f5a703023ec671b1fc Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Sun, 18 Feb 2024 18:43:33 +0300 Subject: [PATCH 06/26] remove unnecessary type limitations in actions --- .../space/kscience/dataforge/actions/AbstractAction.kt | 2 +- .../kotlin/space/kscience/dataforge/actions/MapAction.kt | 4 ++-- .../kotlin/space/kscience/dataforge/actions/ReduceAction.kt | 6 +++--- .../kotlin/space/kscience/dataforge/actions/SplitAction.kt | 6 +++--- .../kotlin/space/kscience/dataforge/data/GroupRule.kt | 4 ++-- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/AbstractAction.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/AbstractAction.kt index 1802e488..00201a90 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/AbstractAction.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/AbstractAction.kt @@ -21,7 +21,7 @@ internal fun MutableMap<Name, *>.removeWhatStartsWith(name: Name) { /** * An action that caches results on-demand and recalculates them on source push */ -public abstract class AbstractAction<T : Any, R : Any>( +public abstract class AbstractAction<T, R>( public val outputType: KType, ) : Action<T, R> { diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt index fafb2d55..ffa1d93d 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt @@ -50,7 +50,7 @@ public class MapActionBuilder<T, R>( } @PublishedApi -internal class MapAction<T : Any, R : Any>( +internal class MapAction<T, R>( outputType: KType, private val block: MapActionBuilder<T, R>.() -> Unit, ) : AbstractAction<T, R>(outputType) { @@ -96,7 +96,7 @@ internal class MapAction<T : Any, R : Any>( * A one-to-one mapping action */ @DFExperimental -public inline fun <T : Any, reified R : Any> Action.Companion.mapping( +public inline fun <T, reified R> Action.Companion.mapping( noinline builder: MapActionBuilder<T, R>.() -> Unit, ): Action<T, R> = MapAction(typeOf<R>(), builder) diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/ReduceAction.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/ReduceAction.kt index 9440be55..0da9b61c 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/ReduceAction.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/ReduceAction.kt @@ -12,7 +12,7 @@ import kotlin.reflect.KType import kotlin.reflect.typeOf -public class JoinGroup<T : Any, R : Any>( +public class JoinGroup<T, R>( public var name: String, internal val set: DataTree<T>, @PublishedApi internal var outputType: KType, @@ -35,7 +35,7 @@ public class JoinGroup<T : Any, R : Any>( } @DFBuilder -public class ReduceGroupBuilder<T : Any, R : Any>( +public class ReduceGroupBuilder<T, R>( public val actionMeta: Meta, private val outputType: KType, ) { @@ -79,7 +79,7 @@ public class ReduceGroupBuilder<T : Any, R : Any>( } @PublishedApi -internal class ReduceAction<T : Any, R : Any>( +internal class ReduceAction<T, R>( outputType: KType, private val action: ReduceGroupBuilder<T, R>.() -> Unit, ) : AbstractAction<T, R>(outputType) { diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/SplitAction.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/SplitAction.kt index cacbf1ee..b2937515 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/SplitAction.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/SplitAction.kt @@ -13,9 +13,9 @@ import kotlin.reflect.KType import kotlin.reflect.typeOf -public class SplitBuilder<T : Any, R : Any>(public val name: Name, public val meta: Meta) { +public class SplitBuilder<T, R>(public val name: Name, public val meta: Meta) { - public class FragmentRule<T : Any, R : Any>( + public class FragmentRule<T, R>( public val name: Name, public var meta: MutableMeta, @PublishedApi internal var outputType: KType, @@ -44,7 +44,7 @@ public class SplitBuilder<T : Any, R : Any>(public val name: Name, public val me * Action that splits each incoming element into a number of fragments defined in builder */ @PublishedApi -internal class SplitAction<T : Any, R : Any>( +internal class SplitAction<T, R>( outputType: KType, private val action: SplitBuilder<T, R>.() -> Unit, ) : AbstractAction<T, R>(outputType) { diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/GroupRule.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/GroupRule.kt index 90486d85..ff7c94a8 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/GroupRule.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/GroupRule.kt @@ -20,7 +20,7 @@ import space.kscience.dataforge.meta.string import space.kscience.dataforge.misc.DFInternal public interface GroupRule { - public fun <T : Any> gather(set: DataTree<T>): Map<String, DataTree<T>> + public fun <T> gather(set: DataTree<T>): Map<String, DataTree<T>> public companion object { /** @@ -37,7 +37,7 @@ public interface GroupRule { defaultTagValue: String, ): GroupRule = object : GroupRule { - override fun <T : Any> gather( + override fun <T> gather( set: DataTree<T>, ): Map<String, DataTree<T>> { val map = HashMap<String, DataTreeBuilder<T>>() From f95e278b2db7171a7e1bda6ffafa00d0f633f3f5 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Sun, 18 Feb 2024 20:11:53 +0300 Subject: [PATCH 07/26] Replace `branch` data builder with `putAll` --- CHANGELOG.md | 1 + .../kscience/dataforge/data/DataSource.kt | 8 ++-- .../kscience/dataforge/data/dataBuilders.kt | 38 +++++++++++++------ .../dataforge/data/dataSetBuilderInContext.kt | 4 +- .../dataforge/data/DataTreeBuilderTest.kt | 2 +- .../kscience/dataforge/workspace/Workspace.kt | 2 +- .../dataforge/workspace/taskBuilders.kt | 6 +-- .../dataforge/workspace/FileDataTest.kt | 2 +- 8 files changed, 39 insertions(+), 24 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5d85a2f..2849fce6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ - Name index comparator ### Changed +- DataSink `branch` is replaced with `putAll` to avoid confusion with DataTree methods ### Deprecated diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt index d379d027..40086ca2 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt @@ -98,15 +98,15 @@ public val DataTree<*>.meta: Meta? get() = data?.meta /** * Provide subtree if it exists */ -public tailrec fun <T, TR : GenericDataTree<T, TR>> GenericDataTree<T, TR>.branch(name: Name): TR? = +public tailrec fun <T, TR : GenericDataTree<T, TR>> GenericDataTree<T, TR>.putAll(name: Name): TR? = when (name.length) { 0 -> self 1 -> items[name.first()] - else -> items[name.first()]?.branch(name.cutFirst()) + else -> items[name.first()]?.putAll(name.cutFirst()) } -public fun <T, TR : GenericDataTree<T, TR>> GenericDataTree<T, TR>.branch(name: String): TR? = - branch(name.parseAsName()) +public fun <T, TR : GenericDataTree<T, TR>> GenericDataTree<T, TR>.putAll(name: String): TR? = + this@branch.putAll(name.parseAsName()) public fun GenericDataTree<*, *>.isEmpty(): Boolean = data == null && items.isEmpty() diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataBuilders.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataBuilders.kt index 8e8b6eaa..bdeb2798 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataBuilders.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataBuilders.kt @@ -16,11 +16,7 @@ public fun <T> DataSink<T>.put(value: NamedData<T>) { put(value.name, value.data) } -public fun <T> DataSink<T>.branch(dataTree: DataTree<T>) { - putAll(dataTree.asSequence()) -} - -public inline fun <T> DataSink<T>.branch( +public inline fun <T> DataSink<T>.putAll( prefix: Name, block: DataSink<T>.() -> Unit, ) { @@ -35,24 +31,42 @@ public inline fun <T> DataSink<T>.branch( } } +@Deprecated("Use putAll", ReplaceWith("putAll(prefix, block)")) +public inline fun <T> DataSink<T>.branch( + prefix: Name, + block: DataSink<T>.() -> Unit, +): Unit = putAll(prefix, block) + + +public inline fun <T> DataSink<T>.putAll( + prefix: String, + block: DataSink<T>.() -> Unit, +): Unit = putAll(prefix.asName(), block) + +@Deprecated("Use putAll", ReplaceWith("putAll(prefix, block)")) public inline fun <T> DataSink<T>.branch( prefix: String, block: DataSink<T>.() -> Unit, -): Unit = branch(prefix.asName(), block) - +): Unit = putAll(prefix, block) public fun <T> DataSink<T>.put(name: String, value: Data<T>) { put(Name.parse(name), value) } -public fun <T> DataSink<T>.branch(name: Name, set: DataTree<T>) { - branch(name) { putAll(set.asSequence()) } +public fun <T> DataSink<T>.putAll(name: Name, tree: DataTree<T>) { + putAll(name) { putAll(tree.asSequence()) } } -public fun <T> DataSink<T>.branch(name: String, set: DataTree<T>) { - branch(Name.parse(name)) { putAll(set.asSequence()) } +@Deprecated("Use putAll", ReplaceWith("putAll(name, tree)")) +public fun <T> DataSink<T>.branch(name: Name, tree: DataTree<T>): Unit = putAll(name,tree) + +public fun <T> DataSink<T>.putAll(name: String, tree: DataTree<T>) { + putAll(Name.parse(name)) { putAll(tree.asSequence()) } } +@Deprecated("Use putAll", ReplaceWith("putAll(name, tree)")) +public fun <T> DataSink<T>.branch(name: String, tree: DataTree<T>): Unit = putAll(name,tree) + /** * Produce lazy [Data] and emit it into the [MutableDataTree] */ @@ -124,7 +138,7 @@ public fun <T : Any> DataSink<T>.watchBranch( name: Name, dataSet: ObservableDataTree<T>, ): Job { - branch(name, dataSet) + putAll(name, dataSet) return dataSet.updates().onEach { put(name + it.name, it.data) }.launchIn(dataSet.updatesScope) diff --git a/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataSetBuilderInContext.kt b/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataSetBuilderInContext.kt index cfccb02b..6055a5fa 100644 --- a/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataSetBuilderInContext.kt +++ b/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataSetBuilderInContext.kt @@ -15,7 +15,7 @@ public infix fun <T : Any> String.put(data: Data<T>): Unit = */ context(DataSink<T>) public infix fun <T : Any> String.put(dataSet: DataTree<T>): Unit = - branch(this, dataSet) + this.putAll(this, dataSet) /** * Build and append node @@ -23,5 +23,5 @@ public infix fun <T : Any> String.put(dataSet: DataTree<T>): Unit = context(DataSink<T>) public infix fun <T : Any> String.put( block: DataSink<T>.() -> Unit, -): Unit = branch(Name.parse(this), block) +): Unit = this.putAll(Name.parse(this), block) diff --git a/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt b/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt index 95b7a7bd..a4e732dc 100644 --- a/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt +++ b/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt @@ -43,7 +43,7 @@ internal class DataTreeBuilderTest { wrap("b", "b") } wrap("root", "root") - putAll(updateData) + this.putAll(updateData) } assertEquals("a", node["update.a"]?.await()) diff --git a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Workspace.kt b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Workspace.kt index f3ea322c..e4e315fd 100644 --- a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Workspace.kt +++ b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Workspace.kt @@ -11,7 +11,7 @@ import space.kscience.dataforge.provider.Provider import kotlin.coroutines.CoroutineContext -public fun interface DataSelector<T> { +public fun interface DataSelector<out T> { public suspend fun select(workspace: Workspace, meta: Meta): DataTree<T> } diff --git a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/taskBuilders.kt b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/taskBuilders.kt index 1900ff23..35fccc99 100644 --- a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/taskBuilders.kt +++ b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/taskBuilders.kt @@ -3,8 +3,8 @@ package space.kscience.dataforge.workspace import space.kscience.dataforge.actions.Action import space.kscience.dataforge.context.PluginFactory import space.kscience.dataforge.data.DataTree -import space.kscience.dataforge.data.branch import space.kscience.dataforge.data.forEach +import space.kscience.dataforge.data.putAll import space.kscience.dataforge.data.transform import space.kscience.dataforge.meta.* import space.kscience.dataforge.misc.DFExperimental @@ -101,7 +101,7 @@ public suspend inline fun <T, reified R> TaskResultBuilder<R>.transformEach( * Set given [dataSet] as a task result. */ public fun <T> TaskResultBuilder<T>.result(dataSet: DataTree<T>) { - branch(dataSet) + this.putAll(dataSet) } /** @@ -113,7 +113,7 @@ public suspend inline fun <T, reified R> TaskResultBuilder<R>.actionFrom( action: Action<T, R>, dependencyMeta: Meta = defaultDependencyMeta, ) { - branch(action.execute(from(selector, dependencyMeta), dependencyMeta)) + this.putAll(action.execute(from(selector, dependencyMeta), dependencyMeta)) } diff --git a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/FileDataTest.kt b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/FileDataTest.kt index 10a1c268..a06f24a5 100644 --- a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/FileDataTest.kt +++ b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/FileDataTest.kt @@ -23,7 +23,7 @@ import kotlin.test.assertEquals class FileDataTest { val dataNode = DataTree<String> { - branch("dir") { + putAll("dir") { wrap("a", "Some string") { "content" put "Some string" } From aa88f05688199c51a4aa725e7f2123844fe391cb Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Mon, 19 Feb 2024 11:41:27 +0300 Subject: [PATCH 08/26] Replace `branch` data builder with `putAll` --- .../kotlin/space/kscience/dataforge/data/DataSource.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt index 40086ca2..d379d027 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt @@ -98,15 +98,15 @@ public val DataTree<*>.meta: Meta? get() = data?.meta /** * Provide subtree if it exists */ -public tailrec fun <T, TR : GenericDataTree<T, TR>> GenericDataTree<T, TR>.putAll(name: Name): TR? = +public tailrec fun <T, TR : GenericDataTree<T, TR>> GenericDataTree<T, TR>.branch(name: Name): TR? = when (name.length) { 0 -> self 1 -> items[name.first()] - else -> items[name.first()]?.putAll(name.cutFirst()) + else -> items[name.first()]?.branch(name.cutFirst()) } -public fun <T, TR : GenericDataTree<T, TR>> GenericDataTree<T, TR>.putAll(name: String): TR? = - this@branch.putAll(name.parseAsName()) +public fun <T, TR : GenericDataTree<T, TR>> GenericDataTree<T, TR>.branch(name: String): TR? = + branch(name.parseAsName()) public fun GenericDataTree<*, *>.isEmpty(): Boolean = data == null && items.isEmpty() From b575801983ff3afc381276c8249f7b628340596f Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Mon, 19 Feb 2024 11:42:04 +0300 Subject: [PATCH 09/26] Replace `branch` data builder with `putAll` --- .../space/kscience/dataforge/data/dataSetBuilderInContext.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataSetBuilderInContext.kt b/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataSetBuilderInContext.kt index 6055a5fa..44602c53 100644 --- a/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataSetBuilderInContext.kt +++ b/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataSetBuilderInContext.kt @@ -15,7 +15,7 @@ public infix fun <T : Any> String.put(data: Data<T>): Unit = */ context(DataSink<T>) public infix fun <T : Any> String.put(dataSet: DataTree<T>): Unit = - this.putAll(this, dataSet) + putAll(this, dataSet) /** * Build and append node @@ -23,5 +23,5 @@ public infix fun <T : Any> String.put(dataSet: DataTree<T>): Unit = context(DataSink<T>) public infix fun <T : Any> String.put( block: DataSink<T>.() -> Unit, -): Unit = this.putAll(Name.parse(this), block) +): Unit = putAll(Name.parse(this), block) From db2da2027d05c24a939eb35b68e7949e988c8760 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Mon, 19 Feb 2024 14:26:33 +0300 Subject: [PATCH 10/26] Replace `branch` data builder with `putAll` --- .../kscience/dataforge/data/dataBuilders.kt | 38 ++++++++----------- .../dataforge/data/DataTreeBuilderTest.kt | 4 +- 2 files changed, 18 insertions(+), 24 deletions(-) diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataBuilders.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataBuilders.kt index bdeb2798..63233c07 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataBuilders.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataBuilders.kt @@ -5,7 +5,6 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach 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.asName import space.kscience.dataforge.names.isEmpty @@ -58,14 +57,14 @@ public fun <T> DataSink<T>.putAll(name: Name, tree: DataTree<T>) { } @Deprecated("Use putAll", ReplaceWith("putAll(name, tree)")) -public fun <T> DataSink<T>.branch(name: Name, tree: DataTree<T>): Unit = putAll(name,tree) +public fun <T> DataSink<T>.branch(name: Name, tree: DataTree<T>): Unit = putAll(name, tree) public fun <T> DataSink<T>.putAll(name: String, tree: DataTree<T>) { putAll(Name.parse(name)) { putAll(tree.asSequence()) } } @Deprecated("Use putAll", ReplaceWith("putAll(name, tree)")) -public fun <T> DataSink<T>.branch(name: String, tree: DataTree<T>): Unit = putAll(name,tree) +public fun <T> DataSink<T>.branch(name: String, tree: DataTree<T>): Unit = putAll(name, tree) /** * Produce lazy [Data] and emit it into the [MutableDataTree] @@ -117,30 +116,25 @@ public fun <T> DataSink<T>.putAll(sequence: Sequence<NamedData<T>>) { } public fun <T> DataSink<T>.putAll(tree: DataTree<T>) { - this.putAll(tree.asSequence()) -} - - -/** - * Update data with given node data and meta with node meta. - */ -@DFExperimental -public fun <T> MutableDataTree<T>.putAll(source: DataTree<T>) { - source.forEach { - put(it.name, it.data) - } + putAll(tree.asSequence()) } /** * Copy given data set and mirror its changes to this [DataSink] in [this@setAndObserve]. Returns an update [Job] */ +public fun <T : Any> DataSink<T>.putAllAndWatch( + branchName: Name = Name.EMPTY, + dataSet: ObservableDataTree<T>, +): Job { + putAll(branchName, dataSet) + return dataSet.updates().onEach { + put(branchName + it.name, it.data) + }.launchIn(dataSet.updatesScope) +} + + +@Deprecated("Use putAllAndWatch", ReplaceWith("putAllAndWatch(name, dataSet)")) public fun <T : Any> DataSink<T>.watchBranch( name: Name, dataSet: ObservableDataTree<T>, -): Job { - putAll(name, dataSet) - return dataSet.updates().onEach { - put(name + it.name, it.data) - }.launchIn(dataSet.updatesScope) - -} \ No newline at end of file +): Job = putAllAndWatch(name, dataSet) \ No newline at end of file diff --git a/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt b/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt index a4e732dc..561e3aa0 100644 --- a/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt +++ b/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt @@ -43,7 +43,7 @@ internal class DataTreeBuilderTest { wrap("b", "b") } wrap("root", "root") - this.putAll(updateData) + putAll(updateData) } assertEquals("a", node["update.a"]?.await()) @@ -55,7 +55,7 @@ internal class DataTreeBuilderTest { val subNode = MutableDataTree<Int>() val rootNode = MutableDataTree<Int> { - watchBranch("sub".asName(), subNode) + putAllAndWatch("sub".asName(), subNode) } repeat(10) { From facf7c3c7e423ce22039e7ad2612192b3f3d2f1b Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Mon, 19 Feb 2024 20:10:15 +0300 Subject: [PATCH 11/26] Remove some experimental flags --- .../space/kscience/dataforge/actions/MapAction.kt | 3 +-- .../space/kscience/dataforge/actions/ReduceAction.kt | 10 ++++------ .../space/kscience/dataforge/actions/SplitAction.kt | 5 ++--- .../space/kscience/dataforge/data/dataFilterJvm.kt | 2 +- .../kotlin/space/kscience/dataforge/io/ioMisc.kt | 3 --- .../kotlin/space/kscience/dataforge/io/fileIO.kt | 3 --- .../space/kscience/dataforge/workspace/readFileData.kt | 6 ------ 7 files changed, 8 insertions(+), 24 deletions(-) diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt index ffa1d93d..0c56f0dd 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt @@ -6,7 +6,6 @@ import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.meta.seal import space.kscience.dataforge.meta.toMutableMeta import space.kscience.dataforge.misc.DFBuilder -import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.names.Name import kotlin.reflect.KType @@ -95,7 +94,7 @@ internal class MapAction<T, R>( /** * A one-to-one mapping action */ -@DFExperimental + public inline fun <T, reified R> Action.Companion.mapping( noinline builder: MapActionBuilder<T, R>.() -> Unit, ): Action<T, R> = MapAction(typeOf<R>(), builder) diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/ReduceAction.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/ReduceAction.kt index 0da9b61c..9df0db26 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/ReduceAction.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/ReduceAction.kt @@ -4,7 +4,6 @@ import space.kscience.dataforge.data.* import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.misc.DFBuilder -import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.parseAsName @@ -22,12 +21,12 @@ public class JoinGroup<T, R>( public lateinit var result: suspend ActionEnv.(Map<Name, ValueWithMeta<T>>) -> R - internal fun <R1 : R> result(outputType: KType, f: suspend ActionEnv.(Map<Name, ValueWithMeta<T>>) -> R1) { + internal fun <R1 : R> result(outputType: KType, f: suspend ActionEnv.(Map<Name, ValueWithMeta<T>>) -> R1) { this.outputType = outputType this.result = f; } - public inline fun <reified R1 : R> result(noinline f: suspend ActionEnv.(Map<Name, ValueWithMeta<T>>) -> R1) { + public inline fun <reified R1 : R> result(noinline f: suspend ActionEnv.(Map<Name, ValueWithMeta<T>>) -> R1) { outputType = typeOf<R1>() this.result = f; } @@ -67,7 +66,7 @@ public class ReduceGroupBuilder<T, R>( /** * Apply transformation to the whole node */ - public fun result(resultName: String, f: suspend ActionEnv.(Map<Name, ValueWithMeta<T>>) -> R) { + public fun result(resultName: String, f: suspend ActionEnv.(Map<Name, ValueWithMeta<T>>) -> R) { groupRules += { node -> listOf(JoinGroup<T, R>(resultName, node, outputType).apply { result(outputType, f) }) } @@ -111,7 +110,6 @@ internal class ReduceAction<T, R>( /** * A one-to-one mapping action */ -@DFExperimental -public inline fun <reified T : Any, reified R : Any> Action.Companion.reducing( +public inline fun <reified T, reified R> Action.Companion.reducing( noinline builder: ReduceGroupBuilder<T, R>.() -> Unit, ): Action<T, R> = ReduceAction(typeOf<R>(), builder) diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/SplitAction.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/SplitAction.kt index b2937515..04fef3ab 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/SplitAction.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/SplitAction.kt @@ -5,7 +5,6 @@ import space.kscience.dataforge.meta.Laminate import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.meta.toMutableMeta -import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.parseAsName import kotlin.collections.set @@ -85,7 +84,7 @@ internal class SplitAction<T, R>( /** * Action that splits each incoming element into a number of fragments defined in builder */ -@DFExperimental -public inline fun <T : Any, reified R : Any> Action.Companion.splitting( + +public inline fun <T, reified R> Action.Companion.splitting( noinline builder: SplitBuilder<T, R>.() -> Unit, ): Action<T, R> = SplitAction(typeOf<R>(), builder) \ No newline at end of file diff --git a/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataFilterJvm.kt b/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataFilterJvm.kt index 48155595..9498c758 100644 --- a/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataFilterJvm.kt +++ b/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataFilterJvm.kt @@ -84,4 +84,4 @@ public fun <R> ObservableDataTree<*>.filterByType( public inline fun <reified R> ObservableDataTree<*>.filterByType( scope: CoroutineScope, predicate: DataFilter = DataFilter.EMPTY, -): ObservableDataTree<R> = filterByType(typeOf<R>(),scope,predicate) \ No newline at end of file +): ObservableDataTree<R> = filterByType(typeOf<R>(), scope, predicate) \ No newline at end of file diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/ioMisc.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/ioMisc.kt index 93fd210a..b5e56dfe 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/ioMisc.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/ioMisc.kt @@ -5,7 +5,6 @@ import kotlinx.io.bytestring.ByteString import kotlinx.io.bytestring.decodeToString import kotlinx.io.bytestring.encodeToByteString import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.misc.DFExperimental import kotlin.math.min /** @@ -52,7 +51,6 @@ public fun IOPlugin.peekBinaryEnvelopeFormat(binary: Binary): EnvelopeFormat? { /** * A zero-copy read from */ -@DFExperimental public fun IOPlugin.readEnvelope( binary: Binary, readNonEnvelopes: Boolean = false, @@ -62,7 +60,6 @@ public fun IOPlugin.readEnvelope( Envelope(Meta.EMPTY, binary) } else error("Can't infer format for $binary") -@DFExperimental public fun IOPlugin.readEnvelope( string: String, readNonEnvelopes: Boolean = false, diff --git a/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/fileIO.kt b/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/fileIO.kt index c15280f3..7df23eb5 100644 --- a/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/fileIO.kt +++ b/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/fileIO.kt @@ -77,14 +77,12 @@ public fun Path.rewrite(block: Sink.() -> Unit): Unit { stream.asSink().buffered().use(block) } -@DFExperimental public fun EnvelopeFormat.readFile(path: Path): Envelope = readFrom(path.asBinary()) /** * Resolve IOFormat based on type */ @Suppress("UNCHECKED_CAST") -@DFExperimental public inline fun <reified T : Any> IOPlugin.resolveIOFormat(): IOFormat<T>? = ioFormatFactories.find { it.type.isSupertypeOf(typeOf<T>()) } as IOFormat<T>? @@ -192,7 +190,6 @@ public fun IOPlugin.peekFileEnvelopeFormat(path: Path): EnvelopeFormat? { * * Return null otherwise. */ -@DFExperimental public fun IOPlugin.readEnvelopeFile( path: Path, readNonEnvelopes: Boolean = false, diff --git a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/readFileData.kt b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/readFileData.kt index 1815c3e4..e0a4bdef 100644 --- a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/readFileData.kt +++ b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/readFileData.kt @@ -7,8 +7,6 @@ import space.kscience.dataforge.data.StaticData import space.kscience.dataforge.io.* import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.copy -import space.kscience.dataforge.misc.DFExperimental -import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.NameToken import space.kscience.dataforge.names.asName @@ -39,7 +37,6 @@ public object FileData { * Read data with supported envelope format and binary format. If the envelope format is null, then read binary directly from file. * The operation is blocking since it must read the meta header. The reading of envelope body is lazy */ -@OptIn(DFExperimental::class) public fun IOPlugin.readFileData( path: Path, ): Data<Binary> { @@ -127,8 +124,6 @@ public fun DataSink<Binary>.files( private fun Path.toName() = Name(map { NameToken.parse(it.nameWithoutExtension) }) -@DFInternal -@DFExperimental public fun DataSink<Binary>.monitorFiles( io: IOPlugin, name: Name, @@ -171,7 +166,6 @@ public fun DataSink<Binary>.monitorFiles( * @param resources The names of the resources to read. * @param classLoader The class loader to use for loading the resources. By default, it uses the current thread's context class loader. */ -@DFExperimental public fun DataSink<Binary>.resources( io: IOPlugin, vararg resources: String, From b2593d308e7c485ac12cce345e9496eefdbff907 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Sat, 24 Feb 2024 11:26:28 +0300 Subject: [PATCH 12/26] Add depth-first walk for data tree --- .../space/kscience/dataforge/data/DataSource.kt | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt index d379d027..90935fa1 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt @@ -93,6 +93,18 @@ public fun <T> DataTree<T>.asSequence( } } +/** + * Walk the data tree depth-first + */ +public fun <T, TR: GenericDataTree<T,TR>> TR.walk( + namePrefix: Name = Name.EMPTY, +): Sequence<TR> = sequence { + yield(this@walk) + items.forEach { (token, tree) -> + yieldAll(tree.walk(namePrefix + token)) + } +} + public val DataTree<*>.meta: Meta? get() = data?.meta /** From 0e72b4b63ceac633c7fa036571a60514f74f6a5f Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Sat, 24 Feb 2024 15:01:27 +0300 Subject: [PATCH 13/26] Add depth-first walk for data tree --- .../kotlin/space/kscience/dataforge/data/DataSource.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt index 90935fa1..855a249c 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt @@ -96,10 +96,10 @@ public fun <T> DataTree<T>.asSequence( /** * Walk the data tree depth-first */ -public fun <T, TR: GenericDataTree<T,TR>> TR.walk( +private fun <T, TR: GenericDataTree<T,TR>> TR.walk( namePrefix: Name = Name.EMPTY, -): Sequence<TR> = sequence { - yield(this@walk) +): Sequence<Pair<Name,TR>> = sequence { + yield(namePrefix to this@walk) items.forEach { (token, tree) -> yieldAll(tree.walk(namePrefix + token)) } From db938e1ad8b0b2054a79143aef204d4c8755c039 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Thu, 14 Mar 2024 17:07:32 +0300 Subject: [PATCH 14/26] add custom json encoder to serializerable meta converter --- .../kotlin/space/kscience/dataforge/meta/MetaConverter.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaConverter.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaConverter.kt index 8959ae4a..00074525 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaConverter.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaConverter.kt @@ -135,16 +135,17 @@ public interface MetaConverter<T>: MetaSpec<T> { @DFExperimental public inline fun <reified T> serializable( descriptor: MetaDescriptor? = null, + jsonEncoder: Json = Json { ignoreUnknownKeys = true }, ): MetaConverter<T> = object : MetaConverter<T> { private val serializer: KSerializer<T> = serializer() override fun readOrNull(source: Meta): T? { val json = source.toJson(descriptor) - return Json.decodeFromJsonElement(serializer, json) + return jsonEncoder.decodeFromJsonElement(serializer, json) } override fun convert(obj: T): Meta { - val json = Json.encodeToJsonElement(obj) + val json = jsonEncoder.encodeToJsonElement(obj) return json.toMeta(descriptor) } From 9fe3deac336e161a12c6a85f7896ecc8f63018a3 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Tue, 2 Apr 2024 10:01:41 +0300 Subject: [PATCH 15/26] Fix scheme set method --- .../space/kscience/dataforge/meta/Scheme.kt | 2 +- .../kscience/dataforge/meta/SchemeTest.kt | 70 ------------------- 2 files changed, 1 insertion(+), 71 deletions(-) delete mode 100644 dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SchemeTest.kt diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt index 96b6df49..85b5087a 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt @@ -122,7 +122,7 @@ public open class Scheme( override fun hashCode(): Int = Meta.hashCode(this) override fun set(name: Name, node: Meta?) { - target[name] = node + target[pathName + name] = node invalidate(name) } diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SchemeTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SchemeTest.kt deleted file mode 100644 index eaa766d8..00000000 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SchemeTest.kt +++ /dev/null @@ -1,70 +0,0 @@ -package space.kscience.dataforge.meta - -import space.kscience.dataforge.misc.DFExperimental -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertNotNull - - -private class SchemeWithInit: Scheme(){ - init { - set("initial", "initialValue") - } - - var initial by string() - companion object: SchemeSpec<SchemeWithInit>(::SchemeWithInit) -} - - - -class SchemeTest { - @Test - fun testSchemeWrappingBeforeEdit() { - val config = MutableMeta() - val scheme = TestScheme.write(config) - scheme.a = 29 - assertEquals(29, config["a"].int) - } - - @OptIn(DFExperimental::class) - @Test - fun testSchemeWrappingAfterEdit() { - val scheme = TestScheme.empty() - scheme.a = 29 - val config = MutableMeta() - scheme.retarget(config) - assertEquals(29, scheme.a) - } - - @Test - fun testSchemeSubscription() { - val scheme = TestScheme.empty() - var flag: Int? = null - scheme.useProperty(TestScheme::a) { a -> - flag = a - } - scheme.a = 2 - assertEquals(2, flag) - } - - @Test - fun testListSubscription(){ - val scheme = TestScheme.empty() - var value: Value? = null - scheme.v = ListValue(0.0,0.0,0.0) - scheme.useProperty(TestScheme::v){ - value = it - } - scheme.v = ListValue(1.0, 2.0, 3.0) - assertNotNull(value) - } - - - @Test - fun testSchemeWithInit(){ - val scheme = SchemeWithInit() - assertEquals("initialValue", scheme.initial) - scheme.initial = "none" - assertEquals("none", scheme.initial) - } -} \ No newline at end of file From 104111f62dce898d45f0682254f8197293fb5e5e Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Tue, 2 Apr 2024 10:03:18 +0300 Subject: [PATCH 16/26] Add byte array value. Refactor exotic values --- .../kscience/dataforge/meta/MetaConverter.kt | 2 +- .../dataforge/meta/MutableMetaDelegate.kt | 11 --- .../space/kscience/dataforge/meta/Value.kt | 2 - .../kscience/dataforge/meta/exoticValues.kt | 80 ++++++++++++++++++ .../dataforge/meta/valueExtensions.kt | 7 -- .../kscience/dataforge/misc/annotations.kt | 9 +- .../dataforge/meta/SpecificationTest.kt | 84 +++++++++++++++++++ .../dataforge/values/DoubleArrayValue.kt | 4 + 8 files changed, 177 insertions(+), 22 deletions(-) create mode 100644 dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/values/DoubleArrayValue.kt diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaConverter.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaConverter.kt index 00074525..124f49f5 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaConverter.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaConverter.kt @@ -135,7 +135,7 @@ public interface MetaConverter<T>: MetaSpec<T> { @DFExperimental public inline fun <reified T> serializable( descriptor: MetaDescriptor? = null, - jsonEncoder: Json = Json { ignoreUnknownKeys = true }, + jsonEncoder: Json = Json, ): MetaConverter<T> = object : MetaConverter<T> { private val serializer: KSerializer<T> = serializer() diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt index 70c4aceb..e308a63d 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt @@ -197,17 +197,6 @@ public fun MutableMetaProvider.numberList( reader = { it?.list?.map { value -> value.numberOrNull ?: Double.NaN } ?: listOf(*default) }, ) -/* A special delegate for double arrays */ - - -public fun MutableMetaProvider.doubleArray( - vararg default: Double, - key: Name? = null, -): ReadWriteProperty<Any?, DoubleArray> = value( - key, - writer = { DoubleArrayValue(it) }, - reader = { it?.doubleArray ?: doubleArrayOf(*default) }, -) public fun <T> MutableMetaProvider.listValue( key: Name? = null, diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Value.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Value.kt index 66e14c86..2ab7b9ee 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Value.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Value.kt @@ -256,8 +256,6 @@ public fun ShortArray.asValue(): Value = if (isEmpty()) Null else ListValue(map public fun FloatArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) }) -public fun ByteArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) }) - public fun <E : Enum<E>> E.asValue(): Value = EnumValue(this) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/exoticValues.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/exoticValues.kt index 74952053..eb39e985 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/exoticValues.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/exoticValues.kt @@ -1,5 +1,9 @@ package space.kscience.dataforge.meta +import space.kscience.dataforge.names.Name +import kotlin.properties.ReadOnlyProperty +import kotlin.properties.ReadWriteProperty + /** * A value built from string which content and type are parsed on-demand @@ -44,3 +48,79 @@ public class DoubleArrayValue(override val value: DoubleArray) : Value, Iterable } public fun DoubleArray.asValue(): Value = if (isEmpty()) Null else DoubleArrayValue(this) + +public val Value.doubleArray: DoubleArray + get() = if (this is DoubleArrayValue) { + value + } else { + DoubleArray(list.size) { list[it].double } + } + +public val Meta?.doubleArray: DoubleArray? get() = this?.value?.doubleArray + +public fun MetaProvider.doubleArray( + vararg default: Double, + key: Name? = null, +): ReadOnlyProperty<Any?, DoubleArray> = value( + key, + reader = { it?.doubleArray ?: doubleArrayOf(*default) }, +) + +public fun MutableMetaProvider.doubleArray( + vararg default: Double, + key: Name? = null, +): ReadWriteProperty<Any?, DoubleArray> = value( + key, + writer = { DoubleArrayValue(it) }, + reader = { it?.doubleArray ?: doubleArrayOf(*default) }, +) + + +public class ByteArrayValue(override val value: ByteArray) : Value, Iterable<Byte> { + override val type: ValueType get() = ValueType.LIST + override val list: List<Value> get() = value.map { NumberValue(it) } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Value) return false + + return when (other) { + is ByteArrayValue -> value.contentEquals(other.value) + else -> list == other.list + } + } + + override fun hashCode(): Int = value.contentHashCode() + + override fun toString(): String = list.joinToString(prefix = "[", postfix = "]") + + override fun iterator(): Iterator<Byte> = value.iterator() +} + +public fun ByteArray.asValue(): Value = ByteArrayValue(this) + +public val Value.byteArray: ByteArray + get() = if (this is ByteArrayValue) { + value + } else { + ByteArray(list.size) { list[it].number.toByte() } + } + +public val Meta?.byteArray: ByteArray? get() = this?.value?.byteArray + +public fun MetaProvider.byteArray( + vararg default: Byte, + key: Name? = null, +): ReadOnlyProperty<Any?, ByteArray> = value( + key, + reader = { it?.byteArray ?: byteArrayOf(*default) }, +) + +public fun MutableMetaProvider.byteArray( + vararg default: Byte, + key: Name? = null, +): ReadWriteProperty<Any?, ByteArray> = value( + key, + writer = { ByteArrayValue(it) }, + reader = { it?.byteArray ?: byteArrayOf(*default) }, +) \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/valueExtensions.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/valueExtensions.kt index e6b622ff..73464305 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/valueExtensions.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/valueExtensions.kt @@ -31,12 +31,5 @@ public inline fun <reified E : Enum<E>> Value.enum(): E = if (this is EnumValue< public val Value.stringList: List<String> get() = list.map { it.string } -public val Value.doubleArray: DoubleArray - get() = if (this is DoubleArrayValue) { - value - } else { - DoubleArray(list.size) { list[it].double } - } - public fun Value.toMeta(): Meta = Meta(this) \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/annotations.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/annotations.kt index 3c9d6ac3..29568403 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/annotations.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/annotations.kt @@ -18,4 +18,11 @@ public annotation class DFExperimental */ @RequiresOptIn(level = RequiresOptIn.Level.WARNING) @Retention(AnnotationRetention.BINARY) -public annotation class DFInternal \ No newline at end of file +public annotation class DFInternal + +/** + * Annotation marks methods that explicitly use KType without checking that it corresponds to the type parameter + */ +@RequiresOptIn(level = RequiresOptIn.Level.WARNING) +@Retention(AnnotationRetention.BINARY) +public annotation class UnsafeKType \ No newline at end of file diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SpecificationTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SpecificationTest.kt index 8d4d3537..dc9b9d64 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SpecificationTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SpecificationTest.kt @@ -1,7 +1,17 @@ package space.kscience.dataforge.meta +import space.kscience.dataforge.misc.DFExperimental import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertNotNull + + +internal class SubScheme : Scheme() { + + var subValue by string() + + companion object : SchemeSpec<SubScheme>(::SubScheme) +} internal class TestScheme : Scheme() { var list by numberList(1, 2, 3) @@ -11,9 +21,23 @@ internal class TestScheme : Scheme() { var v by value() + var sub by scheme(SubScheme) + companion object : SchemeSpec<TestScheme>(::TestScheme) } +private class SchemeWithInit: Scheme(){ + init { + set("initial", "initialValue") + } + + var initial by string() + + companion object: SchemeSpec<SchemeWithInit>(::SchemeWithInit) +} + + + class SpecificationTest { // @Test @@ -71,4 +95,64 @@ class SpecificationTest { assertEquals(22, config["child.a"].int) assertEquals("test", config["child.b"].string) } + + @Test + fun testSchemeWrappingBeforeEdit() { + val config = MutableMeta() + val scheme = TestScheme.write(config) + scheme.a = 29 + assertEquals(29, config["a"].int) + } + + @OptIn(DFExperimental::class) + @Test + fun testSchemeWrappingAfterEdit() { + val scheme = TestScheme.empty() + scheme.a = 29 + val config = MutableMeta() + scheme.retarget(config) + assertEquals(29, scheme.a) + } + + @Test + fun testSchemeSubscription() { + val scheme = TestScheme.empty() + var flag: Int? = null + scheme.useProperty(TestScheme::a) { a -> + flag = a + } + scheme.a = 2 + assertEquals(2, flag) + } + + @Test + fun testListSubscription(){ + val scheme = TestScheme.empty() + var value: Value? = null + scheme.v = ListValue(0.0,0.0,0.0) + scheme.useProperty(TestScheme::v){ + value = it + } + scheme.v = ListValue(1.0, 2.0, 3.0) + assertNotNull(value) + } + + @Test + fun testSubScheme(){ + val scheme = TestScheme.empty() + + scheme.sub.subValue = "aaa" + + assertEquals("aaa",scheme.sub.subValue) + } + + + @Test + fun testSchemeWithInit(){ + val scheme = SchemeWithInit() + assertEquals("initialValue", scheme.initial) + scheme.initial = "none" + assertEquals("none", scheme.initial) + } + } \ No newline at end of file diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/values/DoubleArrayValue.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/values/DoubleArrayValue.kt new file mode 100644 index 00000000..59ccecae --- /dev/null +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/values/DoubleArrayValue.kt @@ -0,0 +1,4 @@ +package space.kscience.dataforge.values + +class DoubleArrayValue { +} \ No newline at end of file From e7db1cc763210de45306b61642e2d75cf0d56307 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Tue, 2 Apr 2024 10:04:46 +0300 Subject: [PATCH 17/26] Refactor of data trees filtering --- CHANGELOG.md | 4 +- build.gradle.kts | 4 +- .../dataforge/actions/AbstractAction.kt | 46 ++- .../kscience/dataforge/actions/Action.kt | 17 +- .../kscience/dataforge/actions/MapAction.kt | 25 +- .../dataforge/actions/ReduceAction.kt | 8 +- .../kscience/dataforge/actions/SplitAction.kt | 34 ++- .../space/kscience/dataforge/data/Data.kt | 16 +- .../kscience/dataforge/data/DataFilter.kt | 45 ++- .../space/kscience/dataforge/data/DataSink.kt | 157 +++++++++++ .../kscience/dataforge/data/DataSource.kt | 263 ++---------------- .../kscience/dataforge/data/GroupRule.kt | 10 +- .../kscience/dataforge/data/MetaMaskData.kt | 2 +- .../kscience/dataforge/data/NamedData.kt | 28 +- .../kscience/dataforge/data/dataBuilders.kt | 71 ++--- .../kscience/dataforge/data/dataTransform.kt | 17 +- .../dataforge/data/dataTreeBuilder.kt | 112 ++++++++ .../kscience/dataforge/data/ActionsTest.kt | 22 +- .../dataforge/data/DataTreeBuilderTest.kt | 71 +++++ .../kscience/dataforge/data/dataFilterJvm.kt | 45 +-- .../dataforge/data/dataSetBuilderInContext.kt | 4 +- .../dataforge/data/DataTreeBuilderTest.kt | 68 ----- .../kscience/dataforge/workspace/Task.kt | 9 +- .../dataforge/workspace/TaskResult.kt | 8 +- .../kscience/dataforge/workspace/Workspace.kt | 7 +- .../dataforge/workspace/WorkspaceBuilder.kt | 10 +- .../dataforge/workspace/WorkspaceImpl.kt | 4 +- .../dataforge/workspace/envelopeData.kt | 4 +- .../dataforge/workspace/taskBuilders.kt | 2 +- .../dataforge/workspace/FileWorkspaceCache.kt | 3 +- .../workspace/InMemoryWorkspaceCache.kt | 3 +- .../dataforge/workspace/readFileData.kt | 26 +- .../workspace/CachingWorkspaceTest.kt | 4 +- .../workspace/DataPropagationTest.kt | 2 +- .../dataforge/workspace/FileDataTest.kt | 4 +- .../workspace/FileWorkspaceCacheTest.kt | 6 +- .../workspace/SimpleWorkspaceTest.kt | 14 +- 37 files changed, 644 insertions(+), 531 deletions(-) create mode 100644 dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSink.kt create mode 100644 dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataTreeBuilder.kt rename dataforge-data/src/{jvmTest => commonTest}/kotlin/space/kscience/dataforge/data/ActionsTest.kt (65%) create mode 100644 dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt delete mode 100644 dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index 2849fce6..a7c134e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,9 @@ ### Removed ### Fixed -- `listOfScheme` and `listOfConvertable` delegates provides correct items order +- `listOfScheme` and `listOfConvertable` delegates provides correct items order. +- Scheme meta setter works with proper sub-branch. +- ### Security diff --git a/build.gradle.kts b/build.gradle.kts index d41918ac..d4e22686 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { allprojects { group = "space.kscience" - version = "0.8.1-dev-1" + version = "0.8.1" } subprojects { @@ -30,7 +30,7 @@ ksciencePublish { useApache2Licence() useSPCTeam() } - repository("spc","https://maven.sciprog.center/kscience") + repository("spc", "https://maven.sciprog.center/kscience") sonatype("https://oss.sonatype.org") } diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/AbstractAction.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/AbstractAction.kt index 00201a90..4ed5f8df 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/AbstractAction.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/AbstractAction.kt @@ -1,11 +1,14 @@ package space.kscience.dataforge.actions -import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.onEach -import kotlinx.coroutines.launch -import space.kscience.dataforge.data.* +import space.kscience.dataforge.data.DataSink +import space.kscience.dataforge.data.DataTree +import space.kscience.dataforge.data.DataUpdate +import space.kscience.dataforge.data.launchUpdate import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.misc.DFInternal +import space.kscience.dataforge.misc.UnsafeKType import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.startsWith import kotlin.reflect.KType @@ -29,7 +32,7 @@ public abstract class AbstractAction<T, R>( * Generate initial content of the output */ protected abstract fun DataSink<R>.generate( - data: DataTree<T>, + source: DataTree<T>, meta: Meta, ) @@ -40,35 +43,28 @@ public abstract class AbstractAction<T, R>( * @param meta the metadata used for the whole data tree * @param updatedData an updated item */ - protected open fun DataSink<R>.update( + protected open suspend fun DataSink<R>.update( source: DataTree<T>, meta: Meta, - updatedData: NamedData<T>, + updatedData: DataUpdate<T>, ) { //by default regenerate the whole data set generate(source, meta) } - @OptIn(DFInternal::class) + @OptIn(UnsafeKType::class) override fun execute( - dataSet: DataTree<T>, + source: DataTree<T>, meta: Meta, - ): DataTree<R> = if (dataSet.isObservable()) { - MutableDataTree<R>(outputType, dataSet.updatesScope).apply { - generate(dataSet, meta) - dataSet.updates().onEach { - update(dataSet, meta, it) - }.launchIn(updatesScope) - - //close updates when the source is closed - updatesScope.launch { - dataSet.awaitClose() - close() - } - } - } else { - DataTree(outputType) { - generate(dataSet, meta) + updatesScope: CoroutineScope + ): DataTree<R> = DataTree(outputType) { + generate(source, meta) + //propagate updates + launchUpdate(updatesScope) { + source.updates.onEach { update -> + update(source, meta, update) + }.collect() } } } + diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/Action.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/Action.kt index 5ed60db9..80898aa8 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/Action.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/Action.kt @@ -1,5 +1,8 @@ package space.kscience.dataforge.actions +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.DelicateCoroutinesApi +import kotlinx.coroutines.GlobalScope import space.kscience.dataforge.data.DataTree import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.misc.DFExperimental @@ -13,7 +16,7 @@ public fun interface Action<T, R> { * Transform the data in the node, producing a new node. By default, it is assumed that all calculations are lazy * so not actual computation is started at this moment. */ - public fun execute(dataSet: DataTree<T>, meta: Meta): DataTree<R> + public fun execute(source: DataTree<T>, meta: Meta, updatesScope: CoroutineScope): DataTree<R> public companion object } @@ -21,23 +24,27 @@ public fun interface Action<T, R> { /** * A convenience method to transform data using given [action] */ +@OptIn(DelicateCoroutinesApi::class) public fun <T, R> DataTree<T>.transform( action: Action<T, R>, meta: Meta = Meta.EMPTY, -): DataTree<R> = action.execute(this, meta) + updateScope: CoroutineScope = GlobalScope, +): DataTree<R> = action.execute(this, meta, updateScope) /** * Action composition. The result is terminal if one of its parts is terminal */ -public infix fun <T, I, R> Action<T, I>.then(action: Action<I, R>): Action<T, R> = Action { dataSet, meta -> - action.execute(this@then.execute(dataSet, meta), meta) +public infix fun <T, I, R> Action<T, I>.then(action: Action<I, R>): Action<T, R> = Action { dataSet, meta, scope -> + action.execute(this@then.execute(dataSet, meta, scope), meta, scope) } @DFExperimental +@OptIn(DelicateCoroutinesApi::class) public operator fun <T, R> Action<T, R>.invoke( dataSet: DataTree<T>, meta: Meta = Meta.EMPTY, -): DataTree<R> = execute(dataSet, meta) + updateScope: CoroutineScope = GlobalScope, +): DataTree<R> = execute(dataSet, meta, updateScope) diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt index 0c56f0dd..a1ca8e59 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt @@ -6,7 +6,7 @@ import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.meta.seal import space.kscience.dataforge.meta.toMutableMeta import space.kscience.dataforge.misc.DFBuilder -import space.kscience.dataforge.misc.DFInternal +import space.kscience.dataforge.misc.UnsafeKType import space.kscience.dataforge.names.Name import kotlin.reflect.KType import kotlin.reflect.typeOf @@ -54,7 +54,12 @@ internal class MapAction<T, R>( private val block: MapActionBuilder<T, R>.() -> Unit, ) : AbstractAction<T, R>(outputType) { - private fun DataSink<R>.mapOne(name: Name, data: Data<T>, meta: Meta) { + private fun DataSink<R>.mapOne(name: Name, data: Data<T>?, meta: Meta) { + //fast return for null data + if (data == null) { + put(name, null) + return + } // Creating a new environment for action using **old** name, old meta and task meta val env = ActionEnv(name, data.meta, meta) @@ -73,7 +78,7 @@ internal class MapAction<T, R>( //getting new meta val newMeta = builder.meta.seal() - @OptIn(DFInternal::class) + @OptIn(UnsafeKType::class) val newData = Data(builder.outputType, newMeta, dependencies = listOf(data)) { builder.result(env, data.await()) } @@ -81,12 +86,18 @@ internal class MapAction<T, R>( put(newName, newData) } - override fun DataSink<R>.generate(data: DataTree<T>, meta: Meta) { - data.forEach { mapOne(it.name, it.data, meta) } + override fun DataSink<R>.generate(source: DataTree<T>, meta: Meta) { + source.forEach { mapOne(it.name, it.data, meta) } } - override fun DataSink<R>.update(source: DataTree<T>, meta: Meta, updatedData: NamedData<T>) { - mapOne(updatedData.name, updatedData.data, updatedData.meta) + + + override suspend fun DataSink<R>.update( + source: DataTree<T>, + meta: Meta, + updatedData: DataUpdate<T>, + ) { + mapOne(updatedData.name, updatedData.data, meta) } } diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/ReduceAction.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/ReduceAction.kt index 9df0db26..93278442 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/ReduceAction.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/ReduceAction.kt @@ -4,7 +4,7 @@ import space.kscience.dataforge.data.* import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.misc.DFBuilder -import space.kscience.dataforge.misc.DFInternal +import space.kscience.dataforge.misc.UnsafeKType import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.parseAsName import kotlin.reflect.KType @@ -84,8 +84,8 @@ internal class ReduceAction<T, R>( ) : AbstractAction<T, R>(outputType) { //TODO optimize reduction. Currently, the whole action recalculates on push - override fun DataSink<R>.generate(data: DataTree<T>, meta: Meta) { - ReduceGroupBuilder<T, R>(meta, outputType).apply(action).buildGroups(data).forEach { group -> + override fun DataSink<R>.generate(source: DataTree<T>, meta: Meta) { + ReduceGroupBuilder<T, R>(meta, outputType).apply(action).buildGroups(source).forEach { group -> val dataFlow: Map<Name, Data<T>> = group.set.asSequence().fold(HashMap()) { acc, value -> acc.apply { acc[value.name] = value.data @@ -97,7 +97,7 @@ internal class ReduceAction<T, R>( val groupMeta = group.meta val env = ActionEnv(groupName.parseAsName(), groupMeta, meta) - @OptIn(DFInternal::class) val res: Data<R> = dataFlow.reduceToData( + @OptIn(UnsafeKType::class) val res: Data<R> = dataFlow.reduceToData( group.outputType, meta = groupMeta ) { group.result.invoke(env, it) } diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/SplitAction.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/SplitAction.kt index 04fef3ab..2268b0fa 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/SplitAction.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/SplitAction.kt @@ -48,10 +48,10 @@ internal class SplitAction<T, R>( private val action: SplitBuilder<T, R>.() -> Unit, ) : AbstractAction<T, R>(outputType) { - private fun DataSink<R>.splitOne(name: Name, data: Data<T>, meta: Meta) { - val laminate = Laminate(data.meta, meta) + private fun DataSink<R>.splitOne(name: Name, data: Data<T>?, meta: Meta) { + val laminate = Laminate(data?.meta, meta) - val split = SplitBuilder<T, R>(name, data.meta).apply(action) + val split = SplitBuilder<T, R>(name, data?.meta ?: Meta.EMPTY).apply(action) // apply individual fragment rules to result @@ -63,21 +63,29 @@ internal class SplitAction<T, R>( ).apply(rule) //data.map<R>(outputType, meta = env.meta) { env.result(it) }.named(fragmentName) - put( - fragmentName, - @Suppress("OPT_IN_USAGE") Data(outputType, meta = env.meta, dependencies = listOf(data)) { - env.result(data.await()) - } - ) + if (data == null) { + put(fragmentName, null) + } else { + put( + fragmentName, + @Suppress("OPT_IN_USAGE") Data(outputType, meta = env.meta, dependencies = listOf(data)) { + env.result(data.await()) + } + ) + } } } - override fun DataSink<R>.generate(data: DataTree<T>, meta: Meta) { - data.forEach { splitOne(it.name, it.data, meta) } + override fun DataSink<R>.generate(source: DataTree<T>, meta: Meta) { + source.forEach { splitOne(it.name, it.data, meta) } } - override fun DataSink<R>.update(source: DataTree<T>, meta: Meta, updatedData: NamedData<T>) { - splitOne(updatedData.name, updatedData.data, updatedData.meta) + override suspend fun DataSink<R>.update( + source: DataTree<T>, + meta: Meta, + updatedData: DataUpdate<T>, + ) { + splitOne(updatedData.name, updatedData.data, meta) } } diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/Data.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/Data.kt index a0bb58ea..b9946a48 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/Data.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/Data.kt @@ -4,8 +4,8 @@ import kotlinx.coroutines.* import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MetaRepr import space.kscience.dataforge.meta.isEmpty -import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.misc.DfType +import space.kscience.dataforge.misc.UnsafeKType import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext import kotlin.reflect.KType @@ -41,7 +41,7 @@ public interface Data<out T> : Goal<T>, MetaRepr { */ internal val TYPE_OF_NOTHING: KType = typeOf<Unit>() - public inline fun <reified T> static( + public inline fun <reified T> wrapValue( value: T, meta: Meta = Meta.EMPTY, ): Data<T> = StaticData(typeOf<T>(), value, meta) @@ -50,10 +50,10 @@ public interface Data<out T> : Goal<T>, MetaRepr { * An empty data containing only meta */ @OptIn(DelicateCoroutinesApi::class) - public fun empty(meta: Meta): Data<Nothing> = object : Data<Nothing> { - override val type: KType = TYPE_OF_NOTHING + public fun buildEmpty(meta: Meta): Data<Nothing> = object : Data<Nothing> { + override val type: KType get() = TYPE_OF_NOTHING override val meta: Meta = meta - override val dependencies: Collection<Goal<*>> = emptyList() + override val dependencies: Collection<Goal<*>> get() = emptyList() override val deferred: Deferred<Nothing> get() = GlobalScope.async(start = CoroutineStart.LAZY) { error("The Data is empty and could not be computed") @@ -62,6 +62,8 @@ public interface Data<out T> : Goal<T>, MetaRepr { override fun async(coroutineScope: CoroutineScope): Deferred<Nothing> = deferred override fun reset() {} } + + public val EMPTY: Data<Nothing> = buildEmpty(Meta.EMPTY) } } @@ -87,7 +89,7 @@ public class StaticData<T>( public inline fun <reified T> Data(value: T, meta: Meta = Meta.EMPTY): StaticData<T> = StaticData(typeOf<T>(), value, meta) -@DFInternal +@UnsafeKType public fun <T> Data( type: KType, meta: Meta = Meta.EMPTY, @@ -96,7 +98,7 @@ public fun <T> Data( block: suspend () -> T, ): Data<T> = LazyData(type, meta, context, dependencies, block) -@OptIn(DFInternal::class) +@OptIn(UnsafeKType::class) public inline fun <reified T> Data( meta: Meta = Meta.EMPTY, context: CoroutineContext = EmptyCoroutineContext, diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataFilter.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataFilter.kt index f45570ad..bc66e910 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataFilter.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataFilter.kt @@ -1,28 +1,30 @@ package space.kscience.dataforge.data -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.filter import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.names.Name +import space.kscience.dataforge.names.NameToken +import space.kscience.dataforge.names.plus import kotlin.reflect.KType public fun interface DataFilter { - public fun accepts(name: Name, meta: Meta, type: KType): Boolean + public fun accepts(name: Name, meta: Meta?, type: KType): Boolean public companion object { public val EMPTY: DataFilter = DataFilter { _, _, _ -> true } } } -public fun DataFilter.accepts(data: NamedData<*>): Boolean = accepts(data.name, data.meta, data.type) -public fun <T> Sequence<NamedData<T>>.filterData(predicate: DataFilter): Sequence<NamedData<T>> = filter { data -> +public fun DataFilter.accepts(update: DataUpdate<*>): Boolean = accepts(update.name, update.data?.meta, update.type) + +public fun <T, DU : DataUpdate<T>> Sequence<DU>.filterData(predicate: DataFilter): Sequence<DU> = filter { data -> predicate.accepts(data) } -public fun <T> Flow<NamedData<T>>.filterData(predicate: DataFilter): Flow<NamedData<T>> = filter { data -> +public fun <T, DU : DataUpdate<T>> Flow<DU>.filterData(predicate: DataFilter): Flow<DU> = filter { data -> predicate.accepts(data) } @@ -41,7 +43,8 @@ public fun <T> DataSource<T>.filterData( public fun <T> ObservableDataSource<T>.filterData( predicate: DataFilter, ): ObservableDataSource<T> = object : ObservableDataSource<T> { - override fun updates(): Flow<NamedData<T>> = this@filterData.updates().filter { predicate.accepts(it) } + override val updates: Flow<DataUpdate<T>> + get() = this@filterData.updates.filter { predicate.accepts(it) } override val dataType: KType get() = this@filterData.dataType @@ -49,14 +52,32 @@ public fun <T> ObservableDataSource<T>.filterData( this@filterData.read(name)?.takeIf { predicate.accepts(name, it.meta, it.type) } } -public fun <T> GenericDataTree<T, *>.filterData( - predicate: DataFilter, -): DataTree<T> = asSequence().filterData(predicate).toTree(dataType) +internal class FilteredDataTree<T>( + val source: DataTree<T>, + val filter: DataFilter, + val branch: Name, + override val dataType: KType = source.dataType, +) : DataTree<T> { -public fun <T> GenericObservableDataTree<T, *>.filterData( - scope: CoroutineScope, + override val data: Data<T>? + get() = source[branch].takeIf { + filter.accepts(Name.EMPTY, data?.meta, data?.type ?: dataType) + } + + override val items: Map<NameToken, DataTree<T>> + get() = source.branch(branch)?.items + ?.mapValues { FilteredDataTree(source, filter, branch + it.key) } + ?.filter { !it.value.isEmpty() } + ?: emptyMap() + + override val updates: Flow<DataUpdate<T>> + get() = source.updates.filter { filter.accepts(it) } +} + + +public fun <T> DataTree<T>.filterData( predicate: DataFilter, -): ObservableDataTree<T> = asSequence().filterData(predicate).toObservableTree(dataType, scope, updates().filterData(predicate)) +): DataTree<T> = FilteredDataTree(this, predicate, Name.EMPTY) ///** diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSink.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSink.kt new file mode 100644 index 00000000..9d860310 --- /dev/null +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSink.kt @@ -0,0 +1,157 @@ +package space.kscience.dataforge.data + +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.launch +import space.kscience.dataforge.misc.UnsafeKType +import space.kscience.dataforge.names.* +import kotlin.reflect.KType +import kotlin.reflect.typeOf + +public interface DataSink<in T> { + /** + * Put data without notification + */ + public fun put(name: Name, data: Data<T>?) + + /** + * Put data and propagate changes downstream + */ + public suspend fun update(name: Name, data: Data<T>?) +} + +/** + * Launch continuous update using + */ +public fun <T> DataSink<T>.launchUpdate( + scope: CoroutineScope, + updater: suspend DataSink<T>.() -> Unit, +): Job = scope.launch { + object : DataSink<T> { + override fun put(name: Name, data: Data<T>?) { + launch { + this@launchUpdate.update(name, data) + } + } + + override suspend fun update(name: Name, data: Data<T>?) { + this@launchUpdate.update(name, data) + } + }.updater() +} + +/** + * A mutable version of [DataTree] + */ +public interface MutableDataTree<T> : DataTree<T>, DataSink<T> { + override var data: Data<T>? + + override val items: Map<NameToken, MutableDataTree<T>> + + public fun getOrCreateItem(token: NameToken): MutableDataTree<T> + + public operator fun set(token: NameToken, data: Data<T>?) + + override fun put(name: Name, data: Data<T>?): Unit = set(name, data) +} + +public tailrec operator fun <T> MutableDataTree<T>.set(name: Name, data: Data<T>?): Unit { + when (name.length) { + 0 -> this.data = data + 1 -> set(name.first(), data) + else -> getOrCreateItem(name.first())[name.cutFirst()] = data + } +} + +/** + * Provide a mutable subtree if it exists + */ +public tailrec fun <T> MutableDataTree<T>.branch(name: Name): MutableDataTree<T>? = + when (name.length) { + 0 -> this + 1 -> items[name.first()] + else -> items[name.first()]?.branch(name.cutFirst()) + } + +private class MutableDataTreeRoot<T>( + override val dataType: KType, +) : MutableDataTree<T> { + + override val updates = MutableSharedFlow<DataUpdate<T>>() + + inner class MutableDataTreeBranch(val branchName: Name) : MutableDataTree<T> { + + override var data: Data<T>? = null + + override val items = HashMap<NameToken, MutableDataTree<T>>() + + override val updates: Flow<DataUpdate<T>> = this@MutableDataTreeRoot.updates.mapNotNull { update -> + update.name.removeFirstOrNull(branchName)?.let { + DataUpdate(update.data?.type ?: dataType, it, update.data) + } + } + override val dataType: KType get() = this@MutableDataTreeRoot.dataType + + + override fun getOrCreateItem(token: NameToken): MutableDataTree<T> = + items.getOrPut(token) { MutableDataTreeBranch(branchName + token) } + + + override fun set(token: NameToken, data: Data<T>?) { + val subTree = getOrCreateItem(token) + subTree.data = data + } + + override suspend fun update(name: Name, data: Data<T>?) { + if (name.isEmpty()) { + this.data = data + } else { + getOrCreateItem(name.first()).update(name.cutFirst(), data) + } + this@MutableDataTreeRoot.updates.emit(DataUpdate(data?.type ?: dataType, branchName + name, data)) + } + + } + + + override var data: Data<T>? = null + + override val items = HashMap<NameToken, MutableDataTree<T>>() + + override fun getOrCreateItem(token: NameToken): MutableDataTree<T> = items.getOrPut(token) { + MutableDataTreeRoot(dataType) + } + + override fun set(token: NameToken, data: Data<T>?) { + val subTree = getOrCreateItem(token) + subTree.data = data + } + + override suspend fun update(name: Name, data: Data<T>?) { + if (name.isEmpty()) { + this.data = data + } else { + getOrCreateItem(name.first()).update(name.cutFirst(), data) + } + updates.emit(DataUpdate(data?.type ?: dataType, name, data)) + } +} + +/** + * Create a new [MutableDataTree] + */ +@UnsafeKType +public fun <T> MutableDataTree( + type: KType, +): MutableDataTree<T> = MutableDataTreeRoot<T>(type) + +/** + * Create and initialize a observable mutable data tree. + */ +@OptIn(UnsafeKType::class) +public inline fun <reified T> MutableDataTree( + generator: MutableDataTree<T>.() -> Unit = {}, +): MutableDataTree<T> = MutableDataTree<T>(typeOf<T>()).apply { generator() } \ No newline at end of file diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt index 855a249c..a9756be7 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSource.kt @@ -1,9 +1,8 @@ package space.kscience.dataforge.data -import kotlinx.coroutines.* -import kotlinx.coroutines.flow.* +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.emptyFlow import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.names.* import kotlin.contracts.contract import kotlin.reflect.KType @@ -33,46 +32,42 @@ public interface ObservableDataSource<out T> : DataSource<T> { /** * Flow updates made to the data */ - public fun updates(): Flow<NamedData<T>> + public val updates: Flow<DataUpdate<T>> } /** * A tree like structure for data holding */ -public interface GenericDataTree<out T, out TR : GenericDataTree<T, TR>> : DataSource<T> { - public val self: TR +public interface DataTree<out T> : ObservableDataSource<T> { public val data: Data<T>? - public val items: Map<NameToken, TR> - + public val items: Map<NameToken, DataTree<T>> override fun read(name: Name): Data<T>? = when (name.length) { 0 -> data else -> items[name.first()]?.read(name.cutFirst()) } + /** + * Flow updates made to the data + */ + override val updates: Flow<DataUpdate<T>> + public companion object { - private object EmptyDataTree : GenericDataTree<Nothing, EmptyDataTree> { - override val self: EmptyDataTree get() = this + private object EmptyDataTree : + DataTree<Nothing> { override val data: Data<Nothing>? = null override val items: Map<NameToken, EmptyDataTree> = emptyMap() override val dataType: KType = typeOf<Unit>() override fun read(name: Name): Data<Nothing>? = null - + override val updates: Flow<DataUpdate<Nothing>> get() = emptyFlow() } - public val EMPTY: GenericDataTree<Nothing, *> = EmptyDataTree + public val EMPTY: DataTree<Nothing> = EmptyDataTree } } -public typealias DataTree<T> = GenericDataTree<T, GenericDataTree<T, *>> - -/** - * Return a single data in this tree. Throw error if it is not single. - */ -public fun <T> DataTree<T>.single(): NamedData<T> = asSequence().single() - /** * An alias for easier access to tree values */ @@ -94,11 +89,13 @@ public fun <T> DataTree<T>.asSequence( } /** - * Walk the data tree depth-first + * Walk the data tree depth-first. + * + * @return a [Sequence] of pairs [Name]-[DataTree] for all nodes including the root one. */ -private fun <T, TR: GenericDataTree<T,TR>> TR.walk( +public fun <T> DataTree<T>.walk( namePrefix: Name = Name.EMPTY, -): Sequence<Pair<Name,TR>> = sequence { +): Sequence<Pair<Name, DataTree<T>>> = sequence { yield(namePrefix to this@walk) items.forEach { (token, tree) -> yieldAll(tree.walk(namePrefix + token)) @@ -110,233 +107,25 @@ public val DataTree<*>.meta: Meta? get() = data?.meta /** * Provide subtree if it exists */ -public tailrec fun <T, TR : GenericDataTree<T, TR>> GenericDataTree<T, TR>.branch(name: Name): TR? = +public tailrec fun <T> DataTree<T>.branch(name: Name): DataTree<T>? = when (name.length) { - 0 -> self + 0 -> this 1 -> items[name.first()] else -> items[name.first()]?.branch(name.cutFirst()) } -public fun <T, TR : GenericDataTree<T, TR>> GenericDataTree<T, TR>.branch(name: String): TR? = +public fun <T> DataTree<T>.branch(name: String): DataTree<T>? = branch(name.parseAsName()) -public fun GenericDataTree<*, *>.isEmpty(): Boolean = data == null && items.isEmpty() - -@PublishedApi -internal class FlatDataTree<T>( - override val dataType: KType, - private val dataSet: Map<Name, Data<T>>, - private val prefix: Name, -) : GenericDataTree<T, FlatDataTree<T>> { - override val self: FlatDataTree<T> get() = this - override val data: Data<T>? get() = dataSet[prefix] - override val items: Map<NameToken, FlatDataTree<T>> - get() = dataSet.keys - .filter { it.startsWith(prefix) && it.length > prefix.length } - .map { it.tokens[prefix.length] } - .associateWith { FlatDataTree(dataType, dataSet, prefix + it) } - - override fun read(name: Name): Data<T>? = dataSet[prefix + name] -} - -/** - * Represent this flat data map as a [DataTree] without copying it - */ -public inline fun <reified T> Map<Name, Data<T>>.asTree(): DataTree<T> = FlatDataTree(typeOf<T>(), this, Name.EMPTY) - -internal fun <T> Sequence<NamedData<T>>.toTree(type: KType): DataTree<T> = - FlatDataTree(type, associate { it.name to it.data }, Name.EMPTY) - -/** - * Collect a sequence of [NamedData] to a [DataTree] - */ -public inline fun <reified T> Sequence<NamedData<T>>.toTree(): DataTree<T> = - FlatDataTree(typeOf<T>(), associate { it.name to it.data }, Name.EMPTY) - -public interface GenericObservableDataTree<out T, out TR : GenericObservableDataTree<T, TR>> : - GenericDataTree<T, TR>, ObservableDataSource<T>, AutoCloseable { - - /** - * A scope that is used to propagate updates. When this scope is closed, no new updates could arrive. - */ - public val updatesScope: CoroutineScope - - /** - * Close this data tree updates channel - */ - override fun close() { - updatesScope.cancel() - } - -} - -public typealias ObservableDataTree<T> = GenericObservableDataTree<T, GenericObservableDataTree<T, *>> +public fun DataTree<*>.isEmpty(): Boolean = data == null && items.isEmpty() /** * Check if the [DataTree] is observable */ -public fun <T> DataTree<T>.isObservable(): Boolean { +public fun <T> DataSource<T>.isObservable(): Boolean { contract { - returns(true) implies (this@isObservable is GenericObservableDataTree<T, *>) + returns(true) implies (this@isObservable is ObservableDataSource<T>) } - return this is GenericObservableDataTree<T, *> + return this is ObservableDataSource<T> } -/** - * Wait for this data tree to stop spawning updates (updatesScope is closed). - * If this [DataTree] is not observable, return immediately. - */ -public suspend fun <T> DataTree<T>.awaitClose() { - if (isObservable()) { - updatesScope.coroutineContext[Job]?.join() - } -} - -public fun <T> DataTree<T>.updates(): Flow<NamedData<T>> = - if (this is GenericObservableDataTree<T, *>) updates() else emptyFlow() - -public fun interface DataSink<in T> { - public fun put(name: Name, data: Data<T>?) -} - -@DFInternal -public class DataTreeBuilder<T>(private val type: KType) : DataSink<T> { - private val map = HashMap<Name, Data<T>>() - override fun put(name: Name, data: Data<T>?) { - if (data == null) { - map.remove(name) - } else { - map[name] = data - } - } - - public fun build(): DataTree<T> = FlatDataTree(type, map, Name.EMPTY) -} - -@DFInternal -public inline fun <T> DataTree( - dataType: KType, - generator: DataSink<T>.() -> Unit, -): DataTree<T> = DataTreeBuilder<T>(dataType).apply(generator).build() - -/** - * Create and a data tree. - */ -@OptIn(DFInternal::class) -public inline fun <reified T> DataTree( - generator: DataSink<T>.() -> Unit, -): DataTree<T> = DataTreeBuilder<T>(typeOf<T>()).apply(generator).build() - -/** - * A mutable version of [GenericDataTree] - */ -public interface MutableDataTree<T> : GenericObservableDataTree<T, MutableDataTree<T>>, DataSink<T> { - override var data: Data<T>? - - override val items: Map<NameToken, MutableDataTree<T>> - - public fun getOrCreateItem(token: NameToken): MutableDataTree<T> - - public operator fun set(token: NameToken, data: Data<T>?) - - override fun put(name: Name, data: Data<T>?): Unit = set(name, data) -} - -public tailrec operator fun <T> MutableDataTree<T>.set(name: Name, data: Data<T>?): Unit { - when (name.length) { - 0 -> this.data = data - 1 -> set(name.first(), data) - else -> getOrCreateItem(name.first())[name.cutFirst()] = data - } -} - -private class MutableDataTreeImpl<T>( - override val dataType: KType, - override val updatesScope: CoroutineScope, -) : MutableDataTree<T> { - - - private val updates = MutableSharedFlow<NamedData<T>>() - - private val children = HashMap<NameToken, MutableDataTree<T>>() - - override var data: Data<T>? = null - set(value) { - if (!updatesScope.isActive) error("Can't send updates to closed MutableDataTree") - field = value - if (value != null) { - updatesScope.launch { - updates.emit(value.named(Name.EMPTY)) - } - } - } - - override val items: Map<NameToken, MutableDataTree<T>> get() = children - - override fun getOrCreateItem(token: NameToken): MutableDataTree<T> = children.getOrPut(token){ - MutableDataTreeImpl(dataType, updatesScope) - } - - override val self: MutableDataTree<T> get() = this - - override fun set(token: NameToken, data: Data<T>?) { - if (!updatesScope.isActive) error("Can't send updates to closed MutableDataTree") - val subTree = getOrCreateItem(token) - subTree.updates().onEach { - updates.emit(it.named(token + it.name)) - }.launchIn(updatesScope) - subTree.data = data - } - - override fun updates(): Flow<NamedData<T>> = updates -} - -/** - * Create a new [MutableDataTree] - * - * @param parentScope a [CoroutineScope] to control data propagation. By default uses [GlobalScope] - */ -@OptIn(DelicateCoroutinesApi::class) -public fun <T> MutableDataTree( - type: KType, - parentScope: CoroutineScope = GlobalScope, -): MutableDataTree<T> = MutableDataTreeImpl<T>( - type, - CoroutineScope(parentScope.coroutineContext + Job(parentScope.coroutineContext[Job])) -) - -/** - * Create and initialize a observable mutable data tree. - */ -@OptIn(DelicateCoroutinesApi::class) -public inline fun <reified T> MutableDataTree( - parentScope: CoroutineScope = GlobalScope, - generator: MutableDataTree<T>.() -> Unit = {}, -): MutableDataTree<T> = MutableDataTree<T>(typeOf<T>(), parentScope).apply { generator() } - -//@DFInternal -//public fun <T> ObservableDataTree( -// type: KType, -// scope: CoroutineScope, -// generator: suspend MutableDataTree<T>.() -> Unit = {}, -//): ObservableDataTree<T> = MutableDataTree<T>(type, scope.coroutineContext).apply(generator) - -public inline fun <reified T> ObservableDataTree( - parentScope: CoroutineScope, - generator: MutableDataTree<T>.() -> Unit = {}, -): ObservableDataTree<T> = MutableDataTree<T>(typeOf<T>(), parentScope).apply(generator) - - -/** - * Collect a [Sequence] into an observable tree with additional [updates] - */ -public fun <T> Sequence<NamedData<T>>.toObservableTree( - dataType: KType, - parentScope: CoroutineScope, - updates: Flow<NamedData<T>>, -): ObservableDataTree<T> = MutableDataTree<T>(dataType, parentScope).apply { - this.putAll(this@toObservableTree) - updates.onEach { - put(it.name, it.data) - }.launchIn(updatesScope) -} diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/GroupRule.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/GroupRule.kt index ff7c94a8..6dd3caa9 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/GroupRule.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/GroupRule.kt @@ -17,7 +17,7 @@ package space.kscience.dataforge.data import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.string -import space.kscience.dataforge.misc.DFInternal +import space.kscience.dataforge.misc.UnsafeKType public interface GroupRule { public fun <T> gather(set: DataTree<T>): Map<String, DataTree<T>> @@ -31,7 +31,7 @@ public interface GroupRule { * @param defaultTagValue * @return */ - @OptIn(DFInternal::class) + @OptIn(UnsafeKType::class) public fun byMetaValue( key: String, defaultTagValue: String, @@ -40,15 +40,15 @@ public interface GroupRule { override fun <T> gather( set: DataTree<T>, ): Map<String, DataTree<T>> { - val map = HashMap<String, DataTreeBuilder<T>>() + val map = HashMap<String, MutableDataTree<T>>() set.forEach { data -> val tagValue: String = data.meta[key]?.string ?: defaultTagValue - map.getOrPut(tagValue) { DataTreeBuilder(set.dataType) }.put(data.name, data.data) + map.getOrPut(tagValue) { MutableDataTree(set.dataType) }.put(data.name, data.data) } - return map.mapValues { it.value.build() } + return map } } } diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/MetaMaskData.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/MetaMaskData.kt index acf2410d..85f0b2f9 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/MetaMaskData.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/MetaMaskData.kt @@ -20,4 +20,4 @@ public fun <T> Data<T>.withMeta(newMeta: Meta): Data<T> = if (this is MetaMaskDa * Create a new [Data] with the same computation, but different meta. The meta is created by applying [block] to * the existing data meta. */ -public inline fun <T> Data<T>.mapMeta(block: MutableMeta.() -> Unit): Data<T> = withMeta(meta.copy(block)) \ No newline at end of file +public inline fun <T> Data<T>.withMeta(block: MutableMeta.() -> Unit): Data<T> = withMeta(meta.copy(block)) \ No newline at end of file diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/NamedData.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/NamedData.kt index bf65292c..9cb4c2d9 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/NamedData.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/NamedData.kt @@ -3,10 +3,30 @@ package space.kscience.dataforge.data import space.kscience.dataforge.meta.isEmpty import space.kscience.dataforge.misc.Named import space.kscience.dataforge.names.Name +import kotlin.reflect.KType -public interface NamedData<out T> : Named, Data<T> { +/** + * An interface implementing a data update event. + * + * If [data] is null, then corresponding element should be removed. + */ +public interface DataUpdate<out T> : Named { + public val type: KType override val name: Name - public val data: Data<T> + public val data: Data<T>? +} + +public fun <T> DataUpdate(type: KType, name: Name, data: Data<T>?): DataUpdate<T> = object : DataUpdate<T> { + override val type: KType = type + override val name: Name = name + override val data: Data<T>? = data +} + +/** + * A data coupled to a name. + */ +public interface NamedData<out T> : DataUpdate<T>, Data<T> { + override val data: Data<T> } public operator fun NamedData<*>.component1(): Name = name @@ -32,4 +52,6 @@ public fun <T> Data<T>.named(name: Name): NamedData<T> = if (this is NamedData) NamedDataImpl(name, this.data) } else { NamedDataImpl(name, this) -} \ No newline at end of file +} + +public fun <T> NamedData(name: Name, data: Data<T>): NamedData<T> = data.named(name) \ No newline at end of file diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataBuilders.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataBuilders.kt index 63233c07..8ec3e361 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataBuilders.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataBuilders.kt @@ -1,5 +1,6 @@ package space.kscience.dataforge.data +import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -22,31 +23,27 @@ public inline fun <T> DataSink<T>.putAll( if (prefix.isEmpty()) { apply(block) } else { - val proxyDataSink = DataSink { nameWithoutPrefix, data -> - this.put(prefix + nameWithoutPrefix, data) + val proxyDataSink = object :DataSink<T>{ + override fun put(name: Name, data: Data<T>?) { + this@putAll.put(prefix + name, data) + } + + override suspend fun update(name: Name, data: Data<T>?) { + this@putAll.update(prefix + name, data) + } + } proxyDataSink.apply(block) } } -@Deprecated("Use putAll", ReplaceWith("putAll(prefix, block)")) -public inline fun <T> DataSink<T>.branch( - prefix: Name, - block: DataSink<T>.() -> Unit, -): Unit = putAll(prefix, block) - public inline fun <T> DataSink<T>.putAll( prefix: String, block: DataSink<T>.() -> Unit, ): Unit = putAll(prefix.asName(), block) -@Deprecated("Use putAll", ReplaceWith("putAll(prefix, block)")) -public inline fun <T> DataSink<T>.branch( - prefix: String, - block: DataSink<T>.() -> Unit, -): Unit = putAll(prefix, block) public fun <T> DataSink<T>.put(name: String, value: Data<T>) { put(Name.parse(name), value) @@ -56,20 +53,15 @@ public fun <T> DataSink<T>.putAll(name: Name, tree: DataTree<T>) { putAll(name) { putAll(tree.asSequence()) } } -@Deprecated("Use putAll", ReplaceWith("putAll(name, tree)")) -public fun <T> DataSink<T>.branch(name: Name, tree: DataTree<T>): Unit = putAll(name, tree) public fun <T> DataSink<T>.putAll(name: String, tree: DataTree<T>) { putAll(Name.parse(name)) { putAll(tree.asSequence()) } } -@Deprecated("Use putAll", ReplaceWith("putAll(name, tree)")) -public fun <T> DataSink<T>.branch(name: String, tree: DataTree<T>): Unit = putAll(name, tree) - /** * Produce lazy [Data] and emit it into the [MutableDataTree] */ -public inline fun <reified T> DataSink<T>.put( +public inline fun <reified T> DataSink<T>.putValue( name: String, meta: Meta = Meta.EMPTY, noinline producer: suspend () -> T, @@ -78,7 +70,7 @@ public inline fun <reified T> DataSink<T>.put( put(name, data) } -public inline fun <reified T> DataSink<T>.put( +public inline fun <reified T> DataSink<T>.putValue( name: Name, meta: Meta = Meta.EMPTY, noinline producer: suspend () -> T, @@ -90,24 +82,23 @@ public inline fun <reified T> DataSink<T>.put( /** * Emit static data with the fixed value */ -public inline fun <reified T> DataSink<T>.wrap( +public inline fun <reified T> DataSink<T>.putValue( name: String, - data: T, + value: T, meta: Meta = Meta.EMPTY, -): Unit = put(name, Data.static(data, meta)) +): Unit = put(name, Data.wrapValue(value, meta)) -public inline fun <reified T> DataSink<T>.wrap( +public inline fun <reified T> DataSink<T>.putValue( name: Name, - data: T, + value: T, meta: Meta = Meta.EMPTY, -): Unit = put(name, Data.static(data, meta)) +): Unit = put(name, Data.wrapValue(value, meta)) -public inline fun <reified T> DataSink<T>.wrap( +public inline fun <reified T> DataSink<T>.putValue( name: String, - data: T, - mutableMeta: MutableMeta.() -> Unit, -): Unit = put(Name.parse(name), Data.static(data, Meta(mutableMeta))) - + value: T, + metaBuilder: MutableMeta.() -> Unit, +): Unit = put(Name.parse(name), Data.wrapValue(value, Meta(metaBuilder))) public fun <T> DataSink<T>.putAll(sequence: Sequence<NamedData<T>>) { sequence.forEach { @@ -123,18 +114,12 @@ public fun <T> DataSink<T>.putAll(tree: DataTree<T>) { * Copy given data set and mirror its changes to this [DataSink] in [this@setAndObserve]. Returns an update [Job] */ public fun <T : Any> DataSink<T>.putAllAndWatch( + scope: CoroutineScope, branchName: Name = Name.EMPTY, - dataSet: ObservableDataTree<T>, + source: DataTree<T>, ): Job { - putAll(branchName, dataSet) - return dataSet.updates().onEach { + putAll(branchName, source) + return source.updates.onEach { put(branchName + it.name, it.data) - }.launchIn(dataSet.updatesScope) -} - - -@Deprecated("Use putAllAndWatch", ReplaceWith("putAllAndWatch(name, dataSet)")) -public fun <T : Any> DataSink<T>.watchBranch( - name: Name, - dataSet: ObservableDataTree<T>, -): Job = putAllAndWatch(name, dataSet) \ No newline at end of file + }.launchIn(scope) +} \ No newline at end of file diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataTransform.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataTransform.kt index 8c7ce70e..ab54eb3e 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataTransform.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataTransform.kt @@ -1,7 +1,7 @@ package space.kscience.dataforge.data import space.kscience.dataforge.meta.* -import space.kscience.dataforge.misc.DFInternal +import space.kscience.dataforge.misc.UnsafeKType import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.NameToken import kotlin.coroutines.CoroutineContext @@ -68,7 +68,7 @@ internal fun Map<*, Data<*>>.joinMeta(): Meta = Meta { } } -@DFInternal +@UnsafeKType public fun <K, T, R> Map<K, Data<T>>.reduceToData( outputType: KType, meta: Meta = joinMeta(), @@ -103,7 +103,7 @@ public inline fun <K, T, reified R> Map<K, Data<T>>.reduceToData( //Iterable operations -@DFInternal +@UnsafeKType public inline fun <T, R> Iterable<Data<T>>.reduceToData( outputType: KType, meta: Meta = joinMeta(), @@ -118,7 +118,7 @@ public inline fun <T, R> Iterable<Data<T>>.reduceToData( transformation(map { it.awaitWithMeta() }) } -@OptIn(DFInternal::class) +@OptIn(UnsafeKType::class) public inline fun <T, reified R> Iterable<Data<T>>.reduceToData( meta: Meta = joinMeta(), coroutineContext: CoroutineContext = EmptyCoroutineContext, @@ -141,7 +141,7 @@ public inline fun <T, reified R> Iterable<Data<T>>.foldToData( /** * Transform an [Iterable] of [NamedData] to a single [Data]. */ -@DFInternal +@UnsafeKType public inline fun <T, R> Iterable<NamedData<T>>.reduceNamedToData( outputType: KType, meta: Meta = joinMeta(), @@ -156,7 +156,7 @@ public inline fun <T, R> Iterable<NamedData<T>>.reduceNamedToData( transformation(map { it.awaitWithMeta() }) } -@OptIn(DFInternal::class) +@OptIn(UnsafeKType::class) public inline fun <T, reified R> Iterable<NamedData<T>>.reduceNamedToData( meta: Meta = joinMeta(), coroutineContext: CoroutineContext = EmptyCoroutineContext, @@ -181,7 +181,8 @@ public inline fun <T, reified R> Iterable<NamedData<T>>.foldNamedToData( //DataSet operations -@DFInternal + +@UnsafeKType public suspend fun <T, R> DataTree<T>.transform( outputType: KType, metaTransform: MutableMeta.() -> Unit = {}, @@ -198,7 +199,7 @@ public suspend fun <T, R> DataTree<T>.transform( } } -@OptIn(DFInternal::class) +@OptIn(UnsafeKType::class) public suspend inline fun <T, reified R> DataTree<T>.transform( noinline metaTransform: MutableMeta.() -> Unit = {}, coroutineContext: CoroutineContext = EmptyCoroutineContext, diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataTreeBuilder.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataTreeBuilder.kt new file mode 100644 index 00000000..ac0492f0 --- /dev/null +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataTreeBuilder.kt @@ -0,0 +1,112 @@ +package space.kscience.dataforge.data + +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.mapNotNull +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import space.kscience.dataforge.misc.UnsafeKType +import space.kscience.dataforge.names.* +import kotlin.reflect.KType +import kotlin.reflect.typeOf + + +private class FlatDataTree<T>( + override val dataType: KType, + private val dataSet: Map<Name, Data<T>>, + private val sourceUpdates: Flow<DataUpdate<T>>, + private val prefix: Name, +) : DataTree<T> { + override val data: Data<T>? get() = dataSet[prefix] + override val items: Map<NameToken, FlatDataTree<T>> + get() = dataSet.keys + .filter { it.startsWith(prefix) && it.length > prefix.length } + .map { it.tokens[prefix.length] } + .associateWith { FlatDataTree(dataType, dataSet, sourceUpdates, prefix + it) } + + override fun read(name: Name): Data<T>? = dataSet[prefix + name] + + override val updates: Flow<DataUpdate<T>> = + sourceUpdates.mapNotNull { update -> + update.name.removeFirstOrNull(prefix)?.let { DataUpdate(dataType, it, update.data) } + } +} + +/** + * A builder for static [DataTree]. + */ +private class DataTreeBuilder<T>( + private val type: KType, + initialData: Map<Name, Data<T>> = emptyMap(), +) : DataSink<T> { + + private val map = HashMap<Name, Data<T>>(initialData) + + private val mutex = Mutex() + + private val updatesFlow = MutableSharedFlow<DataUpdate<T>>() + + override fun put(name: Name, data: Data<T>?) { + if (data == null) { + map.remove(name) + } else { + map[name] = data + } + } + + override suspend fun update(name: Name, data: Data<T>?) { + mutex.withLock { + if (data == null) { + map.remove(name) + } else { + map.put(name, data) + } + } + updatesFlow.emit(DataUpdate(data?.type ?: type, name, data)) + } + + public fun build(): DataTree<T> = FlatDataTree(type, map, updatesFlow, Name.EMPTY) +} + +/** + * Create a static [DataTree] + */ +@UnsafeKType +public fun <T> DataTree( + dataType: KType, + generator: DataSink<T>.() -> Unit, +): DataTree<T> = DataTreeBuilder<T>(dataType).apply(generator).build() + +/** + * Create and a data tree. + */ +@OptIn(UnsafeKType::class) +public inline fun <reified T> DataTree( + noinline generator: DataSink<T>.() -> Unit, +): DataTree<T> = DataTree(typeOf<T>(), generator) + + +/** + * Represent this flat data map as a [DataTree] without copying it + */ +@UnsafeKType +public fun <T> Map<Name, Data<T>>.asTree(type: KType): DataTree<T> = + DataTreeBuilder(type, this).build() + +/** + * Represent this flat data map as a [DataTree] without copying it + */ +@OptIn(UnsafeKType::class) +public inline fun <reified T> Map<Name, Data<T>>.asTree(): DataTree<T> = asTree(typeOf<T>()) + + +@UnsafeKType +public fun <T> Sequence<NamedData<T>>.toTree(type: KType): DataTree<T> = + DataTreeBuilder(type, associate { it.name to it.data }).build() + + +/** + * Collect a sequence of [NamedData] to a [DataTree] + */ +@OptIn(UnsafeKType::class) +public inline fun <reified T> Sequence<NamedData<T>>.toTree(): DataTree<T> = toTree(typeOf<T>()) diff --git a/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt b/dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt similarity index 65% rename from dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt rename to dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt index f6eae12c..ef9b14ab 100644 --- a/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt +++ b/dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt @@ -1,22 +1,24 @@ package space.kscience.dataforge.data -import kotlinx.coroutines.delay -import kotlinx.coroutines.runBlocking +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.take import kotlinx.coroutines.test.runTest -import org.junit.jupiter.api.Test import space.kscience.dataforge.actions.Action import space.kscience.dataforge.actions.invoke import space.kscience.dataforge.actions.mapping import space.kscience.dataforge.misc.DFExperimental +import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.time.Duration.Companion.milliseconds @OptIn(DFExperimental::class) internal class ActionsTest { @Test - fun testStaticMapAction() = runTest { + fun testStaticMapAction() = runTest(timeout = 500.milliseconds) { val data: DataTree<Int> = DataTree { repeat(10) { - wrap(it.toString(), it) + putValue(it.toString(), it) } } @@ -28,7 +30,7 @@ internal class ActionsTest { } @Test - fun testDynamicMapAction() = runBlocking { + fun testDynamicMapAction() = runTest(timeout = 500.milliseconds) { val source: MutableDataTree<Int> = MutableDataTree() val plusOne = Action.mapping<Int, Int> { @@ -39,13 +41,9 @@ internal class ActionsTest { repeat(10) { - source.wrap(it.toString(), it) + source.putValue(it.toString(), it) } - - delay(20) - - source.close() - result.awaitClose() + result.updates.take(10).onEach { println(it.name) }.collect() assertEquals(2, result["1"]?.await()) } diff --git a/dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt b/dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt new file mode 100644 index 00000000..b5738820 --- /dev/null +++ b/dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt @@ -0,0 +1,71 @@ +package space.kscience.dataforge.data + +import kotlinx.coroutines.cancel +import kotlinx.coroutines.flow.collect +import kotlinx.coroutines.flow.take +import kotlinx.coroutines.launch +import kotlinx.coroutines.test.runTest +import space.kscience.dataforge.names.asName +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.time.Duration.Companion.milliseconds + + +internal class DataTreeBuilderTest { + @Test + fun testTreeBuild() = runTest(timeout = 500.milliseconds) { + val node = DataTree<Any> { + putAll("primary"){ + putValue("a", "a") + putValue("b", "b") + } + putValue("c.d", "c.d") + putValue("c.f", "c.f") + } + assertEquals("a", node["primary.a"]?.await()) + assertEquals("b", node["primary.b"]?.await()) + assertEquals("c.d", node["c.d"]?.await()) + assertEquals("c.f", node["c.f"]?.await()) + + } + + @Test + fun testDataUpdate() = runTest(timeout = 500.milliseconds) { + val updateData = DataTree<Any> { + putAll("update") { + put("a", Data.wrapValue("a")) + put("b", Data.wrapValue("b")) + } + } + + val node = DataTree<Any> { + putAll("primary") { + putValue("a", "a") + putValue("b", "b") + } + putValue("root", "root") + putAll(updateData) + } + + assertEquals("a", node["update.a"]?.await()) + assertEquals("a", node["primary.a"]?.await()) + } + + @Test + fun testDynamicUpdates() = runTest(timeout = 500.milliseconds) { + launch { + val subNode = MutableDataTree<Int>() + + val rootNode = MutableDataTree<Int>() { + putAllAndWatch(this@launch, "sub".asName(), subNode) + } + + repeat(10) { + subNode.putValue("value[$it]", it) + } + subNode.updates.take(10).collect() + assertEquals(9, rootNode["sub.value[9]"]?.await()) + cancel() + }.join() + } +} \ No newline at end of file diff --git a/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataFilterJvm.kt b/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataFilterJvm.kt index 9498c758..0cc81f7a 100644 --- a/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataFilterJvm.kt +++ b/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataFilterJvm.kt @@ -1,6 +1,5 @@ package space.kscience.dataforge.data -import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.filter import space.kscience.dataforge.misc.DFInternal @@ -25,32 +24,40 @@ private fun <R> Data<*>.castOrNull(type: KType): Data<R>? = @Suppress("UNCHECKED_CAST") @DFInternal -public fun <R> Sequence<NamedData<*>>.filterByDataType(type: KType): Sequence<NamedData<R>> = +public fun <R> Sequence<DataUpdate<*>>.filterByDataType(type: KType): Sequence<NamedData<R>> = filter { it.type.isSubtypeOf(type) } as Sequence<NamedData<R>> @Suppress("UNCHECKED_CAST") @DFInternal -public fun <R> Flow<NamedData<*>>.filterByDataType(type: KType): Flow<NamedData<R>> = +public fun <R> Flow<DataUpdate<*>>.filterByDataType(type: KType): Flow<NamedData<R>> = filter { it.type.isSubtypeOf(type) } as Flow<NamedData<R>> /** * Select all data matching given type and filters. Does not modify paths * - * @param predicate additional filtering condition based on item name and meta. By default, accepts all + * @param filter additional filtering condition based on item name and meta. By default, accepts all */ +@Suppress("UNCHECKED_CAST") @DFInternal public fun <R> DataTree<*>.filterByType( type: KType, - predicate: DataFilter = DataFilter.EMPTY, -): DataTree<R> = asSequence().filterByDataType<R>(type).filterData(predicate).toTree(type) + branch: Name = Name.EMPTY, + filter: DataFilter = DataFilter.EMPTY, +): DataTree<R> { + val filterWithType = DataFilter { name, meta, dataType -> + filter.accepts(name, meta, dataType) && dataType.isSubtypeOf(type) + } + return FilteredDataTree(this, filterWithType, branch, type) as DataTree<R> +} /** * Select a single datum of the appropriate type */ @OptIn(DFInternal::class) public inline fun <reified R : Any> DataTree<*>.filterByType( - predicate: DataFilter = DataFilter.EMPTY, -): DataTree<R> = filterByType(typeOf<R>(), predicate) + branch: Name = Name.EMPTY, + filter: DataFilter = DataFilter.EMPTY, +): DataTree<R> = filterByType(typeOf<R>(), branch, filter = filter) /** * Select a single datum if it is present and of given [type] @@ -63,25 +70,3 @@ public inline fun <reified R : Any> DataTree<*>.getByType(name: Name): NamedData public inline fun <reified R : Any> DataTree<*>.getByType(name: String): NamedData<R>? = this@getByType.getByType(typeOf<R>(), Name.parse(name)) - -/** - * Select all data matching given type and filters. Does not modify paths - * - * @param predicate additional filtering condition based on item name and meta. By default, accepts all - */ -@DFInternal -public fun <R> ObservableDataTree<*>.filterByType( - type: KType, - scope: CoroutineScope, - predicate: DataFilter = DataFilter.EMPTY, -): ObservableDataTree<R> = asSequence() - .filterByDataType<R>(type) - .filterData(predicate) - .toObservableTree(type, scope, updates().filterByDataType<R>(type).filterData(predicate)) - - -@OptIn(DFInternal::class) -public inline fun <reified R> ObservableDataTree<*>.filterByType( - scope: CoroutineScope, - predicate: DataFilter = DataFilter.EMPTY, -): ObservableDataTree<R> = filterByType(typeOf<R>(), scope, predicate) \ No newline at end of file diff --git a/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataSetBuilderInContext.kt b/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataSetBuilderInContext.kt index 44602c53..8ce50a22 100644 --- a/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataSetBuilderInContext.kt +++ b/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/dataSetBuilderInContext.kt @@ -14,14 +14,14 @@ public infix fun <T : Any> String.put(data: Data<T>): Unit = * Append node */ context(DataSink<T>) -public infix fun <T : Any> String.put(dataSet: DataTree<T>): Unit = +public infix fun <T : Any> String.putAll(dataSet: DataTree<T>): Unit = putAll(this, dataSet) /** * Build and append node */ context(DataSink<T>) -public infix fun <T : Any> String.put( +public infix fun <T : Any> String.putAll( block: DataSink<T>.() -> Unit, ): Unit = putAll(Name.parse(this), block) diff --git a/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt b/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt deleted file mode 100644 index 561e3aa0..00000000 --- a/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt +++ /dev/null @@ -1,68 +0,0 @@ -package space.kscience.dataforge.data - -import kotlinx.coroutines.delay -import kotlinx.coroutines.runBlocking -import kotlinx.coroutines.test.runTest -import space.kscience.dataforge.misc.DFExperimental -import space.kscience.dataforge.names.asName -import kotlin.test.Test -import kotlin.test.assertEquals - - -internal class DataTreeBuilderTest { - @Test - fun testTreeBuild() = runTest { - val node = DataTree<Any> { - "primary" put { - wrap("a", "a") - wrap("b", "b") - } - wrap("c.d", "c.d") - wrap("c.f", "c.f") - } - assertEquals("a", node["primary.a"]?.await()) - assertEquals("b", node["primary.b"]?.await()) - assertEquals("c.d", node["c.d"]?.await()) - assertEquals("c.f", node["c.f"]?.await()) - - } - - @OptIn(DFExperimental::class) - @Test - fun testDataUpdate() = runTest { - val updateData = DataTree<Any> { - "update" put { - "a" put Data.static("a") - "b" put Data.static("b") - } - } - - val node = DataTree<Any> { - "primary" put { - wrap("a", "a") - wrap("b", "b") - } - wrap("root", "root") - putAll(updateData) - } - - assertEquals("a", node["update.a"]?.await()) - assertEquals("a", node["primary.a"]?.await()) - } - - @Test - fun testDynamicUpdates() = runBlocking { - val subNode = MutableDataTree<Int>() - - val rootNode = MutableDataTree<Int> { - putAllAndWatch("sub".asName(), subNode) - } - - repeat(10) { - subNode.wrap("value[$it]", it) - } - - delay(20) - assertEquals(9, rootNode["sub.value[9]"]?.await()) - } -} \ No newline at end of file diff --git a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Task.kt b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Task.kt index e636de49..372b119f 100644 --- a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Task.kt +++ b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Task.kt @@ -10,6 +10,7 @@ import space.kscience.dataforge.meta.MetaSpec import space.kscience.dataforge.meta.descriptors.Described import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.misc.DfType +import space.kscience.dataforge.misc.UnsafeKType import space.kscience.dataforge.names.Name import space.kscience.dataforge.workspace.Task.Companion.TYPE import kotlin.reflect.KType @@ -90,7 +91,8 @@ public fun <T : Any> Task( taskMeta: Meta, ): TaskResult<T> { //TODO use safe builder and check for external data on add and detects cycles - val dataset = MutableDataTree<T>(resultType, workspace.context).apply { + @OptIn(UnsafeKType::class) + val dataset = MutableDataTree<T>(resultType).apply { TaskResultBuilder(workspace, taskName, taskMeta, this).apply { withContext(GoalExecutionRestriction() + workspace.goalLogger) { builder() @@ -98,7 +100,6 @@ public fun <T : Any> Task( } } return workspace.wrapResult(dataset, taskName, taskMeta) - } } @@ -117,6 +118,7 @@ public inline fun <reified T : Any> Task( * @param builder for resulting data set */ + @Suppress("FunctionName") public fun <T : Any, C : MetaRepr> Task( resultType: KType, @@ -132,7 +134,8 @@ public fun <T : Any, C : MetaRepr> Task( ): TaskResult<T> = withContext(GoalExecutionRestriction() + workspace.goalLogger) { //TODO use safe builder and check for external data on add and detects cycles val taskMeta = configuration.toMeta() - val dataset = MutableDataTree<T>(resultType, this).apply { + @OptIn(UnsafeKType::class) + val dataset = MutableDataTree<T>(resultType).apply { TaskResultBuilder(workspace, taskName, taskMeta, this).apply { builder(configuration) } } workspace.wrapResult(dataset, taskName, taskMeta) diff --git a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/TaskResult.kt b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/TaskResult.kt index 7aa94101..d4d4291a 100644 --- a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/TaskResult.kt +++ b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/TaskResult.kt @@ -4,7 +4,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.joinAll import kotlinx.coroutines.launch -import space.kscience.dataforge.data.ObservableDataTree +import space.kscience.dataforge.data.DataTree import space.kscience.dataforge.data.asSequence import space.kscience.dataforge.data.launch import space.kscience.dataforge.meta.Meta @@ -17,16 +17,16 @@ import space.kscience.dataforge.names.Name * @param taskMeta The configuration of the task that produced the result */ public data class TaskResult<T>( - public val content: ObservableDataTree<T>, + public val content: DataTree<T>, public val workspace: Workspace, public val taskName: Name, public val taskMeta: Meta, -) : ObservableDataTree<T> by content +) : DataTree<T> by content /** * Wrap data into [TaskResult] */ -public fun <T> Workspace.wrapResult(data: ObservableDataTree<T>, taskName: Name, taskMeta: Meta): TaskResult<T> = +public fun <T> Workspace.wrapResult(data: DataTree<T>, taskName: Name, taskMeta: Meta): TaskResult<T> = TaskResult(data, this, taskName, taskMeta) /** diff --git a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Workspace.kt b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Workspace.kt index e4e315fd..7247240b 100644 --- a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Workspace.kt +++ b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Workspace.kt @@ -2,7 +2,10 @@ package space.kscience.dataforge.workspace import kotlinx.coroutines.CoroutineScope import space.kscience.dataforge.context.ContextAware -import space.kscience.dataforge.data.* +import space.kscience.dataforge.data.Data +import space.kscience.dataforge.data.DataTree +import space.kscience.dataforge.data.asSequence +import space.kscience.dataforge.data.get import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.misc.DfType @@ -26,7 +29,7 @@ public interface Workspace : ContextAware, Provider, CoroutineScope { /** * The whole data node for current workspace */ - public val data: ObservableDataTree<*> + public val data: DataTree<*> /** * All targets associated with the workspace diff --git a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/WorkspaceBuilder.kt b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/WorkspaceBuilder.kt index 4705c3b0..cf263a46 100644 --- a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/WorkspaceBuilder.kt +++ b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/WorkspaceBuilder.kt @@ -1,6 +1,5 @@ package space.kscience.dataforge.workspace -import kotlinx.coroutines.CoroutineScope import space.kscience.dataforge.actions.Action import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.ContextBuilder @@ -12,6 +11,7 @@ import space.kscience.dataforge.meta.* import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.MetaDescriptorBuilder import space.kscience.dataforge.misc.DFBuilder +import space.kscience.dataforge.misc.UnsafeKType import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import kotlin.collections.set @@ -98,19 +98,19 @@ public inline fun <reified T : Any> TaskContainer.task( public inline fun <T : Any, reified R : Any> TaskContainer.action( selector: DataSelector<T>, action: Action<T, R>, - noinline metaTransform: MutableMeta.()-> Unit = {}, + noinline metaTransform: MutableMeta.() -> Unit = {}, noinline descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {}, ): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, TaskReference<R>>> = task(MetaDescriptor(descriptorBuilder)) { - result(action.execute(from(selector), taskMeta.copy(metaTransform))) + result(action.execute(from(selector), taskMeta.copy(metaTransform), workspace)) } public class WorkspaceBuilder( private val parentContext: Context = Global, - private val coroutineScope: CoroutineScope = parentContext, ) : TaskContainer { private var context: Context? = null - private val data = MutableDataTree<Any?>(typeOf<Any?>(), coroutineScope) + @OptIn(UnsafeKType::class) + private val data = MutableDataTree<Any?>(typeOf<Any?>()) private val targets: HashMap<String, Meta> = HashMap() private val tasks = HashMap<Name, Task<*>>() private var cache: WorkspaceCache? = null diff --git a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/WorkspaceImpl.kt b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/WorkspaceImpl.kt index 21c5e8c2..94839d62 100644 --- a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/WorkspaceImpl.kt +++ b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/WorkspaceImpl.kt @@ -2,14 +2,14 @@ package space.kscience.dataforge.workspace import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.gather -import space.kscience.dataforge.data.ObservableDataTree +import space.kscience.dataforge.data.DataTree import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.names.Name internal class WorkspaceImpl internal constructor( override val context: Context, - override val data: ObservableDataTree<*>, + override val data: DataTree<*>, override val targets: Map<String, Meta>, tasks: Map<Name, Task<*>>, private val postProcess: suspend (TaskResult<*>) -> TaskResult<*>, diff --git a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/envelopeData.kt b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/envelopeData.kt index d54ff510..a74f8f05 100644 --- a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/envelopeData.kt +++ b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/envelopeData.kt @@ -3,14 +3,14 @@ package space.kscience.dataforge.workspace import space.kscience.dataforge.data.Data import space.kscience.dataforge.data.await import space.kscience.dataforge.io.* -import space.kscience.dataforge.misc.DFInternal +import space.kscience.dataforge.misc.UnsafeKType import kotlin.reflect.typeOf /** * Convert an [Envelope] to a data via given format. The actual parsing is done lazily. */ -@OptIn(DFInternal::class) +@OptIn(UnsafeKType::class) public inline fun <reified T : Any> Envelope.toData(format: IOReader<T>): Data<T> = Data(typeOf<T>(), meta) { data?.readWith(format) ?: error("Can't convert envelope without data to Data") } diff --git a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/taskBuilders.kt b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/taskBuilders.kt index 35fccc99..15565995 100644 --- a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/taskBuilders.kt +++ b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/taskBuilders.kt @@ -113,7 +113,7 @@ public suspend inline fun <T, reified R> TaskResultBuilder<R>.actionFrom( action: Action<T, R>, dependencyMeta: Meta = defaultDependencyMeta, ) { - this.putAll(action.execute(from(selector, dependencyMeta), dependencyMeta)) + putAll(action.execute(from(selector, dependencyMeta), dependencyMeta, workspace)) } diff --git a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/FileWorkspaceCache.kt b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/FileWorkspaceCache.kt index a43657f8..da09c095 100644 --- a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/FileWorkspaceCache.kt +++ b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/FileWorkspaceCache.kt @@ -1,5 +1,6 @@ package space.kscience.dataforge.workspace +import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.map import kotlinx.io.* import kotlinx.serialization.ExperimentalSerializationApi @@ -96,7 +97,7 @@ public class FileWorkspaceCache(public val cacheDirectory: Path) : WorkspaceCach val cachedTree = result.asSequence().map { cacheOne(it) } - .toObservableTree(result.dataType, result.workspace, result.updates().map { cacheOne(it) }) + .toTree(result.dataType, result.updates.filterIsInstance<NamedData<T>>().map { cacheOne(it) }) return result.workspace.wrapResult(cachedTree, result.taskName, result.taskMeta) } diff --git a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/InMemoryWorkspaceCache.kt b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/InMemoryWorkspaceCache.kt index a3792231..f3b2ee15 100644 --- a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/InMemoryWorkspaceCache.kt +++ b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/InMemoryWorkspaceCache.kt @@ -1,5 +1,6 @@ package space.kscience.dataforge.workspace +import kotlinx.coroutines.flow.filterIsInstance import kotlinx.coroutines.flow.map import space.kscience.dataforge.data.* import space.kscience.dataforge.meta.Meta @@ -31,7 +32,7 @@ public class InMemoryWorkspaceCache : WorkspaceCache { val cachedTree = result.asSequence().map { cacheOne(it) } - .toObservableTree(result.dataType, result.workspace, result.updates().map { cacheOne(it) }) + .toTree(result.dataType, result.updates.filterIsInstance<NamedData<T>>().map { cacheOne(it) }) return result.workspace.wrapResult(cachedTree, result.taskName, result.taskMeta) } diff --git a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/readFileData.kt b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/readFileData.kt index e0a4bdef..37dafab9 100644 --- a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/readFileData.kt +++ b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/readFileData.kt @@ -7,14 +7,12 @@ import space.kscience.dataforge.data.StaticData import space.kscience.dataforge.io.* import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.copy +import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.NameToken import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.plus -import java.nio.file.Files -import java.nio.file.Path -import java.nio.file.StandardWatchEventKinds -import java.nio.file.WatchEvent +import java.nio.file.* import java.nio.file.attribute.BasicFileAttributes import java.nio.file.spi.FileSystemProvider import kotlin.io.path.* @@ -166,15 +164,25 @@ public fun DataSink<Binary>.monitorFiles( * @param resources The names of the resources to read. * @param classLoader The class loader to use for loading the resources. By default, it uses the current thread's context class loader. */ +@DFExperimental public fun DataSink<Binary>.resources( io: IOPlugin, - vararg resources: String, + resource: String, + vararg otherResources: String, classLoader: ClassLoader = Thread.currentThread().contextClassLoader, ) { - resources.forEach { resource -> - val path = classLoader.getResource(resource)?.toURI()?.toPath() ?: error( - "Resource with name $resource is not resolved" + //create a file system if necessary + val uri = Thread.currentThread().contextClassLoader.getResource("common")!!.toURI() + try { + uri.toPath() + } catch (e: FileSystemNotFoundException) { + FileSystems.newFileSystem(uri, mapOf("create" to "true")) + } + + listOf(resource,*otherResources).forEach { r -> + val path = classLoader.getResource(r)?.toURI()?.toPath() ?: error( + "Resource with name $r is not resolved" ) - files(io, resource.asName(), path) + files(io, r.asName(), path) } } diff --git a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/CachingWorkspaceTest.kt b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/CachingWorkspaceTest.kt index e5c2c230..7a6a8202 100644 --- a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/CachingWorkspaceTest.kt +++ b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/CachingWorkspaceTest.kt @@ -3,7 +3,7 @@ package space.kscience.dataforge.workspace import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Test -import space.kscience.dataforge.data.wrap +import space.kscience.dataforge.data.putValue import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.boolean import space.kscience.dataforge.meta.get @@ -22,7 +22,7 @@ internal class CachingWorkspaceTest { data { //statically initialize data repeat(5) { - wrap("myData[$it]", it) + putValue("myData[$it]", it) } } diff --git a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/DataPropagationTest.kt b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/DataPropagationTest.kt index d611b1c8..cd38f809 100644 --- a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/DataPropagationTest.kt +++ b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/DataPropagationTest.kt @@ -47,7 +47,7 @@ class DataPropagationTest { } data { repeat(100) { - wrap("myData[$it]", it) + putValue("myData[$it]", it) } } } diff --git a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/FileDataTest.kt b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/FileDataTest.kt index a06f24a5..5466da76 100644 --- a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/FileDataTest.kt +++ b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/FileDataTest.kt @@ -24,11 +24,11 @@ import kotlin.test.assertEquals class FileDataTest { val dataNode = DataTree<String> { putAll("dir") { - wrap("a", "Some string") { + putValue("a", "Some string") { "content" put "Some string" } } - wrap("b", "root data") + putValue("b", "root data") // meta { // "content" put "This is root meta node" // } diff --git a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/FileWorkspaceCacheTest.kt b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/FileWorkspaceCacheTest.kt index 0f16b1c8..0cf4f401 100644 --- a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/FileWorkspaceCacheTest.kt +++ b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/FileWorkspaceCacheTest.kt @@ -3,11 +3,11 @@ package space.kscience.dataforge.workspace import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.Test -import space.kscience.dataforge.data.wrap +import space.kscience.dataforge.data.putValue import space.kscience.dataforge.misc.DFExperimental import java.nio.file.Files -@OptIn(ExperimentalCoroutinesApi::class,DFExperimental::class) +@OptIn(ExperimentalCoroutinesApi::class, DFExperimental::class) class FileWorkspaceCacheTest { @Test @@ -16,7 +16,7 @@ class FileWorkspaceCacheTest { data { //statically initialize data repeat(5) { - wrap("myData[$it]", it) + putValue("myData[$it]", it) } } fileCache(Files.createTempDirectory("dataforge-temporary-cache")) diff --git a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/SimpleWorkspaceTest.kt b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/SimpleWorkspaceTest.kt index b49b9d54..837b61bc 100644 --- a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/SimpleWorkspaceTest.kt +++ b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/SimpleWorkspaceTest.kt @@ -6,7 +6,6 @@ package space.kscience.dataforge.workspace import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.runBlocking import kotlinx.coroutines.test.runTest -import org.junit.jupiter.api.Timeout import space.kscience.dataforge.context.* import space.kscience.dataforge.data.* import space.kscience.dataforge.meta.* @@ -16,6 +15,7 @@ import space.kscience.dataforge.names.plus import kotlin.test.Test import kotlin.test.assertEquals import kotlin.test.assertTrue +import kotlin.time.Duration.Companion.milliseconds /** @@ -62,7 +62,7 @@ internal class SimpleWorkspaceTest { data { //statically initialize data repeat(100) { - wrap("myData[$it]", it) + putValue("myData[$it]", it) } } @@ -148,18 +148,16 @@ internal class SimpleWorkspaceTest { } @Test - @Timeout(1) - fun testWorkspace() = runTest { + fun testWorkspace() = runTest(timeout = 10.milliseconds) { val node = workspace.produce("sum") val res = node.asSequence().single() assertEquals(328350, res.await()) } @Test - @Timeout(1) - fun testMetaPropagation() = runTest { + fun testMetaPropagation() = runTest(timeout = 10.milliseconds) { val node = workspace.produce("sum") { "testFlag" put true } - val res = node.single().await() + val res = node.data!!.await() } @Test @@ -188,7 +186,7 @@ internal class SimpleWorkspaceTest { val node = workspace.produce("filterOne") { "name" put "myData[12]" } - assertEquals(12, node.single().await()) + assertEquals(12, node.data!!.await()) } } \ No newline at end of file From 1c6045324423463e4df2852c2160d80efb3a2b10 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Tue, 16 Apr 2024 15:35:21 +0300 Subject: [PATCH 18/26] Fix NameToken.parse --- CHANGELOG.md | 4 +++- .../kscience/dataforge/names/NameToken.kt | 2 +- .../kscience/dataforge/names/NameTest.kt | 20 +++++++++++++++---- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7c134e6..f709b8be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Added - Name index comparator +- Specialized ByteArrayValue ### Changed - DataSink `branch` is replaced with `putAll` to avoid confusion with DataTree methods @@ -15,7 +16,8 @@ ### Fixed - `listOfScheme` and `listOfConvertable` delegates provides correct items order. - Scheme meta setter works with proper sub-branch. -- +- NameToken.parse improper work with indices + ### Security diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/NameToken.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/NameToken.kt index 0dc83c57..83752b9a 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/NameToken.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/NameToken.kt @@ -69,7 +69,7 @@ public class NameToken(public val body: String, public val index: String? = null public fun parse(string: String): NameToken { val body = string.substringBefore('[') val index = string.substringAfter('[', "") - if (index.isNotEmpty() && index.endsWith(']')) error("NameToken with index must end with ']'") + if (index.isNotEmpty() && !index.endsWith(']')) error("NameToken with index must end with ']'") return NameToken(body, index.removeSuffix("]")) } } diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/names/NameTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/names/NameTest.kt index a5bdf3fc..db630487 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/names/NameTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/names/NameTest.kt @@ -1,9 +1,6 @@ package space.kscience.dataforge.names -import kotlin.test.Test -import kotlin.test.assertEquals -import kotlin.test.assertFalse -import kotlin.test.assertTrue +import kotlin.test.* class NameTest { @Test @@ -50,4 +47,19 @@ class NameTest { val name = Name.parse("a.b.c") assertEquals("a.b".parseAsName(), name.cutLast()) } + + @Test + fun tokenParseTest(){ + val token1 = NameToken.parse("token[index]") + assertEquals("token", token1.body) + assertEquals("index", token1.index) + + val token2 = NameToken.parse("token-body") + assertEquals("token-body", token2.body) + assertEquals("", token2.index) + + assertFails { + NameToken.parse("token[22") + } + } } \ No newline at end of file From a720b63d70bbe0cc32cfc21c057cce4d62f444c3 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Tue, 16 Apr 2024 15:35:59 +0300 Subject: [PATCH 19/26] Add ByteArrayValue --- build.gradle.kts | 2 +- .../kscience/dataforge/meta/MutableMeta.kt | 4 ++++ .../dataforge/values/DoubleArrayValue.kt | 20 +++++++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index d4e22686..b2f7e5e9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { allprojects { group = "space.kscience" - version = "0.8.1" + version = "0.8.2" } subprojects { diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt index 6e4a5daa..69e221f5 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt @@ -128,6 +128,10 @@ public interface MutableMeta : Meta, MutableMetaProvider { setValue(Name.parse(this), array.asValue()) } + public infix fun String.put(array: ByteArray) { + setValue(Name.parse(this), array.asValue()) + } + public infix fun String.put(repr: MetaRepr) { set(Name.parse(this), repr.toMeta()) } diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/values/DoubleArrayValue.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/values/DoubleArrayValue.kt index 59ccecae..30bc2adc 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/values/DoubleArrayValue.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/values/DoubleArrayValue.kt @@ -1,4 +1,24 @@ package space.kscience.dataforge.values +import space.kscience.dataforge.meta.DoubleArrayValue +import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.meta.doubleArray +import space.kscience.dataforge.meta.get +import kotlin.test.Test +import kotlin.test.assertEquals +import kotlin.test.assertTrue + class DoubleArrayValue { + @Test + fun doubleArrayWriteRead(){ + val meta = Meta{ + "doubleArray" put doubleArrayOf(1.0,2.0,3.0) + } + + assertTrue { + meta["doubleArray"]?.value is DoubleArrayValue + } + + assertEquals(2.0, meta["doubleArray"].doubleArray?.get(1)) + } } \ No newline at end of file From 28f4beb3485cf07df493347cb7a317e1217dfcc4 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Tue, 23 Apr 2024 18:59:12 +0300 Subject: [PATCH 20/26] Fix all tests --- CHANGELOG.md | 4 +- build.gradle.kts | 2 +- dataforge-context/api/dataforge-context.api | 2 - .../descriptors/reflectiveDescriptors.kt | 22 +- .../descriptors/TestAutoDescriptors.kt | 13 +- .../kscience/dataforge/actions/MapAction.kt | 6 +- .../kscience/dataforge/data/DataFilter.kt | 2 +- .../space/kscience/dataforge/data/DataSink.kt | 10 +- .../kscience/dataforge/data/dataBuilders.kt | 23 +- .../kscience/dataforge/data/ActionsTest.kt | 2 +- .../dataforge/data/DataTreeBuilderTest.kt | 32 +-- .../space/kscience/dataforge/io/IOPlugin.kt | 6 +- dataforge-meta/api/dataforge-meta.api | 246 ++++++++++-------- .../kscience/dataforge/meta/MetaDelegate.kt | 116 +++++---- .../dataforge/meta/MutableMetaDelegate.kt | 129 +++++---- .../dataforge/workspace/CachingAction.kt | 19 ++ .../dataforge/workspace/FileWorkspaceCache.kt | 23 +- .../workspace/InMemoryWorkspaceCache.kt | 17 +- .../workspace/SimpleWorkspaceTest.kt | 8 +- 19 files changed, 409 insertions(+), 273 deletions(-) create mode 100644 dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/CachingAction.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index f709b8be..a56e56e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### Changed - DataSink `branch` is replaced with `putAll` to avoid confusion with DataTree methods +- Meta delegate now uses a specific class that has a descriptor ### Deprecated @@ -16,7 +17,8 @@ ### Fixed - `listOfScheme` and `listOfConvertable` delegates provides correct items order. - Scheme meta setter works with proper sub-branch. -- NameToken.parse improper work with indices +- NameToken.parse improper work with indices. +- Proper data handling for cache. ### Security diff --git a/build.gradle.kts b/build.gradle.kts index b2f7e5e9..78dc6d35 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { allprojects { group = "space.kscience" - version = "0.8.2" + version = "0.8.2-dev-1" } subprojects { diff --git a/dataforge-context/api/dataforge-context.api b/dataforge-context/api/dataforge-context.api index 12bca176..eb94f89d 100644 --- a/dataforge-context/api/dataforge-context.api +++ b/dataforge-context/api/dataforge-context.api @@ -265,8 +265,6 @@ public abstract interface annotation class space/kscience/dataforge/descriptors/ } public final class space/kscience/dataforge/descriptors/ReflectiveDescriptorsKt { - public static final fun forClass (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor$Companion;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; - public static synthetic fun forClass$default (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor$Companion;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; } public final class space/kscience/dataforge/properties/MetaAsFlowKt { diff --git a/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/descriptors/reflectiveDescriptors.kt b/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/descriptors/reflectiveDescriptors.kt index 1f2db7fc..9c36410a 100644 --- a/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/descriptors/reflectiveDescriptors.kt +++ b/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/descriptors/reflectiveDescriptors.kt @@ -10,11 +10,11 @@ import space.kscience.dataforge.meta.ValueType import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.MetaDescriptorBuilder import space.kscience.dataforge.meta.descriptors.node +import space.kscience.dataforge.misc.DFExperimental import java.net.URL import kotlin.reflect.KClass import kotlin.reflect.full.isSubclassOf import kotlin.reflect.full.memberProperties -import kotlin.reflect.typeOf /** @@ -58,9 +58,9 @@ private fun MetaDescriptorBuilder.loadDescriptorFromResource(resource: Descripto } } - -public fun <T : Any> MetaDescriptor.Companion.forClass( - kClass: KClass<T>, +@DFExperimental +public fun MetaDescriptor.Companion.forClass( + kClass: KClass<out Any>, mod: MetaDescriptorBuilder.() -> Unit = {}, ): MetaDescriptor = MetaDescriptor { when { @@ -79,7 +79,7 @@ public fun <T : Any> MetaDescriptor.Companion.forClass( is DescriptorUrl -> loadDescriptorFromUrl(URL(it.url)) } } - kClass.memberProperties.forEach { property -> + kClass.memberProperties.forEach { property-> var flag = false @@ -88,6 +88,12 @@ public fun <T : Any> MetaDescriptor.Companion.forClass( (property.returnType.classifier as? KClass<*>)?.let { from(forClass(it)) } +// +// (property.getDelegate(Unit) as? MetaDelegate<*>)?.descriptor?.let { +// from(it) +// flag = true +// } + property.annotations.forEach { when (it) { is Description -> { @@ -119,6 +125,6 @@ public fun <T : Any> MetaDescriptor.Companion.forClass( mod() } -@Suppress("UNCHECKED_CAST") -public inline fun <reified T : Scheme> SchemeSpec<T>.autoDescriptor( noinline mod: MetaDescriptorBuilder.() -> Unit = {}): MetaDescriptor = - MetaDescriptor.forClass(typeOf<T>().classifier as KClass<T>, mod) \ No newline at end of file +@DFExperimental +public inline fun <reified T : Scheme> SchemeSpec<T>.autoDescriptor(noinline mod: MetaDescriptorBuilder.() -> Unit = {}): MetaDescriptor = + MetaDescriptor.forClass(T::class, mod) \ No newline at end of file diff --git a/dataforge-context/src/jvmTest/kotlin/space/kscience/dataforge/descriptors/TestAutoDescriptors.kt b/dataforge-context/src/jvmTest/kotlin/space/kscience/dataforge/descriptors/TestAutoDescriptors.kt index 617e85cc..df849ce5 100644 --- a/dataforge-context/src/jvmTest/kotlin/space/kscience/dataforge/descriptors/TestAutoDescriptors.kt +++ b/dataforge-context/src/jvmTest/kotlin/space/kscience/dataforge/descriptors/TestAutoDescriptors.kt @@ -1,3 +1,5 @@ +@file:OptIn(DFExperimental::class) + package space.kscience.dataforge.descriptors import kotlinx.serialization.encodeToString @@ -8,8 +10,9 @@ import space.kscience.dataforge.meta.SchemeSpec import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.int import space.kscience.dataforge.meta.string +import space.kscience.dataforge.misc.DFExperimental -private class TestScheme: Scheme(){ +private class TestScheme : Scheme() { @Description("A") val a by string() @@ -17,15 +20,17 @@ private class TestScheme: Scheme(){ @Description("B") val b by int() - companion object: SchemeSpec<TestScheme>(::TestScheme){ + val c by int() + + companion object : SchemeSpec<TestScheme>(::TestScheme) { override val descriptor: MetaDescriptor = autoDescriptor() } } class TestAutoDescriptors { @Test - fun autoDescriptor(){ + fun autoDescriptor() { val autoDescriptor = MetaDescriptor.forClass(TestScheme::class) - println(Json{prettyPrint = true}.encodeToString(autoDescriptor)) + println(Json { prettyPrint = true }.encodeToString(autoDescriptor)) } } \ No newline at end of file diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt index a1ca8e59..08bf08e9 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt @@ -48,8 +48,8 @@ public class MapActionBuilder<T, R>( public inline fun <reified R1 : R> result(noinline f: suspend ActionEnv.(T) -> R1): Unit = result(typeOf<R1>(), f) } -@PublishedApi -internal class MapAction<T, R>( +@UnsafeKType +public class MapAction<T, R>( outputType: KType, private val block: MapActionBuilder<T, R>.() -> Unit, ) : AbstractAction<T, R>(outputType) { @@ -78,7 +78,6 @@ internal class MapAction<T, R>( //getting new meta val newMeta = builder.meta.seal() - @OptIn(UnsafeKType::class) val newData = Data(builder.outputType, newMeta, dependencies = listOf(data)) { builder.result(env, data.await()) } @@ -106,6 +105,7 @@ internal class MapAction<T, R>( * A one-to-one mapping action */ +@OptIn(UnsafeKType::class) public inline fun <T, reified R> Action.Companion.mapping( noinline builder: MapActionBuilder<T, R>.() -> Unit, ): Action<T, R> = MapAction(typeOf<R>(), builder) diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataFilter.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataFilter.kt index bc66e910..38174e50 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataFilter.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataFilter.kt @@ -61,7 +61,7 @@ internal class FilteredDataTree<T>( override val data: Data<T>? get() = source[branch].takeIf { - filter.accepts(Name.EMPTY, data?.meta, data?.type ?: dataType) + filter.accepts(Name.EMPTY, it?.meta, it?.type ?: dataType) } override val items: Map<NameToken, DataTree<T>> diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSink.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSink.kt index 9d860310..6daeae98 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSink.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSink.kt @@ -2,6 +2,7 @@ package space.kscience.dataforge.data import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job +import kotlinx.coroutines.channels.BufferOverflow import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableSharedFlow import kotlinx.coroutines.flow.mapNotNull @@ -80,7 +81,8 @@ private class MutableDataTreeRoot<T>( override val dataType: KType, ) : MutableDataTree<T> { - override val updates = MutableSharedFlow<DataUpdate<T>>() + override val updates = MutableSharedFlow<DataUpdate<T>>(100, onBufferOverflow = BufferOverflow.DROP_LATEST) + inner class MutableDataTreeBranch(val branchName: Name) : MutableDataTree<T> { @@ -108,10 +110,10 @@ private class MutableDataTreeRoot<T>( override suspend fun update(name: Name, data: Data<T>?) { if (name.isEmpty()) { this.data = data + this@MutableDataTreeRoot.updates.emit(DataUpdate(data?.type ?: dataType, branchName + name, data)) } else { getOrCreateItem(name.first()).update(name.cutFirst(), data) } - this@MutableDataTreeRoot.updates.emit(DataUpdate(data?.type ?: dataType, branchName + name, data)) } } @@ -122,7 +124,7 @@ private class MutableDataTreeRoot<T>( override val items = HashMap<NameToken, MutableDataTree<T>>() override fun getOrCreateItem(token: NameToken): MutableDataTree<T> = items.getOrPut(token) { - MutableDataTreeRoot(dataType) + MutableDataTreeBranch(token.asName()) } override fun set(token: NameToken, data: Data<T>?) { @@ -133,10 +135,10 @@ private class MutableDataTreeRoot<T>( override suspend fun update(name: Name, data: Data<T>?) { if (name.isEmpty()) { this.data = data + updates.emit(DataUpdate(data?.type ?: dataType, name, data)) } else { getOrCreateItem(name.first()).update(name.cutFirst(), data) } - updates.emit(DataUpdate(data?.type ?: dataType, name, data)) } } diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataBuilders.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataBuilders.kt index 8ec3e361..649cfd19 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataBuilders.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataBuilders.kt @@ -6,10 +6,7 @@ import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MutableMeta -import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.asName -import space.kscience.dataforge.names.isEmpty -import space.kscience.dataforge.names.plus +import space.kscience.dataforge.names.* public fun <T> DataSink<T>.put(value: NamedData<T>) { @@ -83,13 +80,13 @@ public inline fun <reified T> DataSink<T>.putValue( * Emit static data with the fixed value */ public inline fun <reified T> DataSink<T>.putValue( - name: String, + name: Name, value: T, meta: Meta = Meta.EMPTY, ): Unit = put(name, Data.wrapValue(value, meta)) public inline fun <reified T> DataSink<T>.putValue( - name: Name, + name: String, value: T, meta: Meta = Meta.EMPTY, ): Unit = put(name, Data.wrapValue(value, meta)) @@ -100,6 +97,18 @@ public inline fun <reified T> DataSink<T>.putValue( metaBuilder: MutableMeta.() -> Unit, ): Unit = put(Name.parse(name), Data.wrapValue(value, Meta(metaBuilder))) +public suspend inline fun <reified T> DataSink<T>.updateValue( + name: Name, + value: T, + meta: Meta = Meta.EMPTY, +): Unit = update(name, Data.wrapValue(value, meta)) + +public suspend inline fun <reified T> DataSink<T>.updateValue( + name: String, + value: T, + meta: Meta = Meta.EMPTY, +): Unit = update(name.parseAsName(), Data.wrapValue(value, meta)) + public fun <T> DataSink<T>.putAll(sequence: Sequence<NamedData<T>>) { sequence.forEach { put(it.name, it.data) @@ -120,6 +129,6 @@ public fun <T : Any> DataSink<T>.putAllAndWatch( ): Job { putAll(branchName, source) return source.updates.onEach { - put(branchName + it.name, it.data) + update(branchName + it.name, it.data) }.launchIn(scope) } \ No newline at end of file diff --git a/dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt b/dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt index ef9b14ab..477ca592 100644 --- a/dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt +++ b/dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt @@ -41,7 +41,7 @@ internal class ActionsTest { repeat(10) { - source.putValue(it.toString(), it) + source.updateValue(it.toString(), it) } result.updates.take(10).onEach { println(it.name) }.collect() diff --git a/dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt b/dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt index b5738820..760aeec2 100644 --- a/dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt +++ b/dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/DataTreeBuilderTest.kt @@ -1,9 +1,8 @@ package space.kscience.dataforge.data -import kotlinx.coroutines.cancel +import kotlinx.coroutines.Job import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.take -import kotlinx.coroutines.launch import kotlinx.coroutines.test.runTest import space.kscience.dataforge.names.asName import kotlin.test.Test @@ -15,7 +14,7 @@ internal class DataTreeBuilderTest { @Test fun testTreeBuild() = runTest(timeout = 500.milliseconds) { val node = DataTree<Any> { - putAll("primary"){ + putAll("primary") { putValue("a", "a") putValue("b", "b") } @@ -53,19 +52,22 @@ internal class DataTreeBuilderTest { @Test fun testDynamicUpdates() = runTest(timeout = 500.milliseconds) { - launch { - val subNode = MutableDataTree<Int>() + var job: Job? = null - val rootNode = MutableDataTree<Int>() { - putAllAndWatch(this@launch, "sub".asName(), subNode) - } + val subNode = MutableDataTree<Int>() - repeat(10) { - subNode.putValue("value[$it]", it) - } - subNode.updates.take(10).collect() - assertEquals(9, rootNode["sub.value[9]"]?.await()) - cancel() - }.join() + val rootNode = MutableDataTree<Int>() { + job = putAllAndWatch(this@runTest, "sub".asName(), subNode) + } + + repeat(10) { + subNode.updateValue("value[$it]", it) + } + + rootNode.updates.take(10).collect() + assertEquals(9, rootNode["sub.value[9]"]?.await()) + assertEquals(8, rootNode["sub.value[8]"]?.await()) + + job?.cancel() } } \ No newline at end of file diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/IOPlugin.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/IOPlugin.kt index 0d79da4d..f431a731 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/IOPlugin.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/IOPlugin.kt @@ -6,7 +6,7 @@ import space.kscience.dataforge.io.IOFormatFactory.Companion.IO_FORMAT_TYPE import space.kscience.dataforge.io.MetaFormatFactory.Companion.META_FORMAT_TYPE import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.string -import space.kscience.dataforge.misc.DFInternal +import space.kscience.dataforge.misc.UnsafeKType import space.kscience.dataforge.names.Name import kotlin.reflect.KType import kotlin.reflect.typeOf @@ -19,11 +19,11 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) { } @Suppress("UNCHECKED_CAST") - @DFInternal + @UnsafeKType public fun <T> resolveIOFormat(type: KType, meta: Meta): IOFormat<T>? = ioFormatFactories.singleOrNull { it.type == type }?.build(context, meta) as? IOFormat<T> - @OptIn(DFInternal::class) + @OptIn(UnsafeKType::class) public inline fun <reified T> resolveIOFormat(meta: Meta = Meta.EMPTY): IOFormat<T>? = resolveIOFormat(typeOf<T>(), meta) diff --git a/dataforge-meta/api/dataforge-meta.api b/dataforge-meta/api/dataforge-meta.api index f9834c54..620e64d4 100644 --- a/dataforge-meta/api/dataforge-meta.api +++ b/dataforge-meta/api/dataforge-meta.api @@ -1,3 +1,15 @@ +public final class space/kscience/dataforge/meta/ByteArrayValue : java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker, space/kscience/dataforge/meta/Value { + public fun <init> ([B)V + public fun equals (Ljava/lang/Object;)Z + public fun getList ()Ljava/util/List; + public fun getType ()Lspace/kscience/dataforge/meta/ValueType; + public synthetic fun getValue ()Ljava/lang/Object; + public fun getValue ()[B + public fun hashCode ()I + public fun iterator ()Ljava/util/Iterator; + public fun toString ()Ljava/lang/String; +} + public abstract interface class space/kscience/dataforge/meta/Configurable { public abstract fun getMeta ()Lspace/kscience/dataforge/meta/MutableMeta; } @@ -30,7 +42,20 @@ public final class space/kscience/dataforge/meta/EnumValue : space/kscience/data } public final class space/kscience/dataforge/meta/ExoticValuesKt { + public static final fun asValue ([B)Lspace/kscience/dataforge/meta/Value; public static final fun asValue ([D)Lspace/kscience/dataforge/meta/Value; + public static final fun byteArray (Lspace/kscience/dataforge/meta/MetaProvider;[BLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static final fun byteArray (Lspace/kscience/dataforge/meta/MutableMetaProvider;[BLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun byteArray$default (Lspace/kscience/dataforge/meta/MetaProvider;[BLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun byteArray$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[BLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun doubleArray (Lspace/kscience/dataforge/meta/MetaProvider;[DLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static final fun doubleArray (Lspace/kscience/dataforge/meta/MutableMetaProvider;[DLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun doubleArray$default (Lspace/kscience/dataforge/meta/MetaProvider;[DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun doubleArray$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun getByteArray (Lspace/kscience/dataforge/meta/Meta;)[B + public static final fun getByteArray (Lspace/kscience/dataforge/meta/Value;)[B + public static final fun getDoubleArray (Lspace/kscience/dataforge/meta/Meta;)[D + public static final fun getDoubleArray (Lspace/kscience/dataforge/meta/Value;)[D public static final fun lazyParseValue (Ljava/lang/String;)Lspace/kscience/dataforge/meta/LazyParsedValue; } @@ -199,53 +224,56 @@ public final class space/kscience/dataforge/meta/MetaConverterKt { public static final fun convertNullable (Lspace/kscience/dataforge/meta/MetaConverter;Ljava/lang/Object;)Lspace/kscience/dataforge/meta/Meta; } +public abstract interface class space/kscience/dataforge/meta/MetaDelegate : kotlin/properties/ReadOnlyProperty, space/kscience/dataforge/meta/descriptors/Described { +} + public final class space/kscience/dataforge/meta/MetaDelegateKt { - public static final fun boolean (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun boolean (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty; - public static final fun boolean (Lspace/kscience/dataforge/meta/MetaProvider;ZLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MetaProvider;ZLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun double (Lspace/kscience/dataforge/meta/MetaProvider;DLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun double (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MetaProvider;DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun float (Lspace/kscience/dataforge/meta/MetaProvider;FLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun float (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MetaProvider;FLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun int (Lspace/kscience/dataforge/meta/MetaProvider;ILspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun int (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MetaProvider;ILspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun listOfSpec (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun listOfSpec$default (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun long (Lspace/kscience/dataforge/meta/MetaProvider;JLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun long (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MetaProvider;JLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun node (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static final fun boolean (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun boolean (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun boolean (Lspace/kscience/dataforge/meta/MetaProvider;ZLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MetaProvider;ZLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun double (Lspace/kscience/dataforge/meta/MetaProvider;DLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun double (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MetaProvider;DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun float (Lspace/kscience/dataforge/meta/MetaProvider;FLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun float (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MetaProvider;FLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun int (Lspace/kscience/dataforge/meta/MetaProvider;ILspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun int (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MetaProvider;ILspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun listOfSpec (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun listOfSpec$default (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun long (Lspace/kscience/dataforge/meta/MetaProvider;JLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun long (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MetaProvider;JLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; public static final fun node (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaSpec;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static final fun node (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lspace/kscience/dataforge/meta/MetaDelegate; public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaSpec;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun spec (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun spec$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun value (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun value (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun spec (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun spec$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun value (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun value (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; } public final class space/kscience/dataforge/meta/MetaKt { @@ -352,6 +380,7 @@ public abstract interface class space/kscience/dataforge/meta/MutableMeta : spac public fun put (Ljava/lang/String;Lspace/kscience/dataforge/meta/MetaRepr;)V public fun put (Ljava/lang/String;Lspace/kscience/dataforge/meta/Value;)V public fun put (Ljava/lang/String;Z)V + public fun put (Ljava/lang/String;[B)V public fun put (Ljava/lang/String;[D)V public fun put (Lspace/kscience/dataforge/names/Name;Ljava/lang/Enum;)V public fun put (Lspace/kscience/dataforge/names/Name;Ljava/lang/Number;)V @@ -371,63 +400,64 @@ public final class space/kscience/dataforge/meta/MutableMeta$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public abstract interface class space/kscience/dataforge/meta/MutableMetaDelegate : kotlin/properties/ReadWriteProperty, space/kscience/dataforge/meta/descriptors/Described { +} + public final class space/kscience/dataforge/meta/MutableMetaDelegateKt { - public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty; - public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;ZLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;ZLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun convertable (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/meta/MetaConverter;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun convertable$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/meta/MetaConverter;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun double (Lspace/kscience/dataforge/meta/MutableMetaProvider;DLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun double (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun doubleArray (Lspace/kscience/dataforge/meta/MutableMetaProvider;[DLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun doubleArray$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun float (Lspace/kscience/dataforge/meta/MutableMetaProvider;FLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun float (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;FLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun int (Lspace/kscience/dataforge/meta/MutableMetaProvider;ILspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun int (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;ILspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun listOfConvertable (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/MetaConverter;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun listOfConvertable$default (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/MetaConverter;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun listValue (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun listValue$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun long (Lspace/kscience/dataforge/meta/MutableMetaProvider;JLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun long (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;JLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun node (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun node (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaConverter;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaConverter;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun number (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun number (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun number (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun numberList (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun numberList$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun string (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun string (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun string (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun stringList (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun stringList (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun stringList$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun stringList$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun value (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun value (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;ZLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;ZLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun convertable (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/meta/MetaConverter;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun convertable$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/meta/MetaConverter;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun double (Lspace/kscience/dataforge/meta/MutableMetaProvider;DLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun double (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun float (Lspace/kscience/dataforge/meta/MutableMetaProvider;FLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun float (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;FLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun int (Lspace/kscience/dataforge/meta/MutableMetaProvider;ILspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun int (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;ILspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun listOfConvertable (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/MetaConverter;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun listOfConvertable$default (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/MetaConverter;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun listValue (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun listValue$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun long (Lspace/kscience/dataforge/meta/MutableMetaProvider;JLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun long (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;JLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun node (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaConverter;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun node (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaConverter;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun number (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun number (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun number (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun numberList (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun numberList$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun string (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun string (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun string (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun stringList (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun stringList (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun stringList$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun stringList$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun value (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static final fun value (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; + public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableMetaDelegate; } public final class space/kscience/dataforge/meta/MutableMetaKt { @@ -447,6 +477,7 @@ public final class space/kscience/dataforge/meta/MutableMetaKt { public static final fun getOrCreate (Lspace/kscience/dataforge/meta/MutableTypedMeta;Ljava/lang/String;)Lspace/kscience/dataforge/meta/MutableTypedMeta; public static final fun remove (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;)V public static final fun remove (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)V + public static final fun reset (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/Meta;)V public static final fun set (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Ljava/lang/Iterable;)V public static final fun set (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/meta/Meta;)V public static final fun set (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Ljava/lang/Iterable;)V @@ -703,7 +734,6 @@ public final class space/kscience/dataforge/meta/Value$Companion { public final class space/kscience/dataforge/meta/ValueExtensionsKt { public static final fun getBoolean (Lspace/kscience/dataforge/meta/Value;)Z public static final fun getDouble (Lspace/kscience/dataforge/meta/Value;)D - public static final fun getDoubleArray (Lspace/kscience/dataforge/meta/Value;)[D public static final fun getFloat (Lspace/kscience/dataforge/meta/Value;)F public static final fun getInt (Lspace/kscience/dataforge/meta/Value;)I public static final fun getLong (Lspace/kscience/dataforge/meta/Value;)J @@ -722,7 +752,6 @@ public final class space/kscience/dataforge/meta/ValueKt { public static final fun asValue (Ljava/lang/Number;)Lspace/kscience/dataforge/meta/Value; public static final fun asValue (Ljava/lang/String;)Lspace/kscience/dataforge/meta/Value; public static final fun asValue (Z)Lspace/kscience/dataforge/meta/Value; - public static final fun asValue ([B)Lspace/kscience/dataforge/meta/Value; public static final fun asValue ([F)Lspace/kscience/dataforge/meta/Value; public static final fun asValue ([I)Lspace/kscience/dataforge/meta/Value; public static final fun asValue ([J)Lspace/kscience/dataforge/meta/Value; @@ -928,6 +957,9 @@ public final class space/kscience/dataforge/misc/NamedKt { public static final fun isAnonymous (Lspace/kscience/dataforge/misc/Named;)Z } +public abstract interface annotation class space/kscience/dataforge/misc/UnsafeKType : java/lang/annotation/Annotation { +} + public final class space/kscience/dataforge/names/Name { public static final field Companion Lspace/kscience/dataforge/names/Name$Companion; public static final field NAME_SEPARATOR Ljava/lang/String; @@ -945,6 +977,16 @@ public final class space/kscience/dataforge/names/Name$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class space/kscience/dataforge/names/NameIndexComparator : java/util/Comparator { + public static final field INSTANCE Lspace/kscience/dataforge/names/NameIndexComparator; + public synthetic fun compare (Ljava/lang/Object;Ljava/lang/Object;)I + public fun compare (Ljava/lang/String;Ljava/lang/String;)I +} + +public final class space/kscience/dataforge/names/NameIndexComparatorKt { + public static final fun getIndexedList (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/names/Name;)Ljava/util/List; +} + public final class space/kscience/dataforge/names/NameKt { public static final fun appendFirst (Lspace/kscience/dataforge/names/Name;Ljava/lang/String;)Lspace/kscience/dataforge/names/Name; public static final fun appendLeft (Lspace/kscience/dataforge/names/Name;Ljava/lang/String;)Lspace/kscience/dataforge/names/Name; diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt index a24f7371..8c5a738f 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt @@ -1,15 +1,27 @@ package space.kscience.dataforge.meta +import space.kscience.dataforge.meta.descriptors.Described import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import kotlin.properties.ReadOnlyProperty +import kotlin.reflect.KProperty /* Meta delegates */ -public fun MetaProvider.node(key: Name? = null): ReadOnlyProperty<Any?, Meta?> = ReadOnlyProperty { _, property -> - get(key ?: property.name.asName()) +public interface MetaDelegate<T> : ReadOnlyProperty<Any?, T>, Described + + +public fun MetaProvider.node( + key: Name? = null, + descriptor: MetaDescriptor? = null, +): MetaDelegate<Meta?> = object : MetaDelegate<Meta?> { + override val descriptor: MetaDescriptor? = descriptor + + override fun getValue(thisRef: Any?, property: KProperty<*>): Meta? { + return get(key ?: property.name.asName()) + } } /** @@ -18,8 +30,12 @@ public fun MetaProvider.node(key: Name? = null): ReadOnlyProperty<Any?, Meta?> = public fun <T> MetaProvider.spec( metaSpec: MetaSpec<T>, key: Name? = null, -): ReadOnlyProperty<Any?, T?> = ReadOnlyProperty { _, property -> - get(key ?: property.name.asName())?.let { metaSpec.read(it) } +): MetaDelegate<T?> = object : MetaDelegate<T?> { + override val descriptor: MetaDescriptor? get() = metaSpec.descriptor + + override fun getValue(thisRef: Any?, property: KProperty<*>): T? { + return get(key ?: property.name.asName())?.let { metaSpec.read(it) } + } } /** @@ -27,9 +43,9 @@ public fun <T> MetaProvider.spec( */ @DFExperimental public inline fun <reified T> MetaProvider.serializable( - descriptor: MetaDescriptor? = null, key: Name? = null, -): ReadOnlyProperty<Any?, T?> = spec(MetaConverter.serializable(descriptor), key) + descriptor: MetaDescriptor? = null, +): MetaDelegate<T?> = spec(MetaConverter.serializable(descriptor), key) @Deprecated("Use convertable", ReplaceWith("convertable(converter, key)")) public fun <T> MetaProvider.node( @@ -43,78 +59,90 @@ public fun <T> MetaProvider.node( public fun <T> Meta.listOfSpec( converter: MetaSpec<T>, key: Name? = null, -): ReadOnlyProperty<Any?, List<T>> = ReadOnlyProperty{_, property -> - val name = key ?: property.name.asName() - getIndexed(name).values.map { converter.read(it) } +): MetaDelegate<List<T>> = object : MetaDelegate<List<T>> { + override fun getValue(thisRef: Any?, property: KProperty<*>): List<T> { + val name = key ?: property.name.asName() + return getIndexed(name).values.map { converter.read(it) } + } + + override val descriptor: MetaDescriptor? = converter.descriptor?.copy(multiple = true) } @DFExperimental public inline fun <reified T> Meta.listOfSerializable( - descriptor: MetaDescriptor? = null, key: Name? = null, -): ReadOnlyProperty<Any?, List<T>> = listOfSpec(MetaConverter.serializable(descriptor), key) + descriptor: MetaDescriptor? = null, +): MetaDelegate<List<T>> = listOfSpec(MetaConverter.serializable(descriptor), key) /** * A property delegate that uses custom key */ -public fun MetaProvider.value(key: Name? = null): ReadOnlyProperty<Any?, Value?> = ReadOnlyProperty { _, property -> - get(key ?: property.name.asName())?.value +public fun MetaProvider.value( + key: Name? = null, + descriptor: MetaDescriptor? = null, +): MetaDelegate<Value?> = object : MetaDelegate<Value?> { + override fun getValue(thisRef: Any?, property: KProperty<*>): Value? = get(key ?: property.name.asName())?.value + + override val descriptor: MetaDescriptor? = descriptor } public fun <R> MetaProvider.value( key: Name? = null, + descriptor: MetaDescriptor? = null, reader: (Value?) -> R, -): ReadOnlyProperty<Any?, R> = ReadOnlyProperty { _, property -> - reader(get(key ?: property.name.asName())?.value) +): MetaDelegate<R> = object : MetaDelegate<R> { + override fun getValue(thisRef: Any?, property: KProperty<*>): R = reader(get(key ?: property.name.asName())?.value) + + override val descriptor: MetaDescriptor? = descriptor } //TODO add caching for sealed nodes /* Read-only delegates for [Meta] */ -public fun MetaProvider.string(key: Name? = null): ReadOnlyProperty<Any?, String?> = value(key) { it?.string } +public fun MetaProvider.string(key: Name? = null): MetaDelegate<String?> = value(key = key) { it?.string } -public fun MetaProvider.boolean(key: Name? = null): ReadOnlyProperty<Any?, Boolean?> = value(key) { it?.boolean } +public fun MetaProvider.boolean(key: Name? = null): MetaDelegate<Boolean?> = value(key = key) { it?.boolean } -public fun MetaProvider.number(key: Name? = null): ReadOnlyProperty<Any?, Number?> = value(key) { it?.numberOrNull } +public fun MetaProvider.number(key: Name? = null): MetaDelegate<Number?> = value(key = key) { it?.numberOrNull } -public fun MetaProvider.double(key: Name? = null): ReadOnlyProperty<Any?, Double?> = value(key) { it?.double } +public fun MetaProvider.double(key: Name? = null): MetaDelegate<Double?> = value(key = key) { it?.double } -public fun MetaProvider.float(key: Name? = null): ReadOnlyProperty<Any?, Float?> = value(key) { it?.float } +public fun MetaProvider.float(key: Name? = null): MetaDelegate<Float?> = value(key = key) { it?.float } -public fun MetaProvider.int(key: Name? = null): ReadOnlyProperty<Any?, Int?> = value(key) { it?.int } +public fun MetaProvider.int(key: Name? = null): MetaDelegate<Int?> = value(key = key) { it?.int } -public fun MetaProvider.long(key: Name? = null): ReadOnlyProperty<Any?, Long?> = value(key) { it?.long } +public fun MetaProvider.long(key: Name? = null): MetaDelegate<Long?> = value(key = key) { it?.long } -public fun MetaProvider.string(default: String, key: Name? = null): ReadOnlyProperty<Any?, String> = - value(key) { it?.string ?: default } +public fun MetaProvider.string(default: String, key: Name? = null): MetaDelegate<String> = + value(key = key) { it?.string ?: default } -public fun MetaProvider.boolean(default: Boolean, key: Name? = null): ReadOnlyProperty<Any?, Boolean> = - value(key) { it?.boolean ?: default } +public fun MetaProvider.boolean(default: Boolean, key: Name? = null): MetaDelegate<Boolean> = + value(key = key) { it?.boolean ?: default } -public fun MetaProvider.number(default: Number, key: Name? = null): ReadOnlyProperty<Any?, Number> = - value(key) { it?.numberOrNull ?: default } +public fun MetaProvider.number(default: Number, key: Name? = null): MetaDelegate<Number> = + value(key = key) { it?.numberOrNull ?: default } -public fun MetaProvider.double(default: Double, key: Name? = null): ReadOnlyProperty<Any?, Double> = - value(key) { it?.double ?: default } +public fun MetaProvider.double(default: Double, key: Name? = null): MetaDelegate<Double> = + value(key = key) { it?.double ?: default } -public fun MetaProvider.float(default: Float, key: Name? = null): ReadOnlyProperty<Any?, Float> = - value(key) { it?.float ?: default } +public fun MetaProvider.float(default: Float, key: Name? = null): MetaDelegate<Float> = + value(key = key) { it?.float ?: default } -public fun MetaProvider.int(default: Int, key: Name? = null): ReadOnlyProperty<Any?, Int> = - value(key) { it?.int ?: default } +public fun MetaProvider.int(default: Int, key: Name? = null): MetaDelegate<Int> = + value(key = key) { it?.int ?: default } -public fun MetaProvider.long(default: Long, key: Name? = null): ReadOnlyProperty<Any?, Long> = - value(key) { it?.long ?: default } +public fun MetaProvider.long(default: Long, key: Name? = null): MetaDelegate<Long> = + value(key = key) { it?.long ?: default } -public inline fun <reified E : Enum<E>> MetaProvider.enum(default: E, key: Name? = null): ReadOnlyProperty<Any?, E> = - value<E>(key) { it?.enum<E>() ?: default } +public inline fun <reified E : Enum<E>> MetaProvider.enum(default: E, key: Name? = null): MetaDelegate<E> = + value<E>(key = key) { it?.enum<E>() ?: default } -public fun MetaProvider.string(key: Name? = null, default: () -> String): ReadOnlyProperty<Any?, String> = - value(key) { it?.string ?: default() } +public fun MetaProvider.string(key: Name? = null, default: () -> String): MetaDelegate<String> = + value(key = key) { it?.string ?: default() } -public fun MetaProvider.boolean(key: Name? = null, default: () -> Boolean): ReadOnlyProperty<Any?, Boolean> = - value(key) { it?.boolean ?: default() } +public fun MetaProvider.boolean(key: Name? = null, default: () -> Boolean): MetaDelegate<Boolean> = + value(key = key) { it?.boolean ?: default() } -public fun MetaProvider.number(key: Name? = null, default: () -> Number): ReadOnlyProperty<Any?, Number> = - value(key) { it?.numberOrNull ?: default() } +public fun MetaProvider.number(key: Name? = null, default: () -> Number): MetaDelegate<Number> = + value(key = key) { it?.numberOrNull ?: default() } diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt index e308a63d..37140c6f 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt @@ -1,5 +1,6 @@ package space.kscience.dataforge.meta +import space.kscience.dataforge.meta.descriptors.Described import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name @@ -8,20 +9,28 @@ import space.kscience.dataforge.names.getIndexedList import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty + /* Read-write delegates */ -public fun MutableMetaProvider.node(key: Name? = null): ReadWriteProperty<Any?, Meta?> = - object : ReadWriteProperty<Any?, Meta?> { - override fun getValue(thisRef: Any?, property: KProperty<*>): Meta? { - return get(key ?: property.name.asName()) - } +public interface MutableMetaDelegate<T> : ReadWriteProperty<Any?, T>, Described - override fun setValue(thisRef: Any?, property: KProperty<*>, value: Meta?) { - val name = key ?: property.name.asName() - set(name, value) - } +public fun MutableMetaProvider.node( + key: Name? = null, + descriptor: MetaDescriptor? = null, +): MutableMetaDelegate<Meta?> = object : MutableMetaDelegate<Meta?> { + + override val descriptor: MetaDescriptor? = descriptor + + override fun getValue(thisRef: Any?, property: KProperty<*>): Meta? { + return get(key ?: property.name.asName()) } + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Meta?) { + val name = key ?: property.name.asName() + set(name, value) + } +} + /** * Use [converter] to transform an object to Meta and back. * Note that mutation of the object does not change Meta. @@ -29,21 +38,24 @@ public fun MutableMetaProvider.node(key: Name? = null): ReadWriteProperty<Any?, public fun <T> MutableMetaProvider.convertable( converter: MetaConverter<T>, key: Name? = null, -): ReadWriteProperty<Any?, T?> = - object : ReadWriteProperty<Any?, T?> { - override fun getValue(thisRef: Any?, property: KProperty<*>): T? { - val name = key ?: property.name.asName() - return get(name)?.let { converter.read(it) } - } +): MutableMetaDelegate<T?> = object : MutableMetaDelegate<T?> { - override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) { - val name = key ?: property.name.asName() - set(name, value?.let { converter.convert(it) }) - } + override val descriptor: MetaDescriptor? get() = converter.descriptor + + + override fun getValue(thisRef: Any?, property: KProperty<*>): T? { + val name = key ?: property.name.asName() + return get(name)?.let { converter.read(it) } } + override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) { + val name = key ?: property.name.asName() + set(name, value?.let { converter.convert(it) }) + } +} + @Deprecated("Use convertable", ReplaceWith("convertable(converter, key)")) -public fun <T> MutableMetaProvider.node(key: Name? = null, converter: MetaConverter<T>): ReadWriteProperty<Any?, T?> = +public fun <T> MutableMetaProvider.node(key: Name? = null, converter: MetaConverter<T>): MutableMetaDelegate<T?> = convertable(converter, key) /** @@ -54,7 +66,7 @@ public fun <T> MutableMetaProvider.node(key: Name? = null, converter: MetaConver public inline fun <reified T> MutableMetaProvider.serializable( descriptor: MetaDescriptor? = null, key: Name? = null, -): ReadWriteProperty<Any?, T?> = convertable(MetaConverter.serializable(descriptor), key) +): MutableMetaDelegate<T?> = convertable(MetaConverter.serializable(descriptor), key) /** * Use [converter] to convert a list of same name siblings meta to object and back. @@ -63,7 +75,9 @@ public inline fun <reified T> MutableMetaProvider.serializable( public fun <T> MutableMeta.listOfConvertable( converter: MetaConverter<T>, key: Name? = null, -): ReadWriteProperty<Any?, List<T>> = object : ReadWriteProperty<Any?, List<T>> { +): MutableMetaDelegate<List<T>> = object : MutableMetaDelegate<List<T>> { + override val descriptor: MetaDescriptor? = converter.descriptor?.copy(multiple = true) + override fun getValue(thisRef: Any?, property: KProperty<*>): List<T> { val name = key ?: property.name.asName() return getIndexedList(name).map { converter.read(it) } @@ -77,26 +91,33 @@ public fun <T> MutableMeta.listOfConvertable( @DFExperimental public inline fun <reified T> MutableMeta.listOfSerializable( - descriptor: MetaDescriptor? = null, key: Name? = null, -): ReadWriteProperty<Any?, List<T>> = listOfConvertable(MetaConverter.serializable(descriptor), key) + descriptor: MetaDescriptor? = null, +): MutableMetaDelegate<List<T>> = listOfConvertable(MetaConverter.serializable(descriptor), key) -public fun MutableMetaProvider.value(key: Name? = null): ReadWriteProperty<Any?, Value?> = - object : ReadWriteProperty<Any?, Value?> { - override fun getValue(thisRef: Any?, property: KProperty<*>): Value? = - get(key ?: property.name.asName())?.value +public fun MutableMetaProvider.value( + key: Name? = null, + descriptor: MetaDescriptor? = null, +): MutableMetaDelegate<Value?> = object : MutableMetaDelegate<Value?> { + override val descriptor: MetaDescriptor? = descriptor - override fun setValue(thisRef: Any?, property: KProperty<*>, value: Value?) { - setValue(key ?: property.name.asName(), value) - } + override fun getValue(thisRef: Any?, property: KProperty<*>): Value? = + get(key ?: property.name.asName())?.value + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Value?) { + setValue(key ?: property.name.asName(), value) } +} public fun <T> MutableMetaProvider.value( key: Name? = null, writer: (T) -> Value? = { Value.of(it) }, + descriptor: MetaDescriptor? = null, reader: (Value?) -> T, -): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> { +): MutableMetaDelegate<T> = object : MutableMetaDelegate<T> { + override val descriptor: MetaDescriptor? = descriptor + override fun getValue(thisRef: Any?, property: KProperty<*>): T = reader(get(key ?: property.name.asName())?.value) @@ -107,65 +128,65 @@ public fun <T> MutableMetaProvider.value( /* Read-write delegates for [MutableItemProvider] */ -public fun MutableMetaProvider.string(key: Name? = null): ReadWriteProperty<Any?, String?> = +public fun MutableMetaProvider.string(key: Name? = null): MutableMetaDelegate<String?> = value(key) { it?.string } -public fun MutableMetaProvider.boolean(key: Name? = null): ReadWriteProperty<Any?, Boolean?> = +public fun MutableMetaProvider.boolean(key: Name? = null): MutableMetaDelegate<Boolean?> = value(key) { it?.boolean } -public fun MutableMetaProvider.number(key: Name? = null): ReadWriteProperty<Any?, Number?> = +public fun MutableMetaProvider.number(key: Name? = null): MutableMetaDelegate<Number?> = value(key) { it?.number } -public fun MutableMetaProvider.string(default: String, key: Name? = null): ReadWriteProperty<Any?, String> = +public fun MutableMetaProvider.string(default: String, key: Name? = null): MutableMetaDelegate<String> = value(key) { it?.string ?: default } -public fun MutableMetaProvider.boolean(default: Boolean, key: Name? = null): ReadWriteProperty<Any?, Boolean> = +public fun MutableMetaProvider.boolean(default: Boolean, key: Name? = null): MutableMetaDelegate<Boolean> = value(key) { it?.boolean ?: default } -public fun MutableMetaProvider.number(default: Number, key: Name? = null): ReadWriteProperty<Any?, Number> = +public fun MutableMetaProvider.number(default: Number, key: Name? = null): MutableMetaDelegate<Number> = value(key) { it?.number ?: default } -public fun MutableMetaProvider.string(key: Name? = null, default: () -> String): ReadWriteProperty<Any?, String> = +public fun MutableMetaProvider.string(key: Name? = null, default: () -> String): MutableMetaDelegate<String> = value(key) { it?.string ?: default() } -public fun MutableMetaProvider.boolean(key: Name? = null, default: () -> Boolean): ReadWriteProperty<Any?, Boolean> = +public fun MutableMetaProvider.boolean(key: Name? = null, default: () -> Boolean): MutableMetaDelegate<Boolean> = value(key) { it?.boolean ?: default() } -public fun MutableMetaProvider.number(key: Name? = null, default: () -> Number): ReadWriteProperty<Any?, Number> = +public fun MutableMetaProvider.number(key: Name? = null, default: () -> Number): MutableMetaDelegate<Number> = value(key) { it?.number ?: default() } public inline fun <reified E : Enum<E>> MutableMetaProvider.enum( default: E, key: Name? = null, -): ReadWriteProperty<Any?, E> = value(key) { value -> value?.string?.let { enumValueOf<E>(it) } ?: default } +): MutableMetaDelegate<E> = value(key) { value -> value?.string?.let { enumValueOf<E>(it) } ?: default } /* Number delegates */ -public fun MutableMetaProvider.int(key: Name? = null): ReadWriteProperty<Any?, Int?> = +public fun MutableMetaProvider.int(key: Name? = null): MutableMetaDelegate<Int?> = value(key) { it?.int } -public fun MutableMetaProvider.double(key: Name? = null): ReadWriteProperty<Any?, Double?> = +public fun MutableMetaProvider.double(key: Name? = null): MutableMetaDelegate<Double?> = value(key) { it?.double } -public fun MutableMetaProvider.long(key: Name? = null): ReadWriteProperty<Any?, Long?> = +public fun MutableMetaProvider.long(key: Name? = null): MutableMetaDelegate<Long?> = value(key) { it?.long } -public fun MutableMetaProvider.float(key: Name? = null): ReadWriteProperty<Any?, Float?> = +public fun MutableMetaProvider.float(key: Name? = null): MutableMetaDelegate<Float?> = value(key) { it?.float } /* Safe number delegates*/ -public fun MutableMetaProvider.int(default: Int, key: Name? = null): ReadWriteProperty<Any?, Int> = +public fun MutableMetaProvider.int(default: Int, key: Name? = null): MutableMetaDelegate<Int> = value(key) { it?.int ?: default } -public fun MutableMetaProvider.double(default: Double, key: Name? = null): ReadWriteProperty<Any?, Double> = +public fun MutableMetaProvider.double(default: Double, key: Name? = null): MutableMetaDelegate<Double> = value(key) { it?.double ?: default } -public fun MutableMetaProvider.long(default: Long, key: Name? = null): ReadWriteProperty<Any?, Long> = +public fun MutableMetaProvider.long(default: Long, key: Name? = null): MutableMetaDelegate<Long> = value(key) { it?.long ?: default } -public fun MutableMetaProvider.float(default: Float, key: Name? = null): ReadWriteProperty<Any?, Float> = +public fun MutableMetaProvider.float(default: Float, key: Name? = null): MutableMetaDelegate<Float> = value(key) { it?.float ?: default } @@ -174,7 +195,7 @@ public fun MutableMetaProvider.float(default: Float, key: Name? = null): ReadWri public fun MutableMetaProvider.stringList( vararg default: String, key: Name? = null, -): ReadWriteProperty<Any?, List<String>> = value( +): MutableMetaDelegate<List<String>> = value( key, writer = { list -> list.map { str -> str.asValue() }.asValue() }, reader = { it?.stringList ?: listOf(*default) }, @@ -182,7 +203,7 @@ public fun MutableMetaProvider.stringList( public fun MutableMetaProvider.stringList( key: Name? = null, -): ReadWriteProperty<Any?, List<String>?> = value( +): MutableMetaDelegate<List<String>?> = value( key, writer = { it -> it?.map { str -> str.asValue() }?.asValue() }, reader = { it?.stringList }, @@ -191,7 +212,7 @@ public fun MutableMetaProvider.stringList( public fun MutableMetaProvider.numberList( vararg default: Number, key: Name? = null, -): ReadWriteProperty<Any?, List<Number>> = value( +): MutableMetaDelegate<List<Number>> = value( key, writer = { it.map { num -> num.asValue() }.asValue() }, reader = { it?.list?.map { value -> value.numberOrNull ?: Double.NaN } ?: listOf(*default) }, @@ -202,7 +223,7 @@ public fun <T> MutableMetaProvider.listValue( key: Name? = null, writer: (T) -> Value = { Value.of(it) }, reader: (Value) -> T, -): ReadWriteProperty<Any?, List<T>?> = value( +): MutableMetaDelegate<List<T>?> = value( key, writer = { it?.map(writer)?.asValue() }, reader = { it?.list?.map(reader) } diff --git a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/CachingAction.kt b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/CachingAction.kt new file mode 100644 index 00000000..5f88ab74 --- /dev/null +++ b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/CachingAction.kt @@ -0,0 +1,19 @@ +package space.kscience.dataforge.workspace + +import space.kscience.dataforge.actions.AbstractAction +import space.kscience.dataforge.data.* +import space.kscience.dataforge.meta.Meta +import kotlin.reflect.KType + +internal class CachingAction<T>(type: KType, private val caching: (NamedData<T>) -> NamedData<T>) : + AbstractAction<T, T>(type) { + override fun DataSink<T>.generate(source: DataTree<T>, meta: Meta) { + source.forEach { + put(caching(it)) + } + } + + override suspend fun DataSink<T>.update(source: DataTree<T>, meta: Meta, updatedData: DataUpdate<T>) { + put(updatedData.name, updatedData.data?.named(updatedData.name)?.let(caching)) + } +} \ No newline at end of file diff --git a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/FileWorkspaceCache.kt b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/FileWorkspaceCache.kt index da09c095..4d2578e5 100644 --- a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/FileWorkspaceCache.kt +++ b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/FileWorkspaceCache.kt @@ -1,20 +1,22 @@ package space.kscience.dataforge.workspace -import kotlinx.coroutines.flow.filterIsInstance -import kotlinx.coroutines.flow.map import kotlinx.io.* import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.KSerializer import kotlinx.serialization.json.Json import kotlinx.serialization.protobuf.ProtoBuf import kotlinx.serialization.serializer +import space.kscience.dataforge.actions.Action +import space.kscience.dataforge.actions.invoke import space.kscience.dataforge.context.error import space.kscience.dataforge.context.logger import space.kscience.dataforge.context.request -import space.kscience.dataforge.data.* +import space.kscience.dataforge.data.Data +import space.kscience.dataforge.data.await +import space.kscience.dataforge.data.named import space.kscience.dataforge.io.* import space.kscience.dataforge.misc.DFExperimental -import space.kscience.dataforge.misc.DFInternal +import space.kscience.dataforge.misc.UnsafeKType import space.kscience.dataforge.names.withIndex import java.nio.file.Path import kotlin.io.path.deleteIfExists @@ -52,7 +54,8 @@ public class FileWorkspaceCache(public val cacheDirectory: Path) : WorkspaceCach // private fun <T : Any> TaskData<*>.checkType(taskType: KType): TaskData<T> = this as TaskData<T> - @OptIn(DFExperimental::class, DFInternal::class) + + @OptIn(DFExperimental::class, UnsafeKType::class) override suspend fun <T> cache(result: TaskResult<T>): TaskResult<T> { val io = result.workspace.context.request(IOPlugin) @@ -60,8 +63,8 @@ public class FileWorkspaceCache(public val cacheDirectory: Path) : WorkspaceCach ?: ProtobufIOFormat(result.dataType) ?: error("Can't resolve IOFormat for ${result.dataType}") - fun cacheOne(data: NamedData<T>): NamedData<T> { + val cachingAction: Action<T, T> = CachingAction(result.dataType) { data -> val path = cacheDirectory / result.taskName.withIndex(result.taskMeta.hashCode().toString(16)).toString() / data.name.toString() @@ -80,7 +83,7 @@ public class FileWorkspaceCache(public val cacheDirectory: Path) : WorkspaceCach } } - //waiting for data in current scope because Envelope is synchronous + //waiting for data in the current scope because Envelope is synchronous return@Data data.await().also { result -> val envelope = Envelope { meta = data.meta @@ -92,12 +95,10 @@ public class FileWorkspaceCache(public val cacheDirectory: Path) : WorkspaceCach } } - return datum.named(data.name) + datum.named(data.name) } - - val cachedTree = result.asSequence().map { cacheOne(it) } - .toTree(result.dataType, result.updates.filterIsInstance<NamedData<T>>().map { cacheOne(it) }) + val cachedTree = cachingAction(result) return result.workspace.wrapResult(cachedTree, result.taskName, result.taskMeta) } diff --git a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/InMemoryWorkspaceCache.kt b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/InMemoryWorkspaceCache.kt index f3b2ee15..8ba39ec1 100644 --- a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/InMemoryWorkspaceCache.kt +++ b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/InMemoryWorkspaceCache.kt @@ -1,9 +1,11 @@ package space.kscience.dataforge.workspace -import kotlinx.coroutines.flow.filterIsInstance -import kotlinx.coroutines.flow.map -import space.kscience.dataforge.data.* +import space.kscience.dataforge.actions.Action +import space.kscience.dataforge.actions.invoke +import space.kscience.dataforge.data.Data +import space.kscience.dataforge.data.named import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name import kotlin.reflect.KType import kotlin.reflect.full.isSubtypeOf @@ -20,19 +22,18 @@ public class InMemoryWorkspaceCache : WorkspaceCache { if (type.isSubtypeOf(taskType)) this as Data<T> else error("Cached data type mismatch: expected $taskType but got $type") + @OptIn(DFExperimental::class) override suspend fun <T> cache(result: TaskResult<T>): TaskResult<T> { - fun cacheOne(data: NamedData<T>): NamedData<T> { + val cachingAction: Action<T, T> = CachingAction(result.dataType) { data -> val cachedData = cache.getOrPut(TaskResultId(result.taskName, result.taskMeta)){ HashMap() }.getOrPut(data.name){ data.data } - return cachedData.checkType<T>(result.dataType).named(data.name) + cachedData.checkType<T>(result.dataType).named(data.name) } - - val cachedTree = result.asSequence().map { cacheOne(it) } - .toTree(result.dataType, result.updates.filterIsInstance<NamedData<T>>().map { cacheOne(it) }) + val cachedTree = cachingAction(result) return result.workspace.wrapResult(cachedTree, result.taskName, result.taskMeta) } diff --git a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/SimpleWorkspaceTest.kt b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/SimpleWorkspaceTest.kt index 837b61bc..39837c15 100644 --- a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/SimpleWorkspaceTest.kt +++ b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/SimpleWorkspaceTest.kt @@ -148,16 +148,16 @@ internal class SimpleWorkspaceTest { } @Test - fun testWorkspace() = runTest(timeout = 10.milliseconds) { + fun testWorkspace() = runTest(timeout = 100.milliseconds) { val node = workspace.produce("sum") val res = node.asSequence().single() assertEquals(328350, res.await()) } @Test - fun testMetaPropagation() = runTest(timeout = 10.milliseconds) { + fun testMetaPropagation() = runTest(timeout = 100.milliseconds) { val node = workspace.produce("sum") { "testFlag" put true } - val res = node.data!!.await() + val res = node["sum"]!!.await() } @Test @@ -186,7 +186,7 @@ internal class SimpleWorkspaceTest { val node = workspace.produce("filterOne") { "name" put "myData[12]" } - assertEquals(12, node.data!!.await()) + assertEquals(12, node.asSequence().first().await()) } } \ No newline at end of file From f840ffb473a698ccf8af08dd28ad22078642dcc9 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Sat, 27 Apr 2024 09:47:08 +0300 Subject: [PATCH 21/26] Move data tests to jvm to avoid random failings on native --- .../dataforge/descriptors/reflectiveDescriptors.kt | 7 +------ .../kotlin/space/kscience/dataforge/data/ActionsTest.kt | 0 .../dataforge/meta/descriptors/MetaDescriptorBuilder.kt | 1 + 3 files changed, 2 insertions(+), 6 deletions(-) rename dataforge-data/src/{commonTest => jvmTest}/kotlin/space/kscience/dataforge/data/ActionsTest.kt (100%) diff --git a/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/descriptors/reflectiveDescriptors.kt b/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/descriptors/reflectiveDescriptors.kt index 9c36410a..b2953018 100644 --- a/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/descriptors/reflectiveDescriptors.kt +++ b/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/descriptors/reflectiveDescriptors.kt @@ -79,7 +79,7 @@ public fun MetaDescriptor.Companion.forClass( is DescriptorUrl -> loadDescriptorFromUrl(URL(it.url)) } } - kClass.memberProperties.forEach { property-> + kClass.memberProperties.forEach { property -> var flag = false @@ -88,11 +88,6 @@ public fun MetaDescriptor.Companion.forClass( (property.returnType.classifier as? KClass<*>)?.let { from(forClass(it)) } -// -// (property.getDelegate(Unit) as? MetaDelegate<*>)?.descriptor?.let { -// from(it) -// flag = true -// } property.annotations.forEach { when (it) { diff --git a/dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt b/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt similarity index 100% rename from dataforge-data/src/commonTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt rename to dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt index 2291e3d3..dfdbfeab 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt @@ -47,6 +47,7 @@ public class MetaDescriptorBuilder @PublishedApi internal constructor() { ): Unit { when (name.length) { 0 -> error("Can't set descriptor to root") + 1 -> { children[name.first().body] = descriptorBuilder } From 2cd18854209cdf332e14581fa7c2cf7145dcf25c Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Sat, 27 Apr 2024 10:01:36 +0300 Subject: [PATCH 22/26] Update readme and changelog --- CHANGELOG.md | 24 +++++++++++++++++------- build.gradle.kts | 3 ++- dataforge-context/README.md | 4 ++-- dataforge-data/README.md | 4 ++-- dataforge-io/README.md | 4 ++-- dataforge-io/dataforge-io-yaml/README.md | 4 ++-- dataforge-meta/README.md | 4 ++-- dataforge-scripting/README.md | 4 ++-- dataforge-workspace/README.md | 4 ++-- 9 files changed, 33 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a56e56e6..a94cb585 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,26 +3,36 @@ ## Unreleased ### Added -- Name index comparator -- Specialized ByteArrayValue ### Changed -- DataSink `branch` is replaced with `putAll` to avoid confusion with DataTree methods -- Meta delegate now uses a specific class that has a descriptor ### Deprecated ### Removed ### Fixed + +### Security + +## 0.8.2 - 2024-04-27 + +### Added + +- Name index comparator +- Specialized ByteArrayValue + +### Changed + +- DataSink `branch` is replaced with `putAll` to avoid confusion with DataTree methods +- Meta delegate now uses a specific class that has a descriptor + +### Fixed + - `listOfScheme` and `listOfConvertable` delegates provides correct items order. - Scheme meta setter works with proper sub-branch. - NameToken.parse improper work with indices. - Proper data handling for cache. - -### Security - ## 0.8.0 - 2024-02-03 ### Added diff --git a/build.gradle.kts b/build.gradle.kts index 78dc6d35..4db098be 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,11 +4,12 @@ import space.kscience.gradle.useSPCTeam plugins { id("space.kscience.gradle.project") + id("org.jetbrains.kotlinx.kover") version "0.7.6" } allprojects { group = "space.kscience" - version = "0.8.2-dev-1" + version = "0.8.2" } subprojects { diff --git a/dataforge-context/README.md b/dataforge-context/README.md index f0aff459..7970751c 100644 --- a/dataforge-context/README.md +++ b/dataforge-context/README.md @@ -6,7 +6,7 @@ Context and provider definitions ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-context:0.8.0`. +The Maven coordinates of this project are `space.kscience:dataforge-context:0.8.2`. **Gradle Kotlin DSL:** ```kotlin @@ -16,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:dataforge-context:0.8.0") + implementation("space.kscience:dataforge-context:0.8.2") } ``` diff --git a/dataforge-data/README.md b/dataforge-data/README.md index d77ed1b9..f08a43c2 100644 --- a/dataforge-data/README.md +++ b/dataforge-data/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-data:0.8.0`. +The Maven coordinates of this project are `space.kscience:dataforge-data:0.8.2`. **Gradle Kotlin DSL:** ```kotlin @@ -16,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:dataforge-data:0.8.0") + implementation("space.kscience:dataforge-data:0.8.2") } ``` diff --git a/dataforge-io/README.md b/dataforge-io/README.md index 85e49e5a..5168797b 100644 --- a/dataforge-io/README.md +++ b/dataforge-io/README.md @@ -6,7 +6,7 @@ IO module ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-io:0.8.0`. +The Maven coordinates of this project are `space.kscience:dataforge-io:0.8.2`. **Gradle Kotlin DSL:** ```kotlin @@ -16,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:dataforge-io:0.8.0") + implementation("space.kscience:dataforge-io:0.8.2") } ``` diff --git a/dataforge-io/dataforge-io-yaml/README.md b/dataforge-io/dataforge-io-yaml/README.md index 20f5b4f6..cc1ecd8c 100644 --- a/dataforge-io/dataforge-io-yaml/README.md +++ b/dataforge-io/dataforge-io-yaml/README.md @@ -6,7 +6,7 @@ YAML meta IO ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-io-yaml:0.8.0`. +The Maven coordinates of this project are `space.kscience:dataforge-io-yaml:0.8.2`. **Gradle Kotlin DSL:** ```kotlin @@ -16,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:dataforge-io-yaml:0.8.0") + implementation("space.kscience:dataforge-io-yaml:0.8.2") } ``` diff --git a/dataforge-meta/README.md b/dataforge-meta/README.md index bd11ebf1..a3209760 100644 --- a/dataforge-meta/README.md +++ b/dataforge-meta/README.md @@ -6,7 +6,7 @@ Meta definition and basic operations on meta ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-meta:0.8.0`. +The Maven coordinates of this project are `space.kscience:dataforge-meta:0.8.2`. **Gradle Kotlin DSL:** ```kotlin @@ -16,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:dataforge-meta:0.8.0") + implementation("space.kscience:dataforge-meta:0.8.2") } ``` diff --git a/dataforge-scripting/README.md b/dataforge-scripting/README.md index fbc5cb69..3167e1b4 100644 --- a/dataforge-scripting/README.md +++ b/dataforge-scripting/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-scripting:0.8.0`. +The Maven coordinates of this project are `space.kscience:dataforge-scripting:0.8.2`. **Gradle Kotlin DSL:** ```kotlin @@ -16,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:dataforge-scripting:0.8.0") + implementation("space.kscience:dataforge-scripting:0.8.2") } ``` diff --git a/dataforge-workspace/README.md b/dataforge-workspace/README.md index cea37368..f7461f30 100644 --- a/dataforge-workspace/README.md +++ b/dataforge-workspace/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-workspace:0.8.0`. +The Maven coordinates of this project are `space.kscience:dataforge-workspace:0.8.2`. **Gradle Kotlin DSL:** ```kotlin @@ -16,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:dataforge-workspace:0.8.0") + implementation("space.kscience:dataforge-workspace:0.8.2") } ``` From 3de5691c84dab040e7e570567b8b1fa38228b744 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Sat, 25 May 2024 21:19:06 +0300 Subject: [PATCH 23/26] Add custom coroutine context during new Context creation --- .../space/kscience/dataforge/context/Context.kt | 4 +++- .../kscience/dataforge/context/ContextBuilder.kt | 13 +++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Context.kt b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Context.kt index bb74d605..c614598c 100644 --- a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Context.kt +++ b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Context.kt @@ -10,6 +10,7 @@ import space.kscience.dataforge.misc.ThreadSafe import space.kscience.dataforge.names.Name import space.kscience.dataforge.provider.Provider import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext /** * The local environment for anything being done in DataForge framework. Contexts are organized into tree structure with [Global] at the top. @@ -26,6 +27,7 @@ public open class Context internal constructor( public val parent: Context?, plugins: Set<Plugin>, // set of unattached plugins meta: Meta, + coroutineContext: CoroutineContext = EmptyCoroutineContext, ) : Named, MetaRepr, Provider, CoroutineScope { /** @@ -65,7 +67,7 @@ public open class Context internal constructor( override val coroutineContext: CoroutineContext by lazy { (parent ?: Global).coroutineContext.let { parenContext -> - parenContext + SupervisorJob(parenContext[Job]) + parenContext + coroutineContext + SupervisorJob(parenContext[Job]) } } diff --git a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/ContextBuilder.kt b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/ContextBuilder.kt index c0db4314..894c5f15 100644 --- a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/ContextBuilder.kt +++ b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/ContextBuilder.kt @@ -13,6 +13,8 @@ import space.kscience.dataforge.names.plus import kotlin.collections.component1 import kotlin.collections.component2 import kotlin.collections.set +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext /** * A convenience builder for context @@ -59,8 +61,15 @@ public class ContextBuilder internal constructor( plugin(DeFactoPluginFactory(plugin)) } + private var coroutineContext: CoroutineContext = EmptyCoroutineContext + + public fun coroutineContext(coroutineContext: CoroutineContext) { + this.coroutineContext = coroutineContext + } + + public fun build(): Context { - val contextName = name ?: NameToken("@auto",hashCode().toUInt().toString(16)).asName() + val contextName = name ?: NameToken("@auto", hashCode().toUInt().toString(16)).asName() val plugins = HashMap<PluginTag, Plugin>() fun addPlugin(factory: PluginFactory<*>, meta: Meta) { @@ -86,7 +95,7 @@ public class ContextBuilder internal constructor( addPlugin(factory, meta) } - return Context(contextName, parent, plugins.values.toSet(), meta.seal()) + return Context(contextName, parent, plugins.values.toSet(), meta.seal(), coroutineContext) } } From 5a75b05acd8893371fefb60e8190e5e688c3a014 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Tue, 4 Jun 2024 17:44:44 +0300 Subject: [PATCH 24/26] 0.9-RC --- CHANGELOG.md | 5 + build.gradle.kts | 10 +- .../dataforge/properties/metaAsFlow.kt | 2 +- .../descriptors/reflectiveDescriptors.kt | 129 +++++++++--------- .../descriptors/TestAutoDescriptors.kt | 53 ++++--- .../kscience/dataforge/data/dataTransform.kt | 18 +++ .../kscience/dataforge/data/ActionsTest.kt | 1 + .../space/kscience/dataforge/meta/Laminate.kt | 2 + .../space/kscience/dataforge/meta/Meta.kt | 8 +- .../kscience/dataforge/meta/MetaConverter.kt | 2 +- .../kscience/dataforge/meta/MetaDelegate.kt | 12 +- .../meta/{MetaSpec.kt => MetaReader.kt} | 8 +- .../space/kscience/dataforge/meta/MetaRef.kt | 64 +++++++++ .../kscience/dataforge/meta/MutableMeta.kt | 3 + .../kscience/dataforge/meta/ObservableMeta.kt | 3 + .../dataforge/meta/ObservableMetaWrapper.kt | 3 + .../space/kscience/dataforge/meta/Scheme.kt | 11 +- .../kscience/dataforge/meta/SealedMeta.kt | 3 + .../meta/descriptors/MetaDescriptorBuilder.kt | 2 +- .../space/kscience/dataforge/misc/cast.kt | 3 - .../kscience/dataforge/meta/DynamicMeta.kt | 3 + .../space/kscience/dataforge/misc/castJs.kt | 5 - .../space/kscience/dataforge/misc/castJvm.kt | 4 - .../kscience/dataforge/misc/castNative.kt | 4 - .../space/kscience/dataforge/misc/castWasm.kt | 4 - .../kscience/dataforge/workspace/Task.kt | 12 +- .../dataforge/workspace/WorkspaceBuilder.kt | 4 +- gradle.properties | 7 +- 28 files changed, 234 insertions(+), 151 deletions(-) rename dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/{MetaSpec.kt => MetaReader.kt} (59%) create mode 100644 dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaRef.kt delete mode 100644 dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/cast.kt delete mode 100644 dataforge-meta/src/jsMain/kotlin/space/kscience/dataforge/misc/castJs.kt delete mode 100644 dataforge-meta/src/jvmMain/kotlin/space/kscience/dataforge/misc/castJvm.kt delete mode 100644 dataforge-meta/src/nativeMain/kotlin/space/kscience/dataforge/misc/castNative.kt delete mode 100644 dataforge-meta/src/wasmJsMain/kotlin/space/kscience/dataforge/misc/castWasm.kt diff --git a/CHANGELOG.md b/CHANGELOG.md index a94cb585..d75dd1a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,12 +3,17 @@ ## Unreleased ### Added +- Custom CoroutineContext during `Context` creation. ### Changed +- Kotlin 2.0 +- `MetaSpec` renamed to `MetaReader`. MetaSpec is now reserved for builder-based generation of meta descriptors. +- Add self-type for Meta. Remove unsafe cast method for meta instances. ### Deprecated ### Removed +- Automatic descriptors for schema. It is not possible to implement them without heavy reflection. ### Fixed diff --git a/build.gradle.kts b/build.gradle.kts index 4db098be..815a7077 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,21 +3,21 @@ import space.kscience.gradle.useApache2Licence import space.kscience.gradle.useSPCTeam plugins { - id("space.kscience.gradle.project") - id("org.jetbrains.kotlinx.kover") version "0.7.6" + alias(spclibs.plugins.kscience.project) + alias(spclibs.plugins.kotlinx.kover) } allprojects { group = "space.kscience" - version = "0.8.2" + version = "0.9.0-dev-1" } subprojects { apply(plugin = "maven-publish") tasks.withType<KotlinCompile> { - kotlinOptions { - freeCompilerArgs = freeCompilerArgs + "-Xcontext-receivers" + compilerOptions { + freeCompilerArgs.add("-Xcontext-receivers") } } } diff --git a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/metaAsFlow.kt b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/metaAsFlow.kt index 90fafc5e..da539fcb 100644 --- a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/metaAsFlow.kt +++ b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/metaAsFlow.kt @@ -10,7 +10,7 @@ import space.kscience.dataforge.meta.* import space.kscience.dataforge.misc.DFExperimental @DFExperimental -public fun <T> ObservableMeta.asFlow(converter: MetaSpec<T>): Flow<T> = callbackFlow { +public fun <T> ObservableMeta.asFlow(converter: MetaReader<T>): Flow<T> = callbackFlow { onChange(this){ trySend(converter.read(this)) } diff --git a/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/descriptors/reflectiveDescriptors.kt b/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/descriptors/reflectiveDescriptors.kt index b2953018..590324d7 100644 --- a/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/descriptors/reflectiveDescriptors.kt +++ b/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/descriptors/reflectiveDescriptors.kt @@ -4,18 +4,12 @@ import kotlinx.serialization.ExperimentalSerializationApi import kotlinx.serialization.json.Json import kotlinx.serialization.json.decodeFromStream import org.slf4j.LoggerFactory -import space.kscience.dataforge.meta.Scheme -import space.kscience.dataforge.meta.SchemeSpec -import space.kscience.dataforge.meta.ValueType import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.MetaDescriptorBuilder -import space.kscience.dataforge.meta.descriptors.node import space.kscience.dataforge.misc.DFExperimental import java.net.URL -import kotlin.reflect.KClass -import kotlin.reflect.full.isSubclassOf -import kotlin.reflect.full.memberProperties - +import kotlin.reflect.KAnnotatedElement +import kotlin.reflect.KProperty /** * Description text for meta property, node or whole object @@ -59,18 +53,8 @@ private fun MetaDescriptorBuilder.loadDescriptorFromResource(resource: Descripto } @DFExperimental -public fun MetaDescriptor.Companion.forClass( - kClass: KClass<out Any>, - mod: MetaDescriptorBuilder.() -> Unit = {}, -): MetaDescriptor = MetaDescriptor { - when { - kClass.isSubclassOf(Number::class) -> valueType(ValueType.NUMBER) - kClass == String::class -> ValueType.STRING - kClass == Boolean::class -> ValueType.BOOLEAN - kClass == DoubleArray::class -> ValueType.LIST - } - - kClass.annotations.forEach { +public fun MetaDescriptorBuilder.forAnnotatedElement(element: KAnnotatedElement) { + element.annotations.forEach { when (it) { is Description -> description = it.value @@ -79,47 +63,70 @@ public fun MetaDescriptor.Companion.forClass( is DescriptorUrl -> loadDescriptorFromUrl(URL(it.url)) } } - kClass.memberProperties.forEach { property -> - - var flag = false - - val descriptor = MetaDescriptor { - //use base type descriptor as a base - (property.returnType.classifier as? KClass<*>)?.let { - from(forClass(it)) - } - - property.annotations.forEach { - when (it) { - is Description -> { - description = it.value - flag = true - } - - is Multiple -> { - multiple = true - flag = true - } - - is DescriptorResource -> { - loadDescriptorFromResource(it) - flag = true - } - - is DescriptorUrl -> { - loadDescriptorFromUrl(URL(it.url)) - flag = true - } - } - } - } - if (flag) { - node(property.name, descriptor) - } - } - mod() } @DFExperimental -public inline fun <reified T : Scheme> SchemeSpec<T>.autoDescriptor(noinline mod: MetaDescriptorBuilder.() -> Unit = {}): MetaDescriptor = - MetaDescriptor.forClass(T::class, mod) \ No newline at end of file +public fun MetaDescriptorBuilder.forProperty(property: KProperty<*>) { + property.annotations.forEach { + when (it) { + is Description -> description = it.value + + is DescriptorResource -> loadDescriptorFromResource(it) + + is DescriptorUrl -> loadDescriptorFromUrl(URL(it.url)) + } + } +} +// +//@DFExperimental +//public fun <T : Scheme> MetaDescriptor.Companion.forScheme( +// spec: SchemeSpec<T>, +// mod: MetaDescriptorBuilder.() -> Unit = {}, +//): MetaDescriptor = MetaDescriptor { +// val scheme = spec.empty() +// val kClass: KClass<T> = scheme::class as KClass<T> +// when { +// kClass.isSubclassOf(Number::class) -> valueType(ValueType.NUMBER) +// kClass == String::class -> ValueType.STRING +// kClass == Boolean::class -> ValueType.BOOLEAN +// kClass == DoubleArray::class -> ValueType.LIST +// kClass == ByteArray::class -> ValueType.LIST +// } +// +// forAnnotatedElement(kClass) +// kClass.memberProperties.forEach { property -> +// node(property.name) { +// +// (property.getDelegate(scheme) as? MetaDelegate<*>)?.descriptor?.let { +// from(it) +// } +// +// property.annotations.forEach { +// when (it) { +// is Description -> { +// description = it.value +// } +// +// is Multiple -> { +// multiple = true +// } +// +// is DescriptorResource -> { +// loadDescriptorFromResource(it) +// } +// +// is DescriptorUrl -> { +// loadDescriptorFromUrl(URL(it.url)) +// } +// } +// } +// } +// +// } +// mod() +//} +// +//@DFExperimental +//public inline fun <reified T : Scheme> SchemeSpec<T>.autoDescriptor( +// noinline mod: MetaDescriptorBuilder.() -> Unit = {}, +//): MetaDescriptor = MetaDescriptor.forScheme(this, mod) \ No newline at end of file diff --git a/dataforge-context/src/jvmTest/kotlin/space/kscience/dataforge/descriptors/TestAutoDescriptors.kt b/dataforge-context/src/jvmTest/kotlin/space/kscience/dataforge/descriptors/TestAutoDescriptors.kt index df849ce5..3b1fce3d 100644 --- a/dataforge-context/src/jvmTest/kotlin/space/kscience/dataforge/descriptors/TestAutoDescriptors.kt +++ b/dataforge-context/src/jvmTest/kotlin/space/kscience/dataforge/descriptors/TestAutoDescriptors.kt @@ -2,35 +2,28 @@ package space.kscience.dataforge.descriptors -import kotlinx.serialization.encodeToString -import kotlinx.serialization.json.Json -import org.junit.jupiter.api.Test -import space.kscience.dataforge.meta.Scheme -import space.kscience.dataforge.meta.SchemeSpec -import space.kscience.dataforge.meta.descriptors.MetaDescriptor -import space.kscience.dataforge.meta.int -import space.kscience.dataforge.meta.string import space.kscience.dataforge.misc.DFExperimental -private class TestScheme : Scheme() { - - @Description("A") - val a by string() - - @Description("B") - val b by int() - - val c by int() - - companion object : SchemeSpec<TestScheme>(::TestScheme) { - override val descriptor: MetaDescriptor = autoDescriptor() - } -} - -class TestAutoDescriptors { - @Test - fun autoDescriptor() { - val autoDescriptor = MetaDescriptor.forClass(TestScheme::class) - println(Json { prettyPrint = true }.encodeToString(autoDescriptor)) - } -} \ No newline at end of file +// +//class TestScheme : Scheme() { +// +// @Description("A") +// val a by string() +// +// @Description("B") +// val b by int() +// +// val c by int() +// +// companion object : SchemeSpec<TestScheme>(::TestScheme) { +// override val descriptor: MetaDescriptor = autoDescriptor() +// } +//} +// +//class TestAutoDescriptors { +// @Test +// fun autoDescriptor() { +// val autoDescriptor = MetaDescriptor.forScheme(TestScheme) +// println(Json { prettyPrint = true }.encodeToString(autoDescriptor)) +// } +//} \ No newline at end of file diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataTransform.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataTransform.kt index ab54eb3e..c0d92e9e 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataTransform.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataTransform.kt @@ -18,6 +18,24 @@ public data class NamedValueWithMeta<T>(val name: Name, val value: T, val meta: public suspend fun <T> NamedData<T>.awaitWithMeta(): NamedValueWithMeta<T> = NamedValueWithMeta(name, await(), meta) +/** + * Lazily transform this data to another data. By convention [block] should not use external data (be pure). + * @param type explicit type of the resulting [Data] + * @param coroutineContext additional [CoroutineContext] elements used for data computation. + * @param meta for the resulting data. By default equals input data. + * @param block the transformation itself + */ +@UnsafeKType +public fun <T, R> Data<T>.transform( + type: KType, + meta: Meta = this.meta, + coroutineContext: CoroutineContext = EmptyCoroutineContext, + block: suspend (T) -> R, +): Data<R> = Data(type, meta, coroutineContext, listOf(this)) { + block(await()) +} + + /** * Lazily transform this data to another data. By convention [block] should not use external data (be pure). diff --git a/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt b/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt index 477ca592..13660eee 100644 --- a/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt +++ b/dataforge-data/src/jvmTest/kotlin/space/kscience/dataforge/data/ActionsTest.kt @@ -43,6 +43,7 @@ internal class ActionsTest { repeat(10) { source.updateValue(it.toString(), it) } + result.updates.take(10).onEach { println(it.name) }.collect() assertEquals(2, result["1"]?.await()) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Laminate.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Laminate.kt index 87284107..0ae84bb6 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Laminate.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Laminate.kt @@ -9,6 +9,8 @@ import space.kscience.dataforge.names.NameToken */ public class Laminate internal constructor(public val layers: List<Meta>) : TypedMeta<Laminate> { + override val self: Laminate get() = this + override val value: Value? = layers.firstNotNullOfOrNull { it.value } override val items: Map<NameToken, Laminate> by lazy { diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Meta.kt index 5cf53c75..fd953085 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Meta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Meta.kt @@ -3,7 +3,6 @@ package space.kscience.dataforge.meta import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json import space.kscience.dataforge.misc.DfType -import space.kscience.dataforge.misc.unsafeCast import space.kscience.dataforge.names.* import kotlin.jvm.JvmName @@ -151,6 +150,8 @@ public interface TypedMeta<out M : TypedMeta<M>> : Meta { override val items: Map<NameToken, M> + public val self: M + override fun get(name: Name): M? { tailrec fun M.find(name: Name): M? = if (name.isEmpty()) { this @@ -164,11 +165,6 @@ public interface TypedMeta<out M : TypedMeta<M>> : Meta { override fun toMeta(): Meta = this } -/** - * Access self as a recursive type instance - */ -public inline val <M : TypedMeta<M>> TypedMeta<M>.self: M get() = unsafeCast() - //public typealias Meta = TypedMeta<*> public operator fun <M : TypedMeta<M>> TypedMeta<M>?.get(token: NameToken): M? = this?.items?.get(token) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaConverter.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaConverter.kt index 124f49f5..9baf0087 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaConverter.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaConverter.kt @@ -11,7 +11,7 @@ import space.kscience.dataforge.misc.DFExperimental /** * A converter of generic object to and from [Meta] */ -public interface MetaConverter<T>: MetaSpec<T> { +public interface MetaConverter<T>: MetaReader<T> { /** * A descriptor for resulting meta diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt index 8c5a738f..1b506b44 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt @@ -25,16 +25,16 @@ public fun MetaProvider.node( } /** - * Use [metaSpec] to read the Meta node + * Use [metaReader] to read the Meta node */ public fun <T> MetaProvider.spec( - metaSpec: MetaSpec<T>, + metaReader: MetaReader<T>, key: Name? = null, ): MetaDelegate<T?> = object : MetaDelegate<T?> { - override val descriptor: MetaDescriptor? get() = metaSpec.descriptor + override val descriptor: MetaDescriptor? get() = metaReader.descriptor override fun getValue(thisRef: Any?, property: KProperty<*>): T? { - return get(key ?: property.name.asName())?.let { metaSpec.read(it) } + return get(key ?: property.name.asName())?.let { metaReader.read(it) } } } @@ -50,14 +50,14 @@ public inline fun <reified T> MetaProvider.serializable( @Deprecated("Use convertable", ReplaceWith("convertable(converter, key)")) public fun <T> MetaProvider.node( key: Name? = null, - converter: MetaSpec<T>, + converter: MetaReader<T>, ): ReadOnlyProperty<Any?, T?> = spec(converter, key) /** * Use [converter] to convert a list of same name siblings meta to object */ public fun <T> Meta.listOfSpec( - converter: MetaSpec<T>, + converter: MetaReader<T>, key: Name? = null, ): MetaDelegate<List<T>> = object : MetaDelegate<List<T>> { override fun getValue(thisRef: Any?, property: KProperty<*>): List<T> { diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaSpec.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaReader.kt similarity index 59% rename from dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaSpec.kt rename to dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaReader.kt index 9918d504..a8514d63 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaSpec.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaReader.kt @@ -2,7 +2,7 @@ package space.kscience.dataforge.meta import space.kscience.dataforge.meta.descriptors.Described -public interface MetaSpec<out T> : Described { +public interface MetaReader<out T> : Described { /** * Read the source meta into an object and return null if Meta could not be interpreted as a target type @@ -10,12 +10,12 @@ public interface MetaSpec<out T> : Described { public fun readOrNull(source: Meta): T? /** - * Read generic read-only meta with this [MetaSpec] producing instance of the desired type. + * Read generic read-only meta with this [MetaReader] producing instance of the desired type. * Throws an error if conversion could not be done. */ public fun read(source: Meta): T = readOrNull(source) ?: error("Meta $source could not be interpreted by $this") } -public fun <T : Any> MetaSpec<T>.readNullable(item: Meta?): T? = item?.let { read(it) } -public fun <T> MetaSpec<T>.readValue(value: Value): T? = read(Meta(value)) +public fun <T : Any> MetaReader<T>.readNullable(item: Meta?): T? = item?.let { read(it) } +public fun <T> MetaReader<T>.readValue(value: Value): T? = read(Meta(value)) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaRef.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaRef.kt new file mode 100644 index 00000000..413fe404 --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaRef.kt @@ -0,0 +1,64 @@ +package space.kscience.dataforge.meta + +import space.kscience.dataforge.meta.descriptors.Described +import space.kscience.dataforge.meta.descriptors.MetaDescriptor +import space.kscience.dataforge.meta.descriptors.MetaDescriptorBuilder +import space.kscience.dataforge.misc.DFExperimental +import space.kscience.dataforge.names.Name +import space.kscience.dataforge.names.asName +import kotlin.properties.PropertyDelegateProvider +import kotlin.properties.ReadOnlyProperty + + +/** + * A reference to a read-only value of type [T] inside [MetaProvider] + */ +@DFExperimental +public data class MetaRef<T>( + public val name: Name, + public val converter: MetaConverter<T>, + override val descriptor: MetaDescriptor? = converter.descriptor, +) : Described + +@DFExperimental +public operator fun <T> MetaProvider.get(ref: MetaRef<T>): T? = get(ref.name)?.let { ref.converter.readOrNull(it) } + +@DFExperimental +public operator fun <T> MutableMetaProvider.set(ref: MetaRef<T>, value: T) { + set(ref.name, ref.converter.convert(value)) +} + +@DFExperimental +public class MetaSpec( + private val configuration: MetaDescriptorBuilder.() -> Unit = {}, +) : Described { + private val refs: MutableList<MetaRef<*>> = mutableListOf() + + private fun registerRef(ref: MetaRef<*>) { + refs.add(ref) + } + + public fun <T> item( + converter: MetaConverter<T>, + descriptor: MetaDescriptor? = converter.descriptor, + key: Name? = null, + ): PropertyDelegateProvider<MetaSpec, ReadOnlyProperty<MetaSpec, MetaRef<T>>> = + PropertyDelegateProvider { _, property -> + val ref = MetaRef(key ?: property.name.asName(), converter, descriptor) + registerRef(ref) + ReadOnlyProperty { _, _ -> + ref + } + } + + override val descriptor: MetaDescriptor by lazy { + MetaDescriptor { + refs.forEach { ref -> + ref.descriptor?.let { + node(ref.name, ref.descriptor) + } + } + configuration() + } + } +} \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt index 69e221f5..7be16cc9 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt @@ -253,6 +253,9 @@ private class MutableMetaImpl( value: Value?, children: Map<NameToken, Meta> = emptyMap(), ) : AbstractObservableMeta(), ObservableMutableMeta { + + override val self get() = this + override var value = value @ThreadSafe set(value) { val oldValue = field diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMeta.kt index b481962e..7cd28746 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMeta.kt @@ -39,6 +39,9 @@ public interface ObservableMeta : Meta { * A [Meta] which is both observable and mutable */ public interface ObservableMutableMeta : ObservableMeta, MutableMeta, MutableTypedMeta<ObservableMutableMeta> { + + override val self: ObservableMutableMeta get() = this + override fun getOrCreate(name: Name): ObservableMutableMeta override fun get(name: Name): ObservableMutableMeta? { diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMetaWrapper.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMetaWrapper.kt index abd2deb6..7c62f692 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMetaWrapper.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMetaWrapper.kt @@ -14,6 +14,9 @@ private class ObservableMetaWrapper( val nodeName: Name, val listeners: MutableSet<MetaListener>, ) : ObservableMutableMeta { + + override val self get() = this + override val items: Map<NameToken, ObservableMutableMeta> get() = root[nodeName]?.items?.keys?.associateWith { ObservableMetaWrapper(root, nodeName + it, listeners) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt index 85b5087a..fe121c42 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt @@ -12,7 +12,7 @@ import kotlin.reflect.KProperty import kotlin.reflect.KProperty1 /** - * A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [MetaSpec]. + * A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [MetaReader]. * * @param prototype default values provided by this scheme */ @@ -80,6 +80,9 @@ public open class Scheme( override fun toString(): String = meta.toString() private inner class SchemeMeta(val pathName: Name) : ObservableMutableMeta { + + override val self get() = this + override var value: Value? get() = target[pathName]?.value ?: prototype?.get(pathName)?.value @@ -216,7 +219,7 @@ public fun <T : Scheme> Configurable.updateWith( /** - * A delegate that uses a [MetaSpec] to wrap a child of this provider + * A delegate that uses a [MetaReader] to wrap a child of this provider */ public fun <T : Scheme> MutableMeta.scheme( spec: SchemeSpec<T>, @@ -239,7 +242,7 @@ public fun <T : Scheme> Scheme.scheme( ): ReadWriteProperty<Any?, T> = meta.scheme(spec, key) /** - * A delegate that uses a [MetaSpec] to wrap a child of this provider. + * A delegate that uses a [MetaReader] to wrap a child of this provider. * Returns null if meta with given name does not exist. */ public fun <T : Scheme> MutableMeta.schemeOrNull( @@ -264,7 +267,7 @@ public fun <T : Scheme> Scheme.schemeOrNull( ): ReadWriteProperty<Any?, T?> = meta.schemeOrNull(spec, key) /** - * A delegate that uses a [MetaSpec] to wrap a list of child providers. + * A delegate that uses a [MetaReader] to wrap a list of child providers. * If children are mutable, the changes in list elements are reflected on them. * The list is a snapshot of children state, so change in structure is not reflected on its composition. */ diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/SealedMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/SealedMeta.kt index b3fdf062..b218fad6 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/SealedMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/SealedMeta.kt @@ -13,6 +13,9 @@ public class SealedMeta( override val value: Value?, override val items: Map<NameToken, SealedMeta>, ) : TypedMeta<SealedMeta> { + + override val self: SealedMeta get() = this + override fun toString(): String = Meta.toString(this) override fun equals(other: Any?): Boolean = Meta.equals(this, other as? Meta) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt index dfdbfeab..2590273e 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt @@ -58,7 +58,7 @@ public class MetaDescriptorBuilder @PublishedApi internal constructor() { } } - internal fun node( + public fun node( name: Name, descriptorBuilder: MetaDescriptor, ): Unit { diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/cast.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/cast.kt deleted file mode 100644 index e714d596..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/cast.kt +++ /dev/null @@ -1,3 +0,0 @@ -package space.kscience.dataforge.misc - -public expect inline fun <T> Any?.unsafeCast(): T \ No newline at end of file diff --git a/dataforge-meta/src/jsMain/kotlin/space/kscience/dataforge/meta/DynamicMeta.kt b/dataforge-meta/src/jsMain/kotlin/space/kscience/dataforge/meta/DynamicMeta.kt index b38d5891..57d324c7 100644 --- a/dataforge-meta/src/jsMain/kotlin/space/kscience/dataforge/meta/DynamicMeta.kt +++ b/dataforge-meta/src/jsMain/kotlin/space/kscience/dataforge/meta/DynamicMeta.kt @@ -31,6 +31,9 @@ public fun Meta.toDynamic(): dynamic { } public class DynamicMeta(internal val obj: dynamic) : TypedMeta<DynamicMeta> { + + override val self: DynamicMeta get() = this + private fun keys(): Array<String> = js("Object").keys(obj) as Array<String> private fun isArray(obj: dynamic): Boolean = diff --git a/dataforge-meta/src/jsMain/kotlin/space/kscience/dataforge/misc/castJs.kt b/dataforge-meta/src/jsMain/kotlin/space/kscience/dataforge/misc/castJs.kt deleted file mode 100644 index b057bcbe..00000000 --- a/dataforge-meta/src/jsMain/kotlin/space/kscience/dataforge/misc/castJs.kt +++ /dev/null @@ -1,5 +0,0 @@ -package space.kscience.dataforge.misc -import kotlin.js.unsafeCast as unsafeCastJs - -@Suppress("NOTHING_TO_INLINE") -public actual inline fun <T> Any?.unsafeCast(): T = unsafeCastJs<T>() \ No newline at end of file diff --git a/dataforge-meta/src/jvmMain/kotlin/space/kscience/dataforge/misc/castJvm.kt b/dataforge-meta/src/jvmMain/kotlin/space/kscience/dataforge/misc/castJvm.kt deleted file mode 100644 index 27d399fe..00000000 --- a/dataforge-meta/src/jvmMain/kotlin/space/kscience/dataforge/misc/castJvm.kt +++ /dev/null @@ -1,4 +0,0 @@ -package space.kscience.dataforge.misc - -@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") -public actual inline fun <T> Any?.unsafeCast(): T = this as T \ No newline at end of file diff --git a/dataforge-meta/src/nativeMain/kotlin/space/kscience/dataforge/misc/castNative.kt b/dataforge-meta/src/nativeMain/kotlin/space/kscience/dataforge/misc/castNative.kt deleted file mode 100644 index 4d9aa758..00000000 --- a/dataforge-meta/src/nativeMain/kotlin/space/kscience/dataforge/misc/castNative.kt +++ /dev/null @@ -1,4 +0,0 @@ -package space.kscience.dataforge.misc - -@Suppress("UNCHECKED_CAST") -public actual inline fun <T> Any?.unsafeCast(): T = this as T \ No newline at end of file diff --git a/dataforge-meta/src/wasmJsMain/kotlin/space/kscience/dataforge/misc/castWasm.kt b/dataforge-meta/src/wasmJsMain/kotlin/space/kscience/dataforge/misc/castWasm.kt deleted file mode 100644 index 27d399fe..00000000 --- a/dataforge-meta/src/wasmJsMain/kotlin/space/kscience/dataforge/misc/castWasm.kt +++ /dev/null @@ -1,4 +0,0 @@ -package space.kscience.dataforge.misc - -@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") -public actual inline fun <T> Any?.unsafeCast(): T = this as T \ No newline at end of file diff --git a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Task.kt b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Task.kt index 372b119f..a1a754a4 100644 --- a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Task.kt +++ b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/Task.kt @@ -5,8 +5,8 @@ import space.kscience.dataforge.data.DataSink import space.kscience.dataforge.data.GoalExecutionRestriction import space.kscience.dataforge.data.MutableDataTree import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.meta.MetaReader import space.kscience.dataforge.meta.MetaRepr -import space.kscience.dataforge.meta.MetaSpec import space.kscience.dataforge.meta.descriptors.Described import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.misc.DfType @@ -44,10 +44,10 @@ public interface Task<T> : Described { } /** - * A [Task] with [MetaSpec] for wrapping and unwrapping task configuration + * A [Task] with [MetaReader] for wrapping and unwrapping task configuration */ public interface TaskWithSpec<T, C : Any> : Task<T> { - public val spec: MetaSpec<C> + public val spec: MetaReader<C> override val descriptor: MetaDescriptor? get() = spec.descriptor public suspend fun execute(workspace: Workspace, taskName: Name, configuration: C): TaskResult<T> @@ -122,10 +122,10 @@ public inline fun <reified T : Any> Task( @Suppress("FunctionName") public fun <T : Any, C : MetaRepr> Task( resultType: KType, - specification: MetaSpec<C>, + specification: MetaReader<C>, builder: suspend TaskResultBuilder<T>.(C) -> Unit, ): TaskWithSpec<T, C> = object : TaskWithSpec<T, C> { - override val spec: MetaSpec<C> = specification + override val spec: MetaReader<C> = specification override suspend fun execute( workspace: Workspace, @@ -143,6 +143,6 @@ public fun <T : Any, C : MetaRepr> Task( } public inline fun <reified T : Any, C : MetaRepr> Task( - specification: MetaSpec<C>, + specification: MetaReader<C>, noinline builder: suspend TaskResultBuilder<T>.(C) -> Unit, ): Task<T> = Task(typeOf<T>(), specification, builder) \ No newline at end of file diff --git a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/WorkspaceBuilder.kt b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/WorkspaceBuilder.kt index cf263a46..013c0171 100644 --- a/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/WorkspaceBuilder.kt +++ b/dataforge-workspace/src/commonMain/kotlin/space/kscience/dataforge/workspace/WorkspaceBuilder.kt @@ -71,10 +71,10 @@ public inline fun <reified T : Any> TaskContainer.task( } /** - * Create a task based on [MetaSpec] + * Create a task based on [MetaReader] */ public inline fun <reified T : Any, C : MetaRepr> TaskContainer.task( - specification: MetaSpec<C>, + specification: MetaReader<C>, noinline builder: suspend TaskResultBuilder<T>.(C) -> Unit, ): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, TaskReference<T>>> = PropertyDelegateProvider { _, property -> val taskName = Name.parse(property.name) diff --git a/gradle.properties b/gradle.properties index 3734d13e..ffc318d9 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,10 +1,9 @@ +kotlin.code.style=official + org.gradle.parallel=true org.gradle.jvmargs=-Xmx4096m -kotlin.code.style=official kotlin.mpp.stability.nowarn=true -kotlin.incremental.js.ir=true kotlin.native.ignoreDisabledTargets=true -toolsVersion=0.15.2-kotlin-1.9.21 -#kotlin.experimental.tryK2=true \ No newline at end of file +toolsVersion=0.15.4-kotlin-2.0.0 \ No newline at end of file From 04238295e277430e5b22771e470e87f343bd2fd1 Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Tue, 4 Jun 2024 17:55:25 +0300 Subject: [PATCH 25/26] Remove sequence with list builder in Name::parse to fix problem in Wasm --- .../kotlin/space/kscience/dataforge/names/Name.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/Name.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/Name.kt index b46a3507..7867330c 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/Name.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/Name.kt @@ -58,7 +58,7 @@ public class Name(public val tokens: List<NameToken>) { */ public fun parse(string: String): Name { if (string.isBlank()) return EMPTY - val tokens = sequence { + val tokens = buildList<NameToken> { var bodyBuilder = StringBuilder() var queryBuilder = StringBuilder() var bracketCount = 0 @@ -91,7 +91,7 @@ public class Name(public val tokens: List<NameToken>) { else -> when (it) { '.' -> { val query = if (queryBuilder.isEmpty()) null else queryBuilder.toString() - yield(NameToken(bodyBuilder.toString(), query)) + add(NameToken(bodyBuilder.toString(), query)) bodyBuilder = StringBuilder() queryBuilder = StringBuilder() } @@ -106,9 +106,9 @@ public class Name(public val tokens: List<NameToken>) { } } val query = if (queryBuilder.isEmpty()) null else queryBuilder.toString() - yield(NameToken(bodyBuilder.toString(), query)) + add(NameToken(bodyBuilder.toString(), query)) } - return Name(tokens.toList()) + return Name(tokens) } } } From c62dc2c698ad802e38542c2490f9996d4944ae9f Mon Sep 17 00:00:00 2001 From: Alexander Nozik <altavir@gmail.com> Date: Tue, 4 Jun 2024 18:00:10 +0300 Subject: [PATCH 26/26] 0.9 release --- CHANGELOG.md | 21 +++++-- build.gradle.kts | 2 +- dataforge-context/README.md | 4 +- dataforge-context/api/dataforge-context.api | 23 ++----- dataforge-data/README.md | 4 +- dataforge-io/README.md | 4 +- dataforge-io/dataforge-io-yaml/README.md | 4 +- dataforge-meta/README.md | 4 +- dataforge-meta/api/dataforge-meta.api | 67 +++++++++++---------- dataforge-scripting/README.md | 4 +- dataforge-workspace/README.md | 4 +- 11 files changed, 72 insertions(+), 69 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d75dd1a2..1f59fbae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,22 +3,33 @@ ## Unreleased ### Added -- Custom CoroutineContext during `Context` creation. ### Changed -- Kotlin 2.0 -- `MetaSpec` renamed to `MetaReader`. MetaSpec is now reserved for builder-based generation of meta descriptors. -- Add self-type for Meta. Remove unsafe cast method for meta instances. ### Deprecated ### Removed -- Automatic descriptors for schema. It is not possible to implement them without heavy reflection. ### Fixed ### Security +## 0.9.0 - 2024-06-04 + +### Added + +- Custom CoroutineContext during `Context` creation. + +### Changed + +- Kotlin 2.0 +- `MetaSpec` renamed to `MetaReader`. MetaSpec is now reserved for builder-based generation of meta descriptors. +- Add self-type for Meta. Remove unsafe cast method for meta instances. + +### Removed + +- Automatic descriptors for schema. It is not possible to implement them without heavy reflection. + ## 0.8.2 - 2024-04-27 ### Added diff --git a/build.gradle.kts b/build.gradle.kts index 815a7077..72f61abc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -9,7 +9,7 @@ plugins { allprojects { group = "space.kscience" - version = "0.9.0-dev-1" + version = "0.9.0" } subprojects { diff --git a/dataforge-context/README.md b/dataforge-context/README.md index 7970751c..2cd53fd1 100644 --- a/dataforge-context/README.md +++ b/dataforge-context/README.md @@ -6,7 +6,7 @@ Context and provider definitions ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-context:0.8.2`. +The Maven coordinates of this project are `space.kscience:dataforge-context:0.9.0-dev-1`. **Gradle Kotlin DSL:** ```kotlin @@ -16,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:dataforge-context:0.8.2") + implementation("space.kscience:dataforge-context:0.9.0-dev-1") } ``` diff --git a/dataforge-context/api/dataforge-context.api b/dataforge-context/api/dataforge-context.api index eb94f89d..67cd0cba 100644 --- a/dataforge-context/api/dataforge-context.api +++ b/dataforge-context/api/dataforge-context.api @@ -57,6 +57,7 @@ public abstract interface class space/kscience/dataforge/context/ContextAware { public final class space/kscience/dataforge/context/ContextBuilder { public final fun build ()Lspace/kscience/dataforge/context/Context; + public final fun coroutineContext (Lkotlin/coroutines/CoroutineContext;)V public final fun getName ()Lspace/kscience/dataforge/names/Name; public final fun plugin (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V public final fun plugin (Lspace/kscience/dataforge/context/Plugin;)V @@ -69,9 +70,6 @@ public final class space/kscience/dataforge/context/ContextBuilder { public final fun properties (Lkotlin/jvm/functions/Function1;)V } -public final class space/kscience/dataforge/context/ContextBuilderKt { -} - public final class space/kscience/dataforge/context/DefaultLogManager : space/kscience/dataforge/context/AbstractPlugin, space/kscience/dataforge/context/LogManager { public static final field Companion Lspace/kscience/dataforge/context/DefaultLogManager$Companion; public fun <init> ()V @@ -212,14 +210,14 @@ public final class space/kscience/dataforge/context/PluginTag : space/kscience/d public fun toString ()Ljava/lang/String; } -public final class space/kscience/dataforge/context/PluginTag$$serializer : kotlinx/serialization/internal/GeneratedSerializer { +public synthetic class space/kscience/dataforge/context/PluginTag$$serializer : kotlinx/serialization/internal/GeneratedSerializer { public static final field INSTANCE Lspace/kscience/dataforge/context/PluginTag$$serializer; - public fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; - public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lspace/kscience/dataforge/context/PluginTag; - public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lspace/kscience/dataforge/context/PluginTag; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V - public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lspace/kscience/dataforge/context/PluginTag;)V + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lspace/kscience/dataforge/context/PluginTag;)V public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; } @@ -264,15 +262,6 @@ public abstract interface annotation class space/kscience/dataforge/descriptors/ public abstract interface annotation class space/kscience/dataforge/descriptors/Multiple : java/lang/annotation/Annotation { } -public final class space/kscience/dataforge/descriptors/ReflectiveDescriptorsKt { -} - -public final class space/kscience/dataforge/properties/MetaAsFlowKt { -} - -public final class space/kscience/dataforge/provider/DfTypeKt { -} - public final class space/kscience/dataforge/provider/Path : java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker { public static final field Companion Lspace/kscience/dataforge/provider/Path$Companion; public static final field PATH_SEGMENT_SEPARATOR Ljava/lang/String; diff --git a/dataforge-data/README.md b/dataforge-data/README.md index f08a43c2..35aaa4e6 100644 --- a/dataforge-data/README.md +++ b/dataforge-data/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-data:0.8.2`. +The Maven coordinates of this project are `space.kscience:dataforge-data:0.9.0-dev-1`. **Gradle Kotlin DSL:** ```kotlin @@ -16,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:dataforge-data:0.8.2") + implementation("space.kscience:dataforge-data:0.9.0-dev-1") } ``` diff --git a/dataforge-io/README.md b/dataforge-io/README.md index 5168797b..5a9979a9 100644 --- a/dataforge-io/README.md +++ b/dataforge-io/README.md @@ -6,7 +6,7 @@ IO module ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-io:0.8.2`. +The Maven coordinates of this project are `space.kscience:dataforge-io:0.9.0-dev-1`. **Gradle Kotlin DSL:** ```kotlin @@ -16,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:dataforge-io:0.8.2") + implementation("space.kscience:dataforge-io:0.9.0-dev-1") } ``` diff --git a/dataforge-io/dataforge-io-yaml/README.md b/dataforge-io/dataforge-io-yaml/README.md index cc1ecd8c..f70a1490 100644 --- a/dataforge-io/dataforge-io-yaml/README.md +++ b/dataforge-io/dataforge-io-yaml/README.md @@ -6,7 +6,7 @@ YAML meta IO ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-io-yaml:0.8.2`. +The Maven coordinates of this project are `space.kscience:dataforge-io-yaml:0.9.0-dev-1`. **Gradle Kotlin DSL:** ```kotlin @@ -16,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:dataforge-io-yaml:0.8.2") + implementation("space.kscience:dataforge-io-yaml:0.9.0-dev-1") } ``` diff --git a/dataforge-meta/README.md b/dataforge-meta/README.md index a3209760..e4fcacb1 100644 --- a/dataforge-meta/README.md +++ b/dataforge-meta/README.md @@ -6,7 +6,7 @@ Meta definition and basic operations on meta ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-meta:0.8.2`. +The Maven coordinates of this project are `space.kscience:dataforge-meta:0.9.0-dev-1`. **Gradle Kotlin DSL:** ```kotlin @@ -16,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:dataforge-meta:0.8.2") + implementation("space.kscience:dataforge-meta:0.9.0-dev-1") } ``` diff --git a/dataforge-meta/api/dataforge-meta.api b/dataforge-meta/api/dataforge-meta.api index 620e64d4..0bb4a908 100644 --- a/dataforge-meta/api/dataforge-meta.api +++ b/dataforge-meta/api/dataforge-meta.api @@ -103,6 +103,8 @@ public final class space/kscience/dataforge/meta/Laminate : space/kscience/dataf public synthetic fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMeta; public fun getItems ()Ljava/util/Map; public final fun getLayers ()Ljava/util/List; + public fun getSelf ()Lspace/kscience/dataforge/meta/Laminate; + public synthetic fun getSelf ()Lspace/kscience/dataforge/meta/TypedMeta; public fun getValue ()Lspace/kscience/dataforge/meta/Value; public fun hashCode ()I public final fun merge ()Lspace/kscience/dataforge/meta/SealedMeta; @@ -198,7 +200,7 @@ public final class space/kscience/dataforge/meta/MetaBuilder : space/kscience/da public abstract interface annotation class space/kscience/dataforge/meta/MetaBuilderMarker : java/lang/annotation/Annotation { } -public abstract interface class space/kscience/dataforge/meta/MetaConverter : space/kscience/dataforge/meta/MetaSpec { +public abstract interface class space/kscience/dataforge/meta/MetaConverter : space/kscience/dataforge/meta/MetaReader { public static final field Companion Lspace/kscience/dataforge/meta/MetaConverter$Companion; public abstract fun convert (Ljava/lang/Object;)Lspace/kscience/dataforge/meta/Meta; public fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; @@ -246,15 +248,15 @@ public final class space/kscience/dataforge/meta/MetaDelegateKt { public static final fun int (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MetaProvider;ILspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; - public static final fun listOfSpec (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; - public static synthetic fun listOfSpec$default (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun listOfSpec (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/MetaReader;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun listOfSpec$default (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/MetaReader;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; public static final fun long (Lspace/kscience/dataforge/meta/MetaProvider;JLspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; public static final fun long (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MetaProvider;JLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; - public static final fun node (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaSpec;)Lkotlin/properties/ReadOnlyProperty; + public static final fun node (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaReader;)Lkotlin/properties/ReadOnlyProperty; public static final fun node (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lspace/kscience/dataforge/meta/MetaDelegate; - public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaSpec;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaReader;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; @@ -262,8 +264,8 @@ public final class space/kscience/dataforge/meta/MetaDelegateKt { public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; - public static final fun spec (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; - public static synthetic fun spec$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static final fun spec (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/meta/MetaReader;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; + public static synthetic fun spec$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/meta/MetaReader;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MetaDelegate; public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MetaDelegate; public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lspace/kscience/dataforge/meta/MetaDelegate; @@ -294,7 +296,6 @@ public final class space/kscience/dataforge/meta/MetaKt { public static final fun getLong (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Long; public static final synthetic fun getNonNullable (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/names/NameToken;)Lspace/kscience/dataforge/meta/Meta; public static final fun getNumber (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Number; - public static final fun getSelf (Lspace/kscience/dataforge/meta/TypedMeta;)Lspace/kscience/dataforge/meta/TypedMeta; public static final fun getShort (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Short; public static final fun getString (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/String; public static final fun getStringList (Lspace/kscience/dataforge/meta/Meta;)Ljava/util/List; @@ -311,6 +312,16 @@ public abstract interface class space/kscience/dataforge/meta/MetaProvider : spa public fun getValue (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Value; } +public abstract interface class space/kscience/dataforge/meta/MetaReader : space/kscience/dataforge/meta/descriptors/Described { + public fun read (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Object; + public abstract fun readOrNull (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Object; +} + +public final class space/kscience/dataforge/meta/MetaReaderKt { + public static final fun readNullable (Lspace/kscience/dataforge/meta/MetaReader;Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Object; + public static final fun readValue (Lspace/kscience/dataforge/meta/MetaReader;Lspace/kscience/dataforge/meta/Value;)Ljava/lang/Object; +} + public abstract interface class space/kscience/dataforge/meta/MetaRepr { public abstract fun toMeta ()Lspace/kscience/dataforge/meta/Meta; } @@ -324,16 +335,6 @@ public final class space/kscience/dataforge/meta/MetaSerializer : kotlinx/serial public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lspace/kscience/dataforge/meta/Meta;)V } -public abstract interface class space/kscience/dataforge/meta/MetaSpec : space/kscience/dataforge/meta/descriptors/Described { - public fun read (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Object; - public abstract fun readOrNull (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Object; -} - -public final class space/kscience/dataforge/meta/MetaSpecKt { - public static final fun readNullable (Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Object; - public static final fun readValue (Lspace/kscience/dataforge/meta/MetaSpec;Lspace/kscience/dataforge/meta/Value;)Ljava/lang/Object; -} - public final class space/kscience/dataforge/meta/MetaTransformation { public static final field Companion Lspace/kscience/dataforge/meta/MetaTransformation$Companion; public static final fun apply-impl (Ljava/util/Collection;Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/Meta; @@ -551,6 +552,8 @@ public abstract interface class space/kscience/dataforge/meta/ObservableMutableM public fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; public synthetic fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMeta; public abstract fun getOrCreate (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; + public fun getSelf ()Lspace/kscience/dataforge/meta/ObservableMutableMeta; + public synthetic fun getSelf ()Lspace/kscience/dataforge/meta/TypedMeta; } public final class space/kscience/dataforge/meta/RegexItemTransformationRule : space/kscience/dataforge/meta/TransformationRule { @@ -624,19 +627,21 @@ public final class space/kscience/dataforge/meta/SealedMeta : space/kscience/dat public fun <init> (Lspace/kscience/dataforge/meta/Value;Ljava/util/Map;)V public fun equals (Ljava/lang/Object;)Z public fun getItems ()Ljava/util/Map; + public fun getSelf ()Lspace/kscience/dataforge/meta/SealedMeta; + public synthetic fun getSelf ()Lspace/kscience/dataforge/meta/TypedMeta; public fun getValue ()Lspace/kscience/dataforge/meta/Value; public fun hashCode ()I public fun toString ()Ljava/lang/String; } -public final class space/kscience/dataforge/meta/SealedMeta$$serializer : kotlinx/serialization/internal/GeneratedSerializer { +public synthetic class space/kscience/dataforge/meta/SealedMeta$$serializer : kotlinx/serialization/internal/GeneratedSerializer { public static final field INSTANCE Lspace/kscience/dataforge/meta/SealedMeta$$serializer; - public fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; - public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lspace/kscience/dataforge/meta/SealedMeta; - public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lspace/kscience/dataforge/meta/SealedMeta; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V - public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lspace/kscience/dataforge/meta/SealedMeta;)V + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lspace/kscience/dataforge/meta/SealedMeta;)V public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; } @@ -710,6 +715,7 @@ public abstract interface class space/kscience/dataforge/meta/TypedMeta : space/ public synthetic fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; public fun get (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMeta; public abstract fun getItems ()Ljava/util/Map; + public abstract fun getSelf ()Lspace/kscience/dataforge/meta/TypedMeta; public fun toMeta ()Lspace/kscience/dataforge/meta/Meta; } @@ -844,14 +850,14 @@ public final class space/kscience/dataforge/meta/descriptors/MetaDescriptor { public fun toString ()Ljava/lang/String; } -public final class space/kscience/dataforge/meta/descriptors/MetaDescriptor$$serializer : kotlinx/serialization/internal/GeneratedSerializer { +public synthetic class space/kscience/dataforge/meta/descriptors/MetaDescriptor$$serializer : kotlinx/serialization/internal/GeneratedSerializer { public static final field INSTANCE Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor$$serializer; - public fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public final fun childSerializers ()[Lkotlinx/serialization/KSerializer; public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; - public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; - public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public final fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; + public final fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V - public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)V + public final fun serialize (Lkotlinx/serialization/encoding/Encoder;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)V public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; } @@ -876,6 +882,7 @@ public final class space/kscience/dataforge/meta/descriptors/MetaDescriptorBuild public final fun getMultiple ()Z public final fun getValueRestriction ()Lspace/kscience/dataforge/meta/descriptors/ValueRestriction; public final fun getValueTypes ()Ljava/util/List; + public final fun node (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)V public final fun setAllowedValues (Ljava/util/List;)V public final fun setAttributes (Lspace/kscience/dataforge/meta/MutableMeta;)V public final fun setChildren (Ljava/util/Map;)V @@ -927,10 +934,6 @@ public final class space/kscience/dataforge/meta/descriptors/ValueRestriction$Co public final fun serializer ()Lkotlinx/serialization/KSerializer; } -public final class space/kscience/dataforge/misc/CastJvmKt { - public static final fun unsafeCast (Ljava/lang/Object;)Ljava/lang/Object; -} - public abstract interface annotation class space/kscience/dataforge/misc/DFBuilder : java/lang/annotation/Annotation { } diff --git a/dataforge-scripting/README.md b/dataforge-scripting/README.md index 3167e1b4..1f650bea 100644 --- a/dataforge-scripting/README.md +++ b/dataforge-scripting/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-scripting:0.8.2`. +The Maven coordinates of this project are `space.kscience:dataforge-scripting:0.9.0-dev-1`. **Gradle Kotlin DSL:** ```kotlin @@ -16,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:dataforge-scripting:0.8.2") + implementation("space.kscience:dataforge-scripting:0.9.0-dev-1") } ``` diff --git a/dataforge-workspace/README.md b/dataforge-workspace/README.md index f7461f30..87b38c6e 100644 --- a/dataforge-workspace/README.md +++ b/dataforge-workspace/README.md @@ -6,7 +6,7 @@ ## Artifact: -The Maven coordinates of this project are `space.kscience:dataforge-workspace:0.8.2`. +The Maven coordinates of this project are `space.kscience:dataforge-workspace:0.9.0-dev-1`. **Gradle Kotlin DSL:** ```kotlin @@ -16,6 +16,6 @@ repositories { } dependencies { - implementation("space.kscience:dataforge-workspace:0.8.2") + implementation("space.kscience:dataforge-workspace:0.9.0-dev-1") } ```