diff --git a/CHANGELOG.md b/CHANGELOG.md index e32cc6bf..87ccad00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased ### Added +- Wasm artifacts ### Changed @@ -11,6 +12,7 @@ ### Removed ### Fixed +- Partially fixed a bug with `MutableMeta` observable wrappers. ### Security diff --git a/build.gradle.kts b/build.gradle.kts index 4b5fe48c..edeae557 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -8,7 +8,7 @@ plugins { allprojects { group = "space.kscience" - version = "0.7.0" + version = "0.7.1" } subprojects { @@ -31,7 +31,7 @@ ksciencePublish { useSPCTeam() } repository("spc","https://maven.sciprog.center/kscience") - sonatype() + sonatype("https://oss.sonatype.org") } apiValidation { diff --git a/dataforge-context/build.gradle.kts b/dataforge-context/build.gradle.kts index be9036d0..b59abed0 100644 --- a/dataforge-context/build.gradle.kts +++ b/dataforge-context/build.gradle.kts @@ -8,12 +8,14 @@ kscience { jvm() js() native() + wasm() useCoroutines() useSerialization() - dependencies { + commonMain { api(project(":dataforge-meta")) + api(spclibs.atomicfu) } - dependencies(jvmMain){ + jvmMain{ api(kotlin("reflect")) api("org.slf4j:slf4j-api:1.7.30") } diff --git a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Plugin.kt b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Plugin.kt index 152f5a76..6c5648a6 100644 --- a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Plugin.kt +++ b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Plugin.kt @@ -3,7 +3,7 @@ package space.kscience.dataforge.context import space.kscience.dataforge.context.Plugin.Companion.TARGET import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MetaRepr -import space.kscience.dataforge.misc.DfId +import space.kscience.dataforge.misc.DfType import space.kscience.dataforge.misc.Named import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.parseAsName @@ -18,7 +18,7 @@ import space.kscience.dataforge.provider.Provider * * create - configure - attach - detach - destroy */ -@DfId(TARGET) +@DfType(TARGET) public interface Plugin : Named, ContextAware, Provider, MetaRepr { /** diff --git a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/PluginFactory.kt b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/PluginFactory.kt index 0273d327..9cc67168 100644 --- a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/PluginFactory.kt +++ b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/PluginFactory.kt @@ -1,9 +1,9 @@ package space.kscience.dataforge.context import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.misc.DfId +import space.kscience.dataforge.misc.DfType -@DfId(PluginFactory.TYPE) +@DfType(PluginFactory.TYPE) public interface PluginFactory : Factory { public val tag: PluginTag diff --git a/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/provider/dfType.kt b/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/provider/dfType.kt index ab34ea50..04e681da 100644 --- a/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/provider/dfType.kt +++ b/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/provider/dfType.kt @@ -4,7 +4,7 @@ import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.PluginBuilder import space.kscience.dataforge.context.gather import space.kscience.dataforge.misc.DFExperimental -import space.kscience.dataforge.misc.DfId +import space.kscience.dataforge.misc.DfType import space.kscience.dataforge.misc.Named import space.kscience.dataforge.names.Name import kotlin.reflect.KClass @@ -13,10 +13,10 @@ import kotlin.reflect.full.findAnnotation @DFExperimental public val KClass<*>.dfId: String - get() = findAnnotation()?.id ?: simpleName ?: "" + get() = findAnnotation()?.id ?: simpleName ?: "" /** - * Provide an object with given name inferring target from its type using [DfId] annotation + * Provide an object with given name inferring target from its type using [DfType] annotation */ @DFExperimental public inline fun Provider.provideByType(name: String): T? { diff --git a/dataforge-context/src/wasmJsMain/kotlin/space/kscience/dataforge/context/loggingWasm.kt b/dataforge-context/src/wasmJsMain/kotlin/space/kscience/dataforge/context/loggingWasm.kt new file mode 100644 index 00000000..740957b4 --- /dev/null +++ b/dataforge-context/src/wasmJsMain/kotlin/space/kscience/dataforge/context/loggingWasm.kt @@ -0,0 +1,3 @@ +package space.kscience.dataforge.context + +internal actual fun getGlobalLoggerFactory(): PluginFactory = DefaultLogManager \ No newline at end of file diff --git a/dataforge-data/build.gradle.kts b/dataforge-data/build.gradle.kts index 9f96604a..ea542290 100644 --- a/dataforge-data/build.gradle.kts +++ b/dataforge-data/build.gradle.kts @@ -6,9 +6,11 @@ kscience{ jvm() js() native() + wasm() useCoroutines() dependencies { - api(project(":dataforge-meta")) + api(spclibs.atomicfu) + api(projects.dataforgeMeta) api(kotlin("reflect")) } } 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 883b3928..7b2c94f5 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 @@ -98,8 +98,7 @@ internal class MapAction( * A one-to-one mapping action */ @DFExperimental -@Suppress("FunctionName") -public inline fun Action.Companion.map( +public inline fun Action.Companion.mapping( noinline builder: MapActionBuilder.() -> Unit, ): Action = MapAction(typeOf(), 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 fe823bd7..a74cfad9 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 @@ -112,6 +112,6 @@ internal class ReduceAction( * A one-to-one mapping action */ @DFExperimental -public inline fun Action.Companion.reduce( +public inline fun Action.Companion.reducing( noinline builder: ReduceGroupBuilder.() -> Unit, ): Action = ReduceAction(typeOf(), 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 24745929..0ecde319 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 @@ -87,6 +87,6 @@ internal class SplitAction( * Action that splits each incoming element into a number of fragments defined in builder */ @DFExperimental -public inline fun Action.Companion.split( +public inline fun Action.Companion.splitting( noinline builder: SplitBuilder.() -> Unit, ): Action = SplitAction(typeOf(), builder) \ No newline at end of file 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 984582e5..4d883795 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 @@ -5,7 +5,7 @@ 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.DfId +import space.kscience.dataforge.misc.DfType import kotlin.coroutines.CoroutineContext import kotlin.coroutines.EmptyCoroutineContext import kotlin.reflect.KType @@ -14,7 +14,7 @@ import kotlin.reflect.typeOf /** * A data element characterized by its meta */ -@DfId(Data.TYPE) +@DfType(Data.TYPE) public interface Data : Goal, MetaRepr { /** * Type marker for the data. The type is known before the calculation takes place so it could be checked. diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataTree.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataTree.kt index bafcbea2..b9273c07 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataTree.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataTree.kt @@ -2,7 +2,7 @@ package space.kscience.dataforge.data import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.misc.DFInternal -import space.kscience.dataforge.misc.DfId +import space.kscience.dataforge.misc.DfType import space.kscience.dataforge.names.* import kotlin.collections.component1 import kotlin.collections.component2 @@ -31,7 +31,7 @@ public val DataTreeItem.type: KType /** * A tree-like [DataSet] grouped into the node. All data inside the node must inherit its type */ -@DfId(DataTree.TYPE) +@DfType(DataTree.TYPE) public interface DataTree : DataSet { /** diff --git a/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/actionInContext.kt b/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/actionInContext.kt deleted file mode 100644 index 33731a95..00000000 --- a/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/actionInContext.kt +++ /dev/null @@ -1,2 +0,0 @@ -package space.kscience.dataforge.data - 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 3987cd19..b24c4f27 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 @@ -6,7 +6,7 @@ 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.map +import space.kscience.dataforge.actions.mapping import space.kscience.dataforge.misc.DFExperimental import kotlin.test.assertEquals @@ -20,7 +20,7 @@ internal class ActionsTest { } } - val plusOne = Action.map { + val plusOne = Action.mapping { result { it + 1 } } val result = plusOne(data) @@ -31,7 +31,7 @@ internal class ActionsTest { fun testDynamicMapAction() = runTest { val data: DataSourceBuilder = DataSource() - val plusOne = Action.map { + val plusOne = Action.mapping { result { it + 1 } } diff --git a/dataforge-io/build.gradle.kts b/dataforge-io/build.gradle.kts index 6d3c888c..f7197197 100644 --- a/dataforge-io/build.gradle.kts +++ b/dataforge-io/build.gradle.kts @@ -4,12 +4,13 @@ plugins { description = "IO module" -val ioVersion = "0.2.1" +val ioVersion = "0.3.0" kscience { jvm() js() native() + wasm() useSerialization() useSerialization(sourceSet = space.kscience.gradle.DependencySourceSet.TEST) { cbor() diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeFormat.kt index 0df5ab27..0e998760 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeFormat.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeFormat.kt @@ -4,7 +4,7 @@ import kotlinx.io.Source import space.kscience.dataforge.context.Context import space.kscience.dataforge.io.EnvelopeFormatFactory.Companion.ENVELOPE_FORMAT_TYPE import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.misc.DfId +import space.kscience.dataforge.misc.DfType import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import kotlin.reflect.KType @@ -17,7 +17,7 @@ public interface EnvelopeFormat : IOFormat { public fun EnvelopeFormat.read(input: Source): Envelope = readFrom(input) -@DfId(ENVELOPE_FORMAT_TYPE) +@DfType(ENVELOPE_FORMAT_TYPE) public interface EnvelopeFormatFactory : IOFormatFactory, EnvelopeFormat { override val type: KType get() = typeOf() diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/IOFormat.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/IOFormat.kt index ffcadf1a..390a8bf4 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/IOFormat.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/IOFormat.kt @@ -7,7 +7,7 @@ import space.kscience.dataforge.context.Context import space.kscience.dataforge.context.Factory import space.kscience.dataforge.io.IOFormatFactory.Companion.IO_FORMAT_TYPE import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.misc.DfId +import space.kscience.dataforge.misc.DfType import space.kscience.dataforge.misc.Named import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName @@ -72,7 +72,7 @@ public fun Sink.writeWith(format: IOWriter, obj: T): Unit = format.writeTo(this, obj) -@DfId(IO_FORMAT_TYPE) +@DfType(IO_FORMAT_TYPE) public interface IOFormatFactory : Factory>, Named { /** * Explicit type for dynamic type checks diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/MetaFormat.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/MetaFormat.kt index cadf87ca..f864dd2f 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/MetaFormat.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/MetaFormat.kt @@ -9,7 +9,7 @@ import space.kscience.dataforge.context.Global import space.kscience.dataforge.io.MetaFormatFactory.Companion.META_FORMAT_TYPE import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.descriptors.MetaDescriptor -import space.kscience.dataforge.misc.DfId +import space.kscience.dataforge.misc.DfType import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.plus @@ -38,7 +38,7 @@ public interface MetaFormat : IOFormat { public fun readMeta(source: Source, descriptor: MetaDescriptor? = null): Meta } -@DfId(META_FORMAT_TYPE) +@DfType(META_FORMAT_TYPE) public interface MetaFormatFactory : IOFormatFactory, MetaFormat { public val shortName: String diff --git a/dataforge-meta/api/dataforge-meta.api b/dataforge-meta/api/dataforge-meta.api index 7daa7540..1700ca7d 100644 --- a/dataforge-meta/api/dataforge-meta.api +++ b/dataforge-meta/api/dataforge-meta.api @@ -724,6 +724,7 @@ public final class space/kscience/dataforge/meta/descriptors/MetaDescriptorBuild public final fun getAttributes ()Lspace/kscience/dataforge/meta/MutableMeta; public final fun getChildren ()Ljava/util/Map; 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 @@ -737,6 +738,7 @@ public final class space/kscience/dataforge/meta/descriptors/MetaDescriptorBuild public final fun setAttributes (Lspace/kscience/dataforge/meta/MutableMeta;)V public final fun setChildren (Ljava/util/Map;)V 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 @@ -903,7 +905,7 @@ public abstract interface annotation class space/kscience/dataforge/misc/DFExper public abstract interface annotation class space/kscience/dataforge/misc/DFInternal : java/lang/annotation/Annotation { } -public abstract interface annotation class space/kscience/dataforge/misc/DfId : java/lang/annotation/Annotation { +public abstract interface annotation class space/kscience/dataforge/misc/DfType : java/lang/annotation/Annotation { public abstract fun id ()Ljava/lang/String; } @@ -944,6 +946,7 @@ public final class space/kscience/dataforge/names/NameKt { public static final fun asName (Lspace/kscience/dataforge/names/NameToken;)Lspace/kscience/dataforge/names/Name; public static final fun cutFirst (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/names/Name; public static final fun cutLast (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/names/Name; + public static final fun endsWith (Lspace/kscience/dataforge/names/Name;Ljava/lang/String;)Z public static final fun endsWith (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/names/Name;)Z public static final fun endsWith (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/names/NameToken;)Z public static final fun first (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/names/NameToken; @@ -966,6 +969,7 @@ public final class space/kscience/dataforge/names/NameKt { public static final fun removeHeadOrNull (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/names/Name; public static final fun replaceLast (Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/names/Name; public static final fun set (Ljava/util/Map;Ljava/lang/String;Ljava/lang/Object;)V + public static final fun startsWith (Lspace/kscience/dataforge/names/Name;Ljava/lang/String;)Z public static final fun startsWith (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/names/Name;)Z public static final fun startsWith (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/names/NameToken;)Z public static final fun withIndex (Lspace/kscience/dataforge/names/Name;Ljava/lang/String;)Lspace/kscience/dataforge/names/Name; diff --git a/dataforge-meta/build.gradle.kts b/dataforge-meta/build.gradle.kts index 51b07113..d150ef98 100644 --- a/dataforge-meta/build.gradle.kts +++ b/dataforge-meta/build.gradle.kts @@ -6,6 +6,7 @@ kscience { jvm() js() native() + wasm() useSerialization{ json() } 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 420625ca..979c8782 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 @@ -2,7 +2,7 @@ package space.kscience.dataforge.meta import kotlinx.serialization.Serializable import kotlinx.serialization.json.Json -import space.kscience.dataforge.misc.DfId +import space.kscience.dataforge.misc.DfType import space.kscience.dataforge.misc.unsafeCast import space.kscience.dataforge.names.* import kotlin.jvm.JvmName @@ -31,7 +31,7 @@ public fun interface MetaProvider : ValueProvider { * TODO add documentation * Same name siblings are supported via elements with the same [Name] but different indices. */ -@DfId(Meta.TYPE) +@DfType(Meta.TYPE) @Serializable(MetaSerializer::class) public interface Meta : MetaRepr, MetaProvider { public val value: Value? @@ -248,7 +248,7 @@ public inline fun > Meta?.enum(): E? = this?.value?.let { } } -public val Meta.stringList: List? get() = value?.list?.map { it.string } +public val Meta?.stringList: List? get() = this?.value?.list?.map { it.string } /** * Create a provider that uses given provider for default values if those are not found in this provider 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 76645d83..71e15aa9 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 @@ -6,60 +6,71 @@ import space.kscience.dataforge.names.* /** * A class that takes [MutableMeta] provider and adds obsevability on top of that + * + * TODO rewrite to properly work with detached nodes */ private class ObservableMetaWrapper( val root: MutableMeta, - val absoluteName: Name, + val nodeName: Name, val listeners: MutableSet, ) : ObservableMutableMeta { override val items: Map get() = root.items.keys.associateWith { - ObservableMetaWrapper(root, absoluteName + it, listeners) + ObservableMetaWrapper(root, nodeName + it, listeners) } - override fun get(name: Name): ObservableMutableMeta? = - root.get(name)?.let { ObservableMetaWrapper(root, this.absoluteName + name, listeners) } + override fun get(name: Name): ObservableMutableMeta? = if (root[nodeName + name] == null) { + null + } else { + ObservableMetaWrapper(root, nodeName + name, listeners) + } @ThreadSafe override fun onChange(owner: Any?, callback: Meta.(name: Name) -> Unit) { listeners.add( - MetaListener(Pair(owner, absoluteName)) { name -> - if (name.startsWith(absoluteName)) { - (this[absoluteName] ?: Meta.EMPTY).callback(name.removeFirstOrNull(absoluteName)!!) + MetaListener(Pair(owner, nodeName)) { fullName -> + if (fullName.startsWith(nodeName)) { + root[nodeName]?.callback(fullName.removeFirstOrNull(nodeName)!!) } } ) } override fun removeListener(owner: Any?) { - listeners.removeAll { it.owner === Pair(owner, absoluteName) } + listeners.removeAll { it.owner === Pair(owner, nodeName) } } override fun invalidate(name: Name) { - listeners.forEach { it.callback(this, name) } + listeners.forEach { it.callback(this, nodeName + name) } } override var value: Value? - get() = root.value + get() = root[nodeName]?.value set(value) { - root.value = value + root.getOrCreate(nodeName).value = value invalidate(Name.EMPTY) } override fun getOrCreate(name: Name): ObservableMutableMeta = - ObservableMetaWrapper(root, this.absoluteName + name, listeners) + ObservableMetaWrapper(root, nodeName + name, listeners) - override fun set(name: Name, node: Meta?) { + fun removeNode(name: Name): Meta? { val oldMeta = get(name) //don't forget to remove listener oldMeta?.removeListener(this) - root.set(absoluteName + name, node) + + return oldMeta + } + + override fun set(name: Name, node: Meta?) { + val oldMeta = removeNode(name) + root[nodeName + name] = node if (oldMeta != node) { invalidate(name) } } - override fun toMeta(): Meta = root[absoluteName]?.toMeta() ?: Meta.EMPTY + override fun toMeta(): Meta = root[nodeName]?.toMeta() ?: Meta.EMPTY 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 ae6c171a..95949d03 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 @@ -9,7 +9,11 @@ import space.kscience.dataforge.names.length import kotlin.collections.set public class MetaDescriptorBuilder @PublishedApi internal constructor() { - public var info: String? = null + public var description: String? = null + + @Deprecated("Replace by description", ReplaceWith("description")) + public var info: String? by ::description + public var children: MutableMap = linkedMapOf() public var multiple: Boolean = false public var valueRestriction: ValueRestriction = ValueRestriction.NONE @@ -87,7 +91,7 @@ public class MetaDescriptorBuilder @PublishedApi internal constructor() { @PublishedApi internal fun build(): MetaDescriptor = MetaDescriptor( - description = info, + description = description, children = children.mapValues { it.value.build() }, multiple = multiple, valueRestriction = valueRestriction, @@ -165,7 +169,7 @@ public inline fun > MetaDescriptorBuilder.enum( } private fun MetaDescriptor.toBuilder(): MetaDescriptorBuilder = MetaDescriptorBuilder().apply { - info = this@toBuilder.description + description = this@toBuilder.description children = this@toBuilder.children.mapValuesTo(LinkedHashMap()) { it.value.toBuilder() } multiple = this@toBuilder.multiple valueRestriction = this@toBuilder.valueRestriction diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/DfId.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/DfType.kt similarity index 56% rename from dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/DfId.kt rename to dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/DfType.kt index 5d485e23..11f548ae 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/DfId.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/DfType.kt @@ -5,4 +5,7 @@ package space.kscience.dataforge.misc */ @MustBeDocumented @Target(AnnotationTarget.CLASS) -public annotation class DfId(val id: String) +public annotation class DfType(val id: String) + +@Deprecated("Replace with DfType", replaceWith = ReplaceWith("DfType")) +public typealias DfId = DfType 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 160ea3a1..1c9a9cf3 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 @@ -216,9 +216,13 @@ public fun Name.endsWith(token: NameToken): Boolean = lastOrNull() == token public fun Name.startsWith(name: Name): Boolean = this.length >= name.length && (this == name || tokens.subList(0, name.length) == name.tokens) +public fun Name.startsWith(name: String): Boolean = startsWith(name.parseAsName()) + public fun Name.endsWith(name: Name): Boolean = this.length >= name.length && (this == name || tokens.subList(length - name.length, length) == name.tokens) +public fun Name.endsWith(name: String): Boolean = endsWith(name.parseAsName()) + /** * if [this] starts with given [head] name, returns the reminder of the name (could be empty). Otherwise, returns 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 new file mode 100644 index 00000000..4681ec12 --- /dev/null +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/ObservableMetaTest.kt @@ -0,0 +1,49 @@ +package space.kscience.dataforge.meta + +import space.kscience.dataforge.names.startsWith +import kotlin.test.Ignore +import kotlin.test.Test +import kotlin.test.assertEquals + +class ObservableMetaTest { + + @Test + fun asObservable() { + val meta = MutableMeta { + "data" put { + "x" put ListValue(1, 2, 3) + "y" put ListValue(5, 6, 7) + "type" put "scatter" + } + }.asObservable() + + assertEquals("scatter", meta["data.type"].string) + } + + @Test + @Ignore + fun detachNode() { + val meta = MutableMeta { + "data" put { + "x" put ListValue(1, 2, 3) + "y" put ListValue(5, 6, 7) + "type" put "scatter" + } + }.asObservable() + + var collector: Value? = null + + meta.onChange(null) { name -> + if (name.startsWith("data")) { + collector = get("data.z")?.value + } + } + + val data = meta["data"]!! + + meta.remove("data") + + data["z"] = ListValue(2, 5, 7) + assertEquals(null, collector) + } +} \ No newline at end of file diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/descriptors/DescriptorTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/descriptors/DescriptorTest.kt index e8c321fc..1a08ce34 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/descriptors/DescriptorTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/descriptors/DescriptorTest.kt @@ -11,14 +11,14 @@ class DescriptorTest { val descriptor = MetaDescriptor { node("aNode") { - info = "A root demo node" + description = "A root demo node" value("b", ValueType.NUMBER) { - info = "b number value" + description = "b number value" } node("otherNode") { value("otherValue", ValueType.BOOLEAN) { default(false) - info = "default value" + description = "default value" } } } 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 index b404ebb4..b057bcbe 100644 --- a/dataforge-meta/src/jsMain/kotlin/space/kscience/dataforge/misc/castJs.kt +++ b/dataforge-meta/src/jsMain/kotlin/space/kscience/dataforge/misc/castJs.kt @@ -1,5 +1,5 @@ package space.kscience.dataforge.misc import kotlin.js.unsafeCast as unsafeCastJs -@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") -public actual inline fun Any?.unsafeCast(): T = this.unsafeCastJs() \ No newline at end of file +@Suppress("NOTHING_TO_INLINE") +public actual inline fun Any?.unsafeCast(): T = unsafeCastJs() \ 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 index 27d399fe..4d9aa758 100644 --- a/dataforge-meta/src/nativeMain/kotlin/space/kscience/dataforge/misc/castNative.kt +++ b/dataforge-meta/src/nativeMain/kotlin/space/kscience/dataforge/misc/castNative.kt @@ -1,4 +1,4 @@ package space.kscience.dataforge.misc -@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") +@Suppress("UNCHECKED_CAST") public actual inline fun 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 new file mode 100644 index 00000000..27d399fe --- /dev/null +++ b/dataforge-meta/src/wasmJsMain/kotlin/space/kscience/dataforge/misc/castWasm.kt @@ -0,0 +1,4 @@ +package space.kscience.dataforge.misc + +@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE") +public actual inline fun Any?.unsafeCast(): T = this as T \ No newline at end of file diff --git a/dataforge-scripting/build.gradle.kts b/dataforge-scripting/build.gradle.kts index be81fe70..d9d87742 100644 --- a/dataforge-scripting/build.gradle.kts +++ b/dataforge-scripting/build.gradle.kts @@ -4,15 +4,15 @@ plugins { kscience{ jvm() - dependencies { + commonMain { api(projects.dataforgeWorkspace) implementation(kotlin("scripting-common")) } - dependencies(jvmMain){ + jvmMain{ implementation(kotlin("scripting-jvm-host")) implementation(kotlin("scripting-jvm")) } - dependencies(jvmTest){ + jvmTest{ implementation(spclibs.logback.classic) } } diff --git a/dataforge-workspace/build.gradle.kts b/dataforge-workspace/build.gradle.kts index ec117865..5fa555eb 100644 --- a/dataforge-workspace/build.gradle.kts +++ b/dataforge-workspace/build.gradle.kts @@ -2,29 +2,27 @@ plugins { id("space.kscience.gradle.mpp") } -kscience{ +kscience { jvm() js() native() + wasm() useCoroutines() - useSerialization{ + useSerialization { protobuf() } - commonMain{ - dependencies { - api(projects.dataforgeContext) - api(projects.dataforgeData) - api(projects.dataforgeIo) - } + commonMain { + api(projects.dataforgeContext) + api(projects.dataforgeData) + api(projects.dataforgeIo) + } - jvmTest{ - dependencies { - implementation(spclibs.logback.classic) - implementation(projects.dataforgeIo.dataforgeIoYaml) - } + jvmTest { + implementation(spclibs.logback.classic) + implementation(projects.dataforgeIo.dataforgeIoYaml) } } -readme{ +readme { maturity = space.kscience.gradle.Maturity.EXPERIMENTAL } \ 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 a1ef7be2..329d9c5a 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 @@ -9,7 +9,7 @@ import space.kscience.dataforge.meta.MetaRepr import space.kscience.dataforge.meta.Specification import space.kscience.dataforge.meta.descriptors.Described import space.kscience.dataforge.meta.descriptors.MetaDescriptor -import space.kscience.dataforge.misc.DfId +import space.kscience.dataforge.misc.DfType import space.kscience.dataforge.names.Name import space.kscience.dataforge.workspace.Task.Companion.TYPE import kotlin.reflect.KType @@ -19,7 +19,7 @@ import kotlin.reflect.typeOf * A configurable task that could be executed on a workspace. The [TaskResult] represents a lazy result of the task. * In general no computations should be made until the result is called. */ -@DfId(TYPE) +@DfType(TYPE) public interface Task : Described { /** 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 ee00f539..37b473db 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 @@ -6,7 +6,7 @@ import space.kscience.dataforge.data.DataSet import space.kscience.dataforge.data.asSequence import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MutableMeta -import space.kscience.dataforge.misc.DfId +import space.kscience.dataforge.misc.DfType import space.kscience.dataforge.names.Name import space.kscience.dataforge.provider.Provider @@ -18,7 +18,7 @@ public interface DataSelector{ /** * An environment for pull-mode computation */ -@DfId(Workspace.TYPE) +@DfType(Workspace.TYPE) public interface Workspace : ContextAware, Provider { /** * The whole data node for current workspace diff --git a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/fileData.kt b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/fileData.kt index d9f678b3..ce1b5152 100644 --- a/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/fileData.kt +++ b/dataforge-workspace/src/jvmMain/kotlin/space/kscience/dataforge/workspace/fileData.kt @@ -11,7 +11,6 @@ import space.kscience.dataforge.data.* import space.kscience.dataforge.io.* import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.copy -import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.string import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFInternal @@ -27,10 +26,7 @@ import java.nio.file.WatchEvent import java.nio.file.attribute.BasicFileAttributes import java.nio.file.spi.FileSystemProvider import java.time.Instant -import kotlin.io.path.extension -import kotlin.io.path.name -import kotlin.io.path.nameWithoutExtension -import kotlin.io.path.readAttributes +import kotlin.io.path.* import kotlin.reflect.KType import kotlin.reflect.typeOf @@ -92,7 +88,7 @@ public fun IOPlugin.readDataFile( context(IOPlugin) @DFExperimental -private fun DataSetBuilder.directory( +public fun DataSetBuilder.directory( path: Path, ignoreExtensions: Set, formatResolver: FileFormatResolver, @@ -145,7 +141,7 @@ public inline fun IOPlugin.readDataDirectory( ): DataTree = readDataDirectory(typeOf(), path, ignoreExtensions, formatResolver) /** - * Read raw binary data tree from the directory. All files are read as-is (save for meta files). + * Read a raw binary data tree from the directory. All files are read as-is (save for meta files). */ @DFExperimental public fun IOPlugin.readRawDirectory( @@ -260,6 +256,29 @@ public suspend fun IOPlugin.writeDataDirectory( } } +/** + * Reads the specified resources and returns a [DataTree] containing the data. + * + * @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. + * @return A DataTree containing the data read from the resources. + */ +@DFExperimental +private fun IOPlugin.readResources( + vararg resources: String, + classLoader: ClassLoader = Thread.currentThread().contextClassLoader, +): DataTree { +// require(resource.isNotBlank()) {"Can't mount root resource tree as data root"} + return DataTree { + resources.forEach { resource -> + val path = classLoader.getResource(resource)?.toURI()?.toPath() ?: error( + "Resource with name $resource is not resolved" + ) + node(resource, readRawDirectory(path)) + } + } +} + /** * Add file/directory-based data tree item * diff --git a/gradle.properties b/gradle.properties index 31ef2f9a..3734d13e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,5 +6,5 @@ kotlin.mpp.stability.nowarn=true kotlin.incremental.js.ir=true kotlin.native.ignoreDisabledTargets=true -toolsVersion=0.15.1-kotlin-1.9.21 +toolsVersion=0.15.2-kotlin-1.9.21 #kotlin.experimental.tryK2=true \ No newline at end of file