From 8763d63e28b4d0f567ee2ec4056f5a50455eebb1 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sat, 31 Jul 2021 15:02:11 +0300 Subject: [PATCH] Name revolution --- CHANGELOG.md | 1 + build.gradle.kts | 2 +- .../dataforge/context/ContextBuilder.kt | 7 +- .../kscience/dataforge/context/Plugin.kt | 3 +- .../dataforge/properties/schemeProperty.kt | 12 +- .../space/kscience/dataforge/provider/Path.kt | 3 +- .../kscience/dataforge/context/ContextTest.kt | 8 +- ...ropertiesTest.kt => MetaPropertiesTest.kt} | 2 +- .../dataforge/actions/ReduceAction.kt | 3 +- .../kscience/dataforge/actions/SplitAction.kt | 3 +- .../kscience/dataforge/data/ActiveDataTree.kt | 2 +- .../kscience/dataforge/data/DataSetBuilder.kt | 27 ++-- .../space/kscience/dataforge/data/DataTree.kt | 2 +- .../kscience/dataforge/data/dataFilter.kt | 7 +- .../space/kscience/dataforge/data/select.kt | 3 +- .../dataforge/data/DataTreeBuilderTest.kt | 4 +- .../kscience/dataforge/io/EnvelopeParts.kt | 3 +- .../space/kscience/dataforge/io/IOPlugin.kt | 6 +- .../dataforge/io/TaggedEnvelopeFormat.kt | 4 +- .../dataforge/io/MetaSerializerTest.kt | 3 +- .../space/kscience/dataforge/meta/Meta.kt | 29 +++-- .../kscience/dataforge/meta/MetaDelegate.kt | 44 +++---- .../kscience/dataforge/meta/MutableMeta.kt | 81 ++++++------ .../dataforge/meta/MutableMetaDelegate.kt | 56 ++++----- .../kscience/dataforge/meta/ObservableMeta.kt | 20 +-- .../space/kscience/dataforge/meta/Scheme.kt | 55 ++------- .../kscience/dataforge/meta/Specification.kt | 5 + .../meta/descriptors/MetaDescriptor.kt | 2 +- .../meta/descriptors/MetaDescriptorBuilder.kt | 20 ++- .../space/kscience/dataforge/meta/mapMeta.kt | 6 +- .../transformations/MetaTransformation.kt | 6 +- .../space/kscience/dataforge/names/Name.kt | 116 +++++++++--------- .../dataforge/names/NameSerializer.kt | 4 +- .../kscience/dataforge/names/nameMatcher.kt | 2 +- .../dataforge/meta/MetaDelegateTest.kt | 2 +- .../kscience/dataforge/names/NameMatchTest.kt | 4 +- .../dataforge/names/NameSerializationTest.kt | 2 +- .../kscience/dataforge/names/NameTest.kt | 16 +-- .../kscience/dataforge/meta/DynamicMeta.kt | 4 - .../kscience/dataforge/workspace/Workspace.kt | 7 +- .../dataforge/workspace/WorkspaceBuilder.kt | 5 +- .../workspace/DataPropagationTest.kt | 3 +- 42 files changed, 298 insertions(+), 296 deletions(-) rename dataforge-context/src/commonTest/kotlin/space/kscience/dataforge/properties/{ItemPropertiesTest.kt => MetaPropertiesTest.kt} (96%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 030dac71..58343967 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Build tools 0.10.0 - Relaxed type restriction on `MetaConverter`. Now nullables are available. - **Huge API-breaking refactoring of Meta**. Meta now can hava both value and children. +- **API breaking** `String.toName()` is replaced by `Name.parse()` ### Deprecated - Direct use of `Config` diff --git a/build.gradle.kts b/build.gradle.kts index 67575df7..b1a365cf 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ plugins { allprojects { group = "space.kscience" - version = "0.5.0-dev-3" + version = "0.5.0-dev-4" } subprojects { 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 016eb139..0de5fb7a 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 @@ -7,8 +7,9 @@ import space.kscience.dataforge.meta.toMutableMeta import space.kscience.dataforge.misc.DFBuilder 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 space.kscience.dataforge.names.toName import kotlin.collections.component1 import kotlin.collections.component2 import kotlin.collections.set @@ -30,7 +31,7 @@ public class ContextBuilder internal constructor( } public fun name(string: String) { - this.name = string.toName() + this.name = Name.parse(string) } @OptIn(DFExperimental::class) @@ -63,7 +64,7 @@ public class ContextBuilder internal constructor( } public fun build(): Context { - val contextName = name ?: "@auto[${hashCode().toUInt().toString(16)}]".toName() + val contextName = name ?: NameToken("@auto",hashCode().toUInt().toString(16)).asName() val plugins = HashMap() fun addPlugin(factory: PluginFactory<*>, meta: Meta) { 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 d0f03172..62519a4a 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 @@ -6,7 +6,6 @@ import space.kscience.dataforge.meta.MetaRepr import space.kscience.dataforge.misc.Named import space.kscience.dataforge.misc.Type import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.toName import space.kscience.dataforge.provider.Provider /** @@ -31,7 +30,7 @@ public interface Plugin : Named, ContextAware, Provider, MetaRepr { /** * The name of this plugin ignoring version and group */ - override val name: Name get() = tag.name.toName() + override val name: Name get() = Name.parse(tag.name) /** * Plugin dependencies which are required to attach this plugin. Plugin diff --git a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/schemeProperty.kt b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/schemeProperty.kt index 452eb209..68b42018 100644 --- a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/schemeProperty.kt +++ b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/schemeProperty.kt @@ -1,14 +1,14 @@ package space.kscience.dataforge.properties -import space.kscience.dataforge.meta.ObservableMeta +import space.kscience.dataforge.meta.Scheme import space.kscience.dataforge.misc.DFExperimental +import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.startsWith -import space.kscience.dataforge.names.toName import kotlin.reflect.KMutableProperty1 @DFExperimental -public fun

P.property(property: KMutableProperty1): Property = +public fun S.property(property: KMutableProperty1): Property = object : Property { override var value: T? get() = property.get(this@property) @@ -17,15 +17,15 @@ public fun

P.property(property: KMutableProperty1< } override fun onChange(owner: Any?, callback: (T?) -> Unit) { - this@property.onChange(this) { name -> - if (name.startsWith(property.name.toName())) { + this@property.meta.onChange(this) { name -> + if (name.startsWith(Name.parse(property.name))) { callback(property.get(this@property)) } } } override fun removeChangeListener(owner: Any?) { - this@property.removeListener(this@property) + this@property.meta.removeListener(this@property) } } \ No newline at end of file diff --git a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/provider/Path.kt b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/provider/Path.kt index ef4b4664..4d558179 100644 --- a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/provider/Path.kt +++ b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/provider/Path.kt @@ -16,7 +16,6 @@ package space.kscience.dataforge.provider import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.toName import kotlin.jvm.JvmInline /** @@ -63,7 +62,7 @@ public data class PathToken(val name: Name, val target: String? = null) { public const val TARGET_SEPARATOR: String = "::" public fun parse(token: String): PathToken { val target = token.substringBefore(TARGET_SEPARATOR, "") - val name = token.substringAfter(TARGET_SEPARATOR).toName() + val name = Name.parse(token.substringAfter(TARGET_SEPARATOR)) if (target.contains("[")) TODO("target separators in queries are not supported") return PathToken(name, target) } diff --git a/dataforge-context/src/commonTest/kotlin/space/kscience/dataforge/context/ContextTest.kt b/dataforge-context/src/commonTest/kotlin/space/kscience/dataforge/context/ContextTest.kt index 81fcf884..8e39eb3f 100644 --- a/dataforge-context/src/commonTest/kotlin/space/kscience/dataforge/context/ContextTest.kt +++ b/dataforge-context/src/commonTest/kotlin/space/kscience/dataforge/context/ContextTest.kt @@ -2,7 +2,6 @@ package space.kscience.dataforge.context import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.appendLeft -import space.kscience.dataforge.names.toName import kotlin.test.Test import kotlin.test.assertEquals @@ -12,17 +11,16 @@ class ContextTest { override val tag get() = PluginTag("test") override fun content(target: String): Map { - return when(target){ - "test" -> listOf("a", "b", "c.d").associate { it.toName() to it.toName() } + return when (target) { + "test" -> listOf("a", "b", "c.d").associate { Name.parse(it) to Name.parse(it) } else -> emptyMap() } } - } @Test fun testPluginManager() { - val context = Global.buildContext{ + val context = Global.buildContext { name("test") plugin(DummyPlugin()) } diff --git a/dataforge-context/src/commonTest/kotlin/space/kscience/dataforge/properties/ItemPropertiesTest.kt b/dataforge-context/src/commonTest/kotlin/space/kscience/dataforge/properties/MetaPropertiesTest.kt similarity index 96% rename from dataforge-context/src/commonTest/kotlin/space/kscience/dataforge/properties/ItemPropertiesTest.kt rename to dataforge-context/src/commonTest/kotlin/space/kscience/dataforge/properties/MetaPropertiesTest.kt index df6a26f1..00b71673 100644 --- a/dataforge-context/src/commonTest/kotlin/space/kscience/dataforge/properties/ItemPropertiesTest.kt +++ b/dataforge-context/src/commonTest/kotlin/space/kscience/dataforge/properties/MetaPropertiesTest.kt @@ -14,7 +14,7 @@ internal class TestScheme : Scheme() { } @DFExperimental -class ItemPropertiesTest { +class MetaPropertiesTest { @Test fun testBinding() { val scheme = TestScheme.empty() 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 bffb5b67..7186504d 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 @@ -11,7 +11,6 @@ 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.toName import kotlin.reflect.KType import kotlin.reflect.typeOf @@ -95,7 +94,7 @@ internal class ReduceAction( val groupMeta = group.meta - val env = ActionEnv(groupName.toName(), groupMeta, meta) + val env = ActionEnv(Name.parse(groupName), groupMeta, meta) @OptIn(DFInternal::class) val res: Data = dataFlow.reduceToData( outputType, meta = groupMeta 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 fc22eb95..e8ed7961 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 @@ -12,7 +12,6 @@ import space.kscience.dataforge.meta.toMutableMeta import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.toName import kotlin.collections.set import kotlin.reflect.KType import kotlin.reflect.typeOf @@ -36,7 +35,7 @@ public class SplitBuilder(public val name: Name, public val me * @param rule the rule to transform fragment name and meta using */ public fun fragment(name: String, rule: FragmentRule.() -> Unit) { - fragments[name.toName()] = rule + fragments[Name.parse(name)] = rule } } diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/ActiveDataTree.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/ActiveDataTree.kt index 3c9ee902..8fdc01ab 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/ActiveDataTree.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/ActiveDataTree.kt @@ -115,4 +115,4 @@ public suspend inline fun ActiveDataTree.emit( public suspend inline fun ActiveDataTree.emit( name: String, noinline block: suspend ActiveDataTree.() -> Unit, -): Unit = emit(name.toName(), ActiveDataTree(typeOf(), block)) +): Unit = emit(Name.parse(name), ActiveDataTree(typeOf(), block)) diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSetBuilder.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSetBuilder.kt index 20e3ed1b..d966d8ae 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSetBuilder.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/DataSetBuilder.kt @@ -8,7 +8,6 @@ import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.plus -import space.kscience.dataforge.names.toName import kotlin.reflect.KType public interface DataSetBuilder { @@ -39,17 +38,17 @@ public interface DataSetBuilder { /** * Append data to node */ - public suspend infix fun String.put(data: Data): Unit = emit(toName(), data) + public suspend infix fun String.put(data: Data): Unit = emit(Name.parse(this), data) /** * Append node */ - public suspend infix fun String.put(dataSet: DataSet): Unit = emit(toName(), dataSet) + public suspend infix fun String.put(dataSet: DataSet): Unit = emit(Name.parse(this), dataSet) /** * Build and append node */ - public suspend infix fun String.put(block: suspend DataSetBuilder.() -> Unit): Unit = emit(toName(), block) + public suspend infix fun String.put(block: suspend DataSetBuilder.() -> Unit): Unit = emit(Name.parse(this), block) } private class SubSetBuilder( @@ -77,15 +76,15 @@ public suspend fun DataSetBuilder.emit(name: Name, block: suspend D public suspend fun DataSetBuilder.emit(name: String, data: Data) { - emit(name.toName(), data) + emit(Name.parse(name), data) } public suspend fun DataSetBuilder.emit(name: String, set: DataSet) { - this.emit(name.toName(), set) + this.emit(Name.parse(name), set) } public suspend fun DataSetBuilder.emit(name: String, block: suspend DataSetBuilder.() -> Unit): Unit = - this@emit.emit(name.toName(), block) + this@emit.emit(Name.parse(name), block) public suspend fun DataSetBuilder.emit(data: NamedData) { emit(data.name, data.data) @@ -115,17 +114,25 @@ public suspend inline fun DataSetBuilder.produce( /** * Emit a static data with the fixed value */ -public suspend inline fun DataSetBuilder.static(name: String, data: T, meta: Meta = Meta.EMPTY): Unit = +public suspend inline fun DataSetBuilder.static( + name: String, + data: T, + meta: Meta = Meta.EMPTY +): Unit = emit(name, Data.static(data, meta)) -public suspend inline fun DataSetBuilder.static(name: Name, data: T, meta: Meta = Meta.EMPTY): Unit = +public suspend inline fun DataSetBuilder.static( + name: Name, + data: T, + meta: Meta = Meta.EMPTY +): Unit = emit(name, Data.static(data, meta)) public suspend inline fun DataSetBuilder.static( name: String, data: T, mutableMeta: MutableMeta.() -> Unit, -): Unit = emit(name.toName(), Data.static(data, Meta(mutableMeta))) +): Unit = emit(Name.parse(name), Data.static(data, Meta(mutableMeta))) /** * Update data with given node data and meta with node meta. 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 cf852b17..87397f3e 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 @@ -57,7 +57,7 @@ public interface DataTree : DataSet { } } -public suspend fun DataSet.getData(name: String): Data? = getData(name.toName()) +public suspend fun DataSet.getData(name: String): Data? = getData(Name.parse(name)) /** * Get a [DataTreeItem] with given [name] or null if the item does not exist 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 2dd487e5..469594fe 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 @@ -5,7 +5,10 @@ import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.mapNotNull import space.kscience.dataforge.misc.DFExperimental -import space.kscience.dataforge.names.* +import space.kscience.dataforge.names.Name +import space.kscience.dataforge.names.isEmpty +import space.kscience.dataforge.names.plus +import space.kscience.dataforge.names.removeHeadOrNull import kotlin.reflect.KType @@ -64,7 +67,7 @@ public fun DataSet.branch(branchName: Name): DataSet = if (branc override val updates: Flow get() = this@branch.updates.mapNotNull { it.removeHeadOrNull(branchName) } } -public fun DataSet.branch(branchName: String): DataSet = this@branch.branch(branchName.toName()) +public fun DataSet.branch(branchName: String): DataSet = this@branch.branch(Name.parse(branchName)) @DFExperimental public suspend fun DataSet.rootData(): Data? = getData(Name.EMPTY) diff --git a/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/select.kt b/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/select.kt index b98331c2..7d311159 100644 --- a/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/select.kt +++ b/dataforge-data/src/jvmMain/kotlin/space/kscience/dataforge/data/select.kt @@ -6,7 +6,6 @@ import kotlinx.coroutines.flow.map import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.matches -import space.kscience.dataforge.names.toName import kotlin.reflect.KType import kotlin.reflect.full.isSubtypeOf import kotlin.reflect.typeOf @@ -61,4 +60,4 @@ public suspend fun DataSet<*>.selectOne(type: KType, name: Name): Name public suspend inline fun DataSet<*>.selectOne(name: Name): NamedData? = selectOne(typeOf(), name) public suspend inline fun DataSet<*>.selectOne(name: String): NamedData? = - selectOne(typeOf(), name.toName()) \ No newline at end of file + selectOne(typeOf(), Name.parse(name)) \ 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 186f1214..4bdadece 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 @@ -3,7 +3,7 @@ package space.kscience.dataforge.data import kotlinx.coroutines.* import kotlinx.coroutines.flow.collect import space.kscience.dataforge.misc.DFExperimental -import space.kscience.dataforge.names.toName +import space.kscience.dataforge.names.asName import kotlin.test.Test import kotlin.test.assertEquals @@ -72,7 +72,7 @@ internal class DataTreeBuilderTest { } } val rootNode = ActiveDataTree { - setAndObserve("sub".toName(), subNode) + setAndObserve("sub".asName(), subNode) } launch { 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 a715c66d..2d6376e3 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 @@ -10,12 +10,11 @@ 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.plus -import space.kscience.dataforge.names.toName private class PartDescriptor : Scheme() { var offset by int(0) var size by int(0) - var partMeta by item("meta".toName()) + var partMeta by item("meta".asName()) companion object : SchemeSpec(::PartDescriptor) { val MULTIPART_KEY = ENVELOPE_NODE_KEY + "multipart" 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 f0f2e6a4..d7ed301f 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 @@ -10,7 +10,7 @@ import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.string import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.toName + import kotlin.native.concurrent.ThreadLocal import kotlin.reflect.KClass @@ -23,7 +23,7 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) { public fun resolveIOFormat(item: Meta, type: KClass): IOFormat? { val key = item.string ?: item[NAME_KEY]?.string ?: error("Format name not defined") - val name = key.toName() + val name = Name.parse(key) return ioFormatFactories.find { it.name == name }?.let { @Suppress("UNCHECKED_CAST") if (it.type != type) error("Format type ${it.type} is not the same as requested type $type") @@ -52,7 +52,7 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) { public fun resolveEnvelopeFormat(item: Meta): EnvelopeFormat? { val name = item.string ?: item[NAME_KEY]?.string ?: error("Envelope format name not defined") val meta = item[META_KEY] ?: Meta.EMPTY - return resolveEnvelopeFormat(name.toName(), meta) + return resolveEnvelopeFormat(Name.parse(name), meta) } override fun content(target: String): Map { diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/TaggedEnvelopeFormat.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/TaggedEnvelopeFormat.kt index dfc5f233..8347118c 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/TaggedEnvelopeFormat.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/TaggedEnvelopeFormat.kt @@ -10,7 +10,7 @@ import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.string import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.plus -import space.kscience.dataforge.names.toName + /** * A streaming-friendly envelope format with a short binary tag. @@ -121,7 +121,7 @@ public class TaggedEnvelopeFormat( override fun invoke(meta: Meta, context: Context): EnvelopeFormat { val io = context.io - val metaFormatName = meta["name"].string?.toName() ?: JsonMetaFormat.name + val metaFormatName = meta["name"].string?.let { Name.parse(it) } ?: JsonMetaFormat.name //Check if appropriate factory exists io.metaFormatFactories.find { it.name == metaFormatName } ?: error("Meta format could not be resolved") diff --git a/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/MetaSerializerTest.kt b/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/MetaSerializerTest.kt index 332a647c..7aa95635 100644 --- a/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/MetaSerializerTest.kt +++ b/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/MetaSerializerTest.kt @@ -7,7 +7,6 @@ import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MetaSerializer import space.kscience.dataforge.meta.seal import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.toName import kotlin.test.Test import kotlin.test.assertEquals @@ -43,7 +42,7 @@ class MetaSerializerTest { @Test fun testNameSerialization() { - val name = "a.b.c".toName() + val name = Name.parse("a.b.c") val string = JSON_PRETTY.encodeToString(Name.serializer(), name) val restored = JSON_PLAIN.decodeFromString(Name.serializer(), string) assertEquals(name, restored) 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 e53ccc69..75c290cf 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 @@ -16,6 +16,13 @@ public interface MetaRepr { public fun toMeta(): Meta } +/** + * A container for meta nodes + */ +public fun interface MetaProvider { + public fun getMeta(name: Name): Meta? +} + /** * A meta node * TODO add documentation @@ -23,10 +30,12 @@ public interface MetaRepr { */ @Type(Meta.TYPE) @Serializable(MetaSerializer::class) -public interface Meta : MetaRepr { +public interface Meta : MetaRepr, MetaProvider { public val value: Value? public val items: Map + override fun getMeta(name: Name): Meta? = find(name) + override fun toMeta(): Meta = this override fun toString(): String @@ -66,6 +75,12 @@ public interface Meta : MetaRepr { public fun toString(meta: Meta): String = json.encodeToString(MetaSerializer, meta) public val EMPTY: Meta = SealedMeta(null, emptyMap()) + + private tailrec fun Meta.find(name: Name): Meta? = if (name.isEmpty()) { + this + } else { + items[name.firstOrNull()!!]?.find(name.cutFirst()) + } } } @@ -82,16 +97,12 @@ public operator fun Meta.get(token: NameToken): Meta? = items[token] * * If [name] is empty return current [Meta] */ -public tailrec operator fun Meta.get(name: Name): Meta? = if (name.isEmpty()) { - this -} else { - get(name.firstOrNull()!!)?.get(name.cutFirst()) -} +public operator fun Meta.get(name: Name): Meta? = getMeta(name) /** * Parse [Name] from [key] using full name notation and pass it to [Meta.get] */ -public operator fun Meta.get(key: String): Meta? = this[key.toName()] +public operator fun Meta.get(key: String): Meta? = this[Name.parse(key)] /** * Get all items matching given name. The index of the last element, if present is used as a [Regex], @@ -155,7 +166,7 @@ public tailrec operator fun > TypedMeta.get(name: Name): M? /** * Parse [Name] from [key] using full name notation and pass it to [TypedMeta.get] */ -public operator fun > TypedMeta.get(key: String): M? = this[key.toName()] +public operator fun > TypedMeta.get(key: String): M? = this[Name.parse(key)] /** @@ -197,7 +208,7 @@ public fun Meta.isEmpty(): Boolean = this === Meta.EMPTY || (value == null && it public fun > TypedMeta.getIndexed(name: Name): Map = (this as Meta).getIndexed(name) as Map -public fun > TypedMeta.getIndexed(name: String): Map = getIndexed(name.toName()) +public fun > TypedMeta.getIndexed(name: String): Map = getIndexed(Name.parse(name)) public val Meta?.string: String? get() = this?.value?.string 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 b0cdc3bb..b0905e88 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 @@ -10,8 +10,8 @@ import kotlin.properties.ReadOnlyProperty public typealias MetaDelegate = ReadOnlyProperty -public fun Meta.item(key: Name? = null): MetaDelegate = ReadOnlyProperty { _, property -> - get(key ?: property.name.asName()) +public fun MetaProvider.item(key: Name? = null): MetaDelegate = ReadOnlyProperty { _, property -> + getMeta(key ?: property.name.asName()) } //TODO add caching for sealed nodes @@ -50,62 +50,62 @@ public fun MetaDelegate.convert( /** * A property delegate that uses custom key */ -public fun Meta.value(key: Name? = null): ReadOnlyProperty = +public fun MetaProvider.value(key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.value) -public fun Meta.string(key: Name? = null): ReadOnlyProperty = +public fun MetaProvider.string(key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.string) -public fun Meta.boolean(key: Name? = null): ReadOnlyProperty = +public fun MetaProvider.boolean(key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.boolean) -public fun Meta.number(key: Name? = null): ReadOnlyProperty = +public fun MetaProvider.number(key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.number) -public fun Meta.double(key: Name? = null): ReadOnlyProperty = +public fun MetaProvider.double(key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.double) -public fun Meta.float(key: Name? = null): ReadOnlyProperty = +public fun MetaProvider.float(key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.float) -public fun Meta.int(key: Name? = null): ReadOnlyProperty = +public fun MetaProvider.int(key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.int) -public fun Meta.long(key: Name? = null): ReadOnlyProperty = +public fun MetaProvider.long(key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.long) -public fun Meta.node(key: Name? = null): ReadOnlyProperty = +public fun MetaProvider.node(key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.meta) -public fun Meta.string(default: String, key: Name? = null): ReadOnlyProperty = +public fun MetaProvider.string(default: String, key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.string) { default } -public fun Meta.boolean(default: Boolean, key: Name? = null): ReadOnlyProperty = +public fun MetaProvider.boolean(default: Boolean, key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.boolean) { default } -public fun Meta.number(default: Number, key: Name? = null): ReadOnlyProperty = +public fun MetaProvider.number(default: Number, key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.number) { default } -public fun Meta.double(default: Double, key: Name? = null): ReadOnlyProperty = +public fun MetaProvider.double(default: Double, key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.double) { default } -public fun Meta.float(default: Float, key: Name? = null): ReadOnlyProperty = +public fun MetaProvider.float(default: Float, key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.float) { default } -public fun Meta.int(default: Int, key: Name? = null): ReadOnlyProperty = +public fun MetaProvider.int(default: Int, key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.int) { default } -public fun Meta.long(default: Long, key: Name? = null): ReadOnlyProperty = +public fun MetaProvider.long(default: Long, key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.long) { default } -public inline fun > Meta.enum(default: E, key: Name? = null): ReadOnlyProperty = +public inline fun > MetaProvider.enum(default: E, key: Name? = null): ReadOnlyProperty = item(key).convert(MetaConverter.enum()) { default } -public fun Meta.string(key: Name? = null, default: () -> String): ReadOnlyProperty = +public fun MetaProvider.string(key: Name? = null, default: () -> String): ReadOnlyProperty = item(key).convert(MetaConverter.string, default) -public fun Meta.boolean(key: Name? = null, default: () -> Boolean): ReadOnlyProperty = +public fun MetaProvider.boolean(key: Name? = null, default: () -> Boolean): ReadOnlyProperty = item(key).convert(MetaConverter.boolean, default) -public fun Meta.number(key: Name? = null, default: () -> Number): ReadOnlyProperty = +public fun MetaProvider.number(key: Name? = null, default: () -> Number): ReadOnlyProperty = item(key).convert(MetaConverter.number, default) 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 da822aa0..ebb1501a 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 @@ -16,13 +16,17 @@ import kotlin.jvm.Synchronized @DslMarker public annotation class MetaBuilder +public interface MutableMetaProvider : MetaProvider { + public fun setMeta(name: Name, node: Meta?) +} + /** * Mutable variant of [Meta] * TODO documentation */ @Serializable(MutableMetaSerializer::class) @MetaBuilder -public interface MutableMeta : Meta { +public interface MutableMeta : Meta, MutableMetaProvider { override val items: Map @@ -36,6 +40,14 @@ public interface MutableMeta : Meta { */ public operator fun set(name: Name, meta: Meta) + override fun setMeta(name: Name, node: Meta?) { + if (node == null) { + remove(name) + } else { + set(name, node) + } + } + /** * Remove a node at a given [name] if it is present */ @@ -85,47 +97,47 @@ public interface MutableMeta : Meta { } public infix fun String.put(meta: Meta) { - toName() put meta + Name.parse(this) put meta } public infix fun String.put(value: Value?) { - set(toName(), value) + set(Name.parse(this), value) } public infix fun String.put(string: String) { - set(toName(), string.asValue()) + set(Name.parse(this), string.asValue()) } public infix fun String.put(number: Number) { - set(toName(), number.asValue()) + set(Name.parse(this), number.asValue()) } public infix fun String.put(boolean: Boolean) { - set(toName(), boolean.asValue()) + set(Name.parse(this), boolean.asValue()) } public infix fun String.put(enum: Enum<*>) { - set(toName(), EnumValue(enum)) + set(Name.parse(this), EnumValue(enum)) } public infix fun String.put(array: DoubleArray) { - set(toName(), array.asValue()) + set(Name.parse(this), array.asValue()) } public infix fun String.put(repr: MetaRepr) { - toName() put repr.toMeta() + Name.parse(this) put repr.toMeta() } public infix fun String.put(iterable: Iterable) { - setIndexed(toName(), iterable) + setIndexed(Name.parse(this), iterable) } public infix fun String.put(builder: MutableMeta.() -> Unit) { - set(toName(), MutableMeta(builder)) + set(Name.parse(this), MutableMeta(builder)) } } -public fun MutableMeta.getOrCreate(string: String): MutableMeta = getOrCreate(string.toName()) +public fun MutableMeta.getOrCreate(key: String): MutableMeta = getOrCreate(Name.parse(key)) @Serializable(MutableMetaSerializer::class) public interface MutableTypedMeta> : TypedMeta, MutableMeta { @@ -138,47 +150,37 @@ public interface MutableTypedMeta> : TypedMeta, Mutab override fun getOrCreate(name: Name): M } -public fun > M.getOrCreate(string: String): M = getOrCreate(string.toName()) +public fun > M.getOrCreate(key: String): M = getOrCreate(Name.parse(key)) -public fun MutableMeta.remove(name: String){ - remove(name.toName()) +public fun MutableMeta.remove(key: String) { + remove(Name.parse(key)) } // node setters -public operator fun MutableMeta.set(name: NameToken, value: Meta): Unit = set(name.asName(), value) -public operator fun MutableMeta.set(name: Name, meta: Meta?): Unit { - if (meta == null) { - remove(name) - } else { - set(name, meta) - } -} - -public operator fun MutableMeta.set(key: String, meta: Meta?): Unit { - set(key.toName(), meta) -} +public operator fun MutableMetaProvider.set(Key: NameToken, value: Meta): Unit = setMeta(Key.asName(), value) +public operator fun MutableMetaProvider.set(key: String, value: Meta): Unit = setMeta(Name.parse(key), value) //value setters public operator fun MutableMeta.set(name: NameToken, value: Value?): Unit = set(name.asName(), value) -public operator fun MutableMeta.set(key: String, value: Value?): Unit = set(key.toName(), value) +public operator fun MutableMeta.set(key: String, value: Value?): Unit = set(Name.parse(key), value) public operator fun MutableMeta.set(name: Name, value: String): Unit = set(name, value.asValue()) public operator fun MutableMeta.set(name: NameToken, value: String): Unit = set(name.asName(), value.asValue()) -public operator fun MutableMeta.set(key: String, value: String): Unit = set(key.toName(), value.asValue()) +public operator fun MutableMeta.set(key: String, value: String): Unit = set(Name.parse(key), value.asValue()) public operator fun MutableMeta.set(name: Name, value: Boolean): Unit = set(name, value.asValue()) public operator fun MutableMeta.set(name: NameToken, value: Boolean): Unit = set(name.asName(), value.asValue()) -public operator fun MutableMeta.set(key: String, value: Boolean): Unit = set(key.toName(), value.asValue()) +public operator fun MutableMeta.set(key: String, value: Boolean): Unit = set(Name.parse(key), value.asValue()) public operator fun MutableMeta.set(name: Name, value: Number): Unit = set(name, value.asValue()) public operator fun MutableMeta.set(name: NameToken, value: Number): Unit = set(name.asName(), value.asValue()) -public operator fun MutableMeta.set(key: String, value: Number): Unit = set(key.toName(), value.asValue()) +public operator fun MutableMeta.set(key: String, value: Number): Unit = set(Name.parse(key), value.asValue()) public operator fun MutableMeta.set(name: Name, value: List): Unit = set(name, value.asValue()) public operator fun MutableMeta.set(name: NameToken, value: List): Unit = set(name.asName(), value.asValue()) -public operator fun MutableMeta.set(key: String, value: List): Unit = set(key.toName(), value.asValue()) +public operator fun MutableMeta.set(key: String, value: List): Unit = set(Name.parse(key), value.asValue()) //public fun MutableMeta.set(key: String, index: String, value: Value?): Unit = // set(key.toName().withIndex(index), value) @@ -218,8 +220,8 @@ public fun MutableMeta.setIndexed( public operator fun MutableMeta.set(name: Name, metas: Iterable): Unit = setIndexed(name, metas) -public operator fun MutableMeta.set(name: String, metas: Iterable): Unit = - setIndexed(name.toName(), metas) +public operator fun MutableMeta.set(key: String, metas: Iterable): Unit = + setIndexed(Name.parse(key), metas) /** @@ -396,13 +398,13 @@ public fun MutableMeta.append(name: Name, meta: Meta) { } @DFExperimental -public fun MutableMeta.append(name: String, meta: Meta): Unit = append(name.toName(), meta) +public fun MutableMeta.append(key: String, meta: Meta): Unit = append(Name.parse(key), meta) @DFExperimental public fun MutableMeta.append(name: Name, value: Value): Unit = append(name, Meta(value)) @DFExperimental -public fun MutableMeta.append(name: String, value: Value): Unit = append(name.toName(), value) +public fun MutableMeta.append(key: String, value: Value): Unit = append(Name.parse(key), value) ///** // * Apply existing node with given [builder] or create a new element with it. @@ -443,8 +445,9 @@ public inline fun Meta.copy(block: MutableMeta.() -> Unit = {}): Meta = toMutableMeta().apply(block) -private class MutableMetaWithDefault(val source: MutableMeta, val default: Meta, val name: Name) : - MutableMeta by source { +private class MutableMetaWithDefault( + val source: MutableMeta, val default: Meta, val name: Name +) : MutableMeta by source { override val items: Map get() = (source.items.keys + default.items.keys).associateWith { MutableMetaWithDefault(source, default, name + it) @@ -456,6 +459,8 @@ private class MutableMetaWithDefault(val source: MutableMeta, val default: Meta, source[name] = value } + override fun getMeta(name: Name): Meta? = source.getMeta(name) ?: default.getMeta(name) + override fun toString(): String = Meta.toString(this) override fun equals(other: Any?): Boolean = Meta.equals(this, other as? Meta) override fun hashCode(): Int = Meta.hashCode(this) 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 3ff71289..44cba048 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 @@ -11,14 +11,14 @@ import kotlin.reflect.KProperty public typealias MutableMetaDelegate = ReadWriteProperty -public fun MutableMeta.item(key: Name? = null): MutableMetaDelegate = object : MutableMetaDelegate { +public fun MutableMetaProvider.item(key: Name? = null): MutableMetaDelegate = object : MutableMetaDelegate { override fun getValue(thisRef: Any?, property: KProperty<*>): Meta? { - return get(key ?: property.name.asName()) + return getMeta(key ?: property.name.asName()) } override fun setValue(thisRef: Any?, property: KProperty<*>, value: Meta?) { val name = key ?: property.name.asName() - set(name, value) + setMeta(name, value) } } @@ -74,40 +74,40 @@ public fun MutableMetaDelegate.convert( /** * A property delegate that uses custom key */ -public fun MutableMeta.value(key: Name? = null): ReadWriteProperty = +public fun MutableMetaProvider.value(key: Name? = null): ReadWriteProperty = item(key).convert(MetaConverter.value) -public fun MutableMeta.string(key: Name? = null): ReadWriteProperty = +public fun MutableMetaProvider.string(key: Name? = null): ReadWriteProperty = item(key).convert(MetaConverter.string) -public fun MutableMeta.boolean(key: Name? = null): ReadWriteProperty = +public fun MutableMetaProvider.boolean(key: Name? = null): ReadWriteProperty = item(key).convert(MetaConverter.boolean) -public fun MutableMeta.number(key: Name? = null): ReadWriteProperty = +public fun MutableMetaProvider.number(key: Name? = null): ReadWriteProperty = item(key).convert(MetaConverter.number) -public fun MutableMeta.string(default: String, key: Name? = null): ReadWriteProperty = +public fun MutableMetaProvider.string(default: String, key: Name? = null): ReadWriteProperty = item(key).convert(MetaConverter.string) { default } -public fun MutableMeta.boolean(default: Boolean, key: Name? = null): ReadWriteProperty = +public fun MutableMetaProvider.boolean(default: Boolean, key: Name? = null): ReadWriteProperty = item(key).convert(MetaConverter.boolean) { default } -public fun MutableMeta.number(default: Number, key: Name? = null): ReadWriteProperty = +public fun MutableMetaProvider.number(default: Number, key: Name? = null): ReadWriteProperty = item(key).convert(MetaConverter.number) { default } -public fun MutableMeta.value(key: Name? = null, default: () -> Value): ReadWriteProperty = +public fun MutableMetaProvider.value(key: Name? = null, default: () -> Value): ReadWriteProperty = item(key).convert(MetaConverter.value, default) -public fun MutableMeta.string(key: Name? = null, default: () -> String): ReadWriteProperty = +public fun MutableMetaProvider.string(key: Name? = null, default: () -> String): ReadWriteProperty = item(key).convert(MetaConverter.string, default) -public fun MutableMeta.boolean(key: Name? = null, default: () -> Boolean): ReadWriteProperty = +public fun MutableMetaProvider.boolean(key: Name? = null, default: () -> Boolean): ReadWriteProperty = item(key).convert(MetaConverter.boolean, default) -public fun MutableMeta.number(key: Name? = null, default: () -> Number): ReadWriteProperty = +public fun MutableMetaProvider.number(key: Name? = null, default: () -> Number): ReadWriteProperty = item(key).convert(MetaConverter.number, default) -public inline fun > MutableMeta.enum( +public inline fun > MutableMetaProvider.enum( default: E, key: Name? = null, ): ReadWriteProperty = @@ -115,37 +115,37 @@ public inline fun > MutableMeta.enum( /* Number delegates */ -public fun MutableMeta.int(key: Name? = null): ReadWriteProperty = +public fun MutableMetaProvider.int(key: Name? = null): ReadWriteProperty = item(key).convert(MetaConverter.int) -public fun MutableMeta.double(key: Name? = null): ReadWriteProperty = +public fun MutableMetaProvider.double(key: Name? = null): ReadWriteProperty = item(key).convert(MetaConverter.double) -public fun MutableMeta.long(key: Name? = null): ReadWriteProperty = +public fun MutableMetaProvider.long(key: Name? = null): ReadWriteProperty = item(key).convert(MetaConverter.long) -public fun MutableMeta.float(key: Name? = null): ReadWriteProperty = +public fun MutableMetaProvider.float(key: Name? = null): ReadWriteProperty = item(key).convert(MetaConverter.float) /* Safe number delegates*/ -public fun MutableMeta.int(default: Int, key: Name? = null): ReadWriteProperty = +public fun MutableMetaProvider.int(default: Int, key: Name? = null): ReadWriteProperty = item(key).convert(MetaConverter.int) { default } -public fun MutableMeta.double(default: Double, key: Name? = null): ReadWriteProperty = +public fun MutableMetaProvider.double(default: Double, key: Name? = null): ReadWriteProperty = item(key).convert(MetaConverter.double) { default } -public fun MutableMeta.long(default: Long, key: Name? = null): ReadWriteProperty = +public fun MutableMetaProvider.long(default: Long, key: Name? = null): ReadWriteProperty = item(key).convert(MetaConverter.long) { default } -public fun MutableMeta.float(default: Float, key: Name? = null): ReadWriteProperty = +public fun MutableMetaProvider.float(default: Float, key: Name? = null): ReadWriteProperty = item(key).convert(MetaConverter.float) { default } /* Extra delegates for special cases */ -public fun MutableMeta.stringList( +public fun MutableMetaProvider.stringList( vararg default: String, key: Name? = null, ): ReadWriteProperty> = item(key).convert( @@ -153,14 +153,14 @@ public fun MutableMeta.stringList( writer = { Meta(it.map { str -> str.asValue() }.asValue()) } ) -public fun MutableMeta.stringList( +public fun MutableMetaProvider.stringList( key: Name? = null, ): ReadWriteProperty?> = item(key).convert( reader = { it?.stringList }, writer = { it?.map { str -> str.asValue() }?.asValue()?.let { Meta(it) } } ) -public fun MutableMeta.numberList( +public fun MutableMetaProvider.numberList( vararg default: Number, key: Name? = null, ): ReadWriteProperty> = item(key).convert( @@ -171,7 +171,7 @@ public fun MutableMeta.numberList( /* A special delegate for double arrays */ -public fun MutableMeta.doubleArray( +public fun MutableMetaProvider.doubleArray( vararg default: Double, key: Name? = null, ): ReadWriteProperty = item(key).convert( @@ -179,7 +179,7 @@ public fun MutableMeta.doubleArray( writer = { Meta(DoubleArrayValue(it)) } ) -public fun MutableMeta.listValue( +public fun MutableMetaProvider.listValue( key: Name? = null, writer: (T) -> Value = { Value.of(it) }, reader: (Value) -> T, 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 5ea37757..9e45a150 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 @@ -1,9 +1,6 @@ package space.kscience.dataforge.meta -import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.NameToken -import space.kscience.dataforge.names.asName -import space.kscience.dataforge.names.startsWith +import space.kscience.dataforge.names.* import space.kscience.dataforge.values.Value import kotlin.jvm.Synchronized import kotlin.reflect.KProperty1 @@ -57,6 +54,8 @@ private class ObservableMetaWrapper( override val items: Map get() = origin.items.mapValues { ObservableMetaWrapper(it.value) } + override fun getMeta(name: Name): Meta? = origin.getMeta(name) + override var value: Value? get() = origin.value set(value) { @@ -86,7 +85,10 @@ private class ObservableMetaWrapper( } override fun attach(name: Name, node: ObservableMutableMeta) { - TODO("Not yet implemented") + set(name, node) + node.onChange(this) { changeName -> + setMeta(name + changeName, node[changeName]) + } } } @@ -104,14 +106,14 @@ public fun MutableMeta.asObservable(): ObservableMutableMeta = * * Optional [owner] property is used for */ -public fun O.useProperty( - property: KProperty1, +public fun S.useProperty( + property: KProperty1, owner: Any? = null, - callBack: O.(T) -> Unit, + callBack: S.(T) -> Unit, ) { //Pass initial value. callBack(property.get(this)) - onChange(owner) { name -> + meta.onChange(owner) { name -> if (name.startsWith(property.name.asName())) { callBack(property.get(this@useProperty)) } 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 55fb2360..10f3d038 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 @@ -2,35 +2,24 @@ package space.kscience.dataforge.meta import space.kscience.dataforge.meta.descriptors.* import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.NameToken -import space.kscience.dataforge.values.Value /** * A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [Specification]. - * Default item provider and [NodeDescriptor] are optional + * Default item provider and [MetaDescriptor] are optional */ -public open class Scheme( - source: MutableMeta = MutableMeta() -) : Described, MutableMeta, ObservableMeta, Meta by source { +public open class Scheme : Described, MetaRepr, MutableMetaProvider { - private var source = source.asObservable() + public var meta: ObservableMutableMeta = MutableMeta() + private set final override var descriptor: MetaDescriptor? = null internal set - override var value: Value? - get() = source.value - set(value) { - source.value = value - } - - override val items: Map get() = source.items - internal fun wrap( items: MutableMeta, preserveDefault: Boolean = false ) { - this.source = (if (preserveDefault) items.withDefault(this.source) else items).asObservable() + meta = (if (preserveDefault) items.withDefault(meta.seal()) else items).asObservable() } /** @@ -41,35 +30,17 @@ public open class Scheme( return descriptor?.validate(meta) ?: true } - /** - * Set a configurable property - */ - override fun set(name: Name, meta: Meta) { - val oldItem = source[name] - if (oldItem != meta) { - if (validate(name, meta)) { - source[name] = meta - } else { - error("Validation failed for property $name with value $meta") - } + override fun getMeta(name: Name): Meta? = meta.getMeta(name) + + override fun setMeta(name: Name, node: Meta?) { + if (validate(name, meta)) { + meta.setMeta(name, node) + } else { + error("Validation failed for node $node at $name") } } - override fun toMeta(): Laminate = Laminate(source, descriptor?.defaultNode) - - override fun remove(name: Name) { - source.remove(name) - } - - override fun getOrCreate(name: Name): MutableMeta = source.getOrCreate(name) - - override fun onChange(owner: Any?, callback: Meta.(name: Name) -> Unit) { - source.onChange(owner ?: this, callback) - } - - override fun removeListener(owner: Any?) { - source.removeListener(owner ?: this) - } + override fun toMeta(): Laminate = Laminate(meta, descriptor?.defaultNode) } /** diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Specification.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Specification.kt index 9c035fc9..44263d01 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Specification.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Specification.kt @@ -77,6 +77,11 @@ public fun MutableMeta.spec( } } +public fun Scheme.spec( + spec: Specification, + key: Name? = null, +): ReadWriteProperty = meta.spec(spec, key) + /** * A delegate that uses a [Specification] to wrap a list of child providers. * If children are mutable, the changes in list elements are reflected on them. diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptor.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptor.kt index d7d640ee..2a519173 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptor.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptor.kt @@ -43,7 +43,7 @@ public operator fun MetaDescriptor.get(name: Name): MetaDescriptor? = when (name else -> get(name.firstOrNull()!!.asName())?.get(name.cutFirst()) } -public operator fun MetaDescriptor.get(name: String): MetaDescriptor? = get(name.toName()) +public operator fun MetaDescriptor.get(name: String): MetaDescriptor? = get(Name.parse(name)) /** * A node constructed of default values for this descriptor and its children 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 0c25793c..38c256e0 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 @@ -4,10 +4,22 @@ import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.set -import space.kscience.dataforge.names.* +import space.kscience.dataforge.names.Name +import space.kscience.dataforge.names.cutFirst +import space.kscience.dataforge.names.first +import space.kscience.dataforge.names.length import space.kscience.dataforge.values.Value import space.kscience.dataforge.values.ValueType import space.kscience.dataforge.values.asValue +import kotlin.collections.List +import kotlin.collections.MutableMap +import kotlin.collections.emptyList +import kotlin.collections.getOrPut +import kotlin.collections.hashMapOf +import kotlin.collections.listOf +import kotlin.collections.map +import kotlin.collections.mapValues +import kotlin.collections.set public class MetaDescriptorBuilder { public var info: String? = null @@ -67,7 +79,7 @@ public class MetaDescriptorBuilder { } public fun MetaDescriptorBuilder.item(name: String, block: MetaDescriptorBuilder.() -> Unit) { - item(name.toName(), block) + item(Name.parse(name), block) } public fun MetaDescriptor(block: MetaDescriptorBuilder.() -> Unit): MetaDescriptor = @@ -94,7 +106,7 @@ public fun MetaDescriptorBuilder.value( vararg additionalTypes: ValueType, block: MetaDescriptorBuilder.() -> Unit ) { - value(name.toName(), type, additionalTypes = additionalTypes, block) + value(Name.parse(name), type, additionalTypes = additionalTypes, block) } /** @@ -108,7 +120,7 @@ public fun MetaDescriptorBuilder.node(name: Name, block: MetaDescriptorBuilder.( } public fun MetaDescriptorBuilder.node(name: String, block: MetaDescriptorBuilder.() -> Unit) { - node(name.toName(), block) + node(Name.parse(name), block) } public inline fun > MetaDescriptorBuilder.enum( diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/mapMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/mapMeta.kt index a2190457..6074cb8a 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/mapMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/mapMeta.kt @@ -3,7 +3,7 @@ package space.kscience.dataforge.meta import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.descriptors.get import space.kscience.dataforge.misc.DFExperimental -import space.kscience.dataforge.names.toName +import space.kscience.dataforge.names.Name import space.kscience.dataforge.values.ListValue import space.kscience.dataforge.values.Value @@ -28,7 +28,7 @@ public fun Meta.toMap(descriptor: MetaDescriptor? = null): Map = b /** * Convert map of maps to meta. This method will recognize [Meta], [Map] and [List] of all mentioned above as value. - * All other values will be converted to values. + * All other values will be converted to [Value]. */ @DFExperimental public fun Map.toMeta(descriptor: MetaDescriptor? = null): Meta = Meta { @@ -45,7 +45,7 @@ public fun Map.toMeta(descriptor: MetaDescriptor? = null): Meta = if (items.all { it.isLeaf }) { set(key, ListValue(items.map { it.value!! })) } else { - setIndexedItems(key.toName(), value.map { toMeta(it) }) + setIndexedItems(Name.parse(key), value.map { toMeta(it) }) } } else { set(key, toMeta(value)) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/transformations/MetaTransformation.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/transformations/MetaTransformation.kt index 138deb73..b54f486a 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/transformations/MetaTransformation.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/transformations/MetaTransformation.kt @@ -42,7 +42,7 @@ public data class KeepTransformationRule(val selector: (Name) -> Boolean) : meta.nodeSequence().map { it.first }.filter(selector) override fun transformItem(name: Name, item: Meta?, target: MutableMeta) { - if (selector(name)) target.set(name, item) + if (selector(name)) target.setMeta(name, item) } } @@ -174,7 +174,7 @@ public class MetaTransformationBuilder { public fun keep(regex: String) { transformations.add( RegexItemTransformationRule(regex.toRegex()) { name, _, Meta -> - set(name, Meta) + setMeta(name, Meta) }) } @@ -184,7 +184,7 @@ public class MetaTransformationBuilder { public fun move(from: Name, to: Name, operation: (Meta?) -> Meta? = { it }) { transformations.add( SingleItemTransformationRule(from) { _, item -> - set(to, operation(item)) + setMeta(to, operation(item)) } ) } 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 cca67f58..ca0a7ce6 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 @@ -47,6 +47,61 @@ public class Name(public val tokens: List) { public val MATCH_ALL_TOKEN: NameToken = NameToken("**") public val EMPTY: Name = Name(emptyList()) + + /** + * Convert a [String] to name parsing it and extracting name tokens and index syntax. + * This operation is rather heavy so it should be used with care in high performance code. + */ + public fun parse(string: String): Name{ + if (string.isBlank()) return Name.EMPTY + val tokens = sequence { + var bodyBuilder = StringBuilder() + var queryBuilder = StringBuilder() + var bracketCount: Int = 0 + var escape: Boolean = false + fun queryOn() = bracketCount > 0 + + for (it in string) { + when { + escape -> { + if (queryOn()) { + queryBuilder.append(it) + } else { + bodyBuilder.append(it) + } + escape = false + } + it == '\\' -> { + escape = true + } + queryOn() -> { + when (it) { + '[' -> bracketCount++ + ']' -> bracketCount-- + } + if (queryOn()) queryBuilder.append(it) + } + else -> when (it) { + '.' -> { + val query = if (queryBuilder.isEmpty()) null else queryBuilder.toString() + yield(NameToken(bodyBuilder.toString(), query)) + bodyBuilder = StringBuilder() + queryBuilder = StringBuilder() + } + '[' -> bracketCount++ + ']' -> error("Syntax error: closing bracket ] not have not matching open bracket") + else -> { + if (queryBuilder.isNotEmpty()) error("Syntax error: only name end and name separator are allowed after index") + bodyBuilder.append(it) + } + } + } + } + val query = if (queryBuilder.isEmpty()) null else queryBuilder.toString() + yield(NameToken(bodyBuilder.toString(), query)) + } + return Name(tokens.toList()) + } } } @@ -80,61 +135,6 @@ public fun Name.firstOrNull(): NameToken? = tokens.firstOrNull() public fun Name.first(): NameToken = tokens.first() -/** - * Convert a [String] to name parsing it and extracting name tokens and index syntax. - * This operation is rather heavy so it should be used with care in high performance code. - */ -public fun String.toName(): Name { - if (isBlank()) return Name.EMPTY - val tokens = sequence { - var bodyBuilder = StringBuilder() - var queryBuilder = StringBuilder() - var bracketCount: Int = 0 - var escape: Boolean = false - fun queryOn() = bracketCount > 0 - - for (it in this@toName) { - when { - escape -> { - if (queryOn()) { - queryBuilder.append(it) - } else { - bodyBuilder.append(it) - } - escape = false - } - it == '\\' -> { - escape = true - } - queryOn() -> { - when (it) { - '[' -> bracketCount++ - ']' -> bracketCount-- - } - if (queryOn()) queryBuilder.append(it) - } - else -> when (it) { - '.' -> { - val query = if (queryBuilder.isEmpty()) null else queryBuilder.toString() - yield(NameToken(bodyBuilder.toString(), query)) - bodyBuilder = StringBuilder() - queryBuilder = StringBuilder() - } - '[' -> bracketCount++ - ']' -> error("Syntax error: closing bracket ] not have not matching open bracket") - else -> { - if (queryBuilder.isNotEmpty()) error("Syntax error: only name end and name separator are allowed after index") - bodyBuilder.append(it) - } - } - } - } - val query = if (queryBuilder.isEmpty()) null else queryBuilder.toString() - yield(NameToken(bodyBuilder.toString(), query)) - } - return Name(tokens.toList()) -} - /** * Convert the [String] to a [Name] by simply wrapping it in a single name token without parsing. * The input string could contain dots and braces, but they are just escaped, not parsed. @@ -145,7 +145,7 @@ public operator fun NameToken.plus(other: Name): Name = Name(listOf(this) + othe public operator fun Name.plus(other: Name): Name = Name(this.tokens + other.tokens) -public operator fun Name.plus(other: String): Name = this + other.toName() +public operator fun Name.plus(other: String): Name = this + Name.parse(other) public operator fun Name.plus(other: NameToken): Name = Name(tokens + other) @@ -174,8 +174,8 @@ public fun Name.withIndex(index: String): Name { * Fast [String]-based accessor for item map */ public operator fun Map.get(body: String, query: String? = null): T? = get(NameToken(body, query)) -public operator fun Map.get(name: String): T? = get(name.toName()) -public operator fun MutableMap.set(name: String, value: T): Unit = set(name.toName(), value) +public operator fun Map.get(name: String): T? = get(Name.parse(name)) +public operator fun MutableMap.set(name: String, value: T): Unit = set(Name.parse(name), value) /* Name comparison operations */ diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/NameSerializer.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/NameSerializer.kt index 9d6b9988..077a8d82 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/NameSerializer.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/NameSerializer.kt @@ -12,7 +12,7 @@ public object NameSerializer : KSerializer { PrimitiveSerialDescriptor("space.kscience.dataforge.names.Name", PrimitiveKind.STRING) override fun deserialize(decoder: Decoder): Name { - return decoder.decodeString().toName() + return Name.parse(decoder.decodeString()) } override fun serialize(encoder: Encoder, value: Name) { @@ -25,7 +25,7 @@ public object NameTokenSerializer: KSerializer { PrimitiveSerialDescriptor("space.kscience.dataforge.names.NameToken", PrimitiveKind.STRING) override fun deserialize(decoder: Decoder): NameToken { - return decoder.decodeString().toName().firstOrNull()!! + return Name.parse(decoder.decodeString()).firstOrNull()!! } override fun serialize( diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/nameMatcher.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/nameMatcher.kt index 7abcdc4f..fdcda953 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/nameMatcher.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/names/nameMatcher.kt @@ -44,4 +44,4 @@ public fun Name.matches(pattern: Name): Boolean = when { } @OptIn(DFExperimental::class) -public fun Name.matches(pattern: String): Boolean = matches(pattern.toName()) \ No newline at end of file +public fun Name.matches(pattern: String): Boolean = matches(Name.parse(pattern)) \ No newline at end of file diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MetaDelegateTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MetaDelegateTest.kt index dfdf722d..3456494f 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MetaDelegateTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MetaDelegateTest.kt @@ -30,7 +30,7 @@ class MetaDelegateTest { fun delegateTest() { val testObject = TestScheme.empty() - testObject.set("myValue","theString".asValue()) + testObject.meta["myValue"] = "theString".asValue() testObject.enumValue = TestEnum.NO testObject.inner = InnerScheme { innerValue = "ddd" } diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/names/NameMatchTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/names/NameMatchTest.kt index 00131068..2218b55c 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/names/NameMatchTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/names/NameMatchTest.kt @@ -10,7 +10,7 @@ import kotlin.test.assertTrue class NameMatchTest { @Test fun matchWildCards() { - val theName = "a.b.c.d".toName() + val theName = Name.parse("a.b.c.d") assertTrue { theName.matches("a.b.**") } assertTrue { theName.matches("a.*.c.**") } assertTrue { theName.matches("**.d") } @@ -22,7 +22,7 @@ class NameMatchTest { @Test fun matchPattern() { - val theName = "a[dd+2].b[13].c.d[\"d\"]".toName() + val theName = Name.parse("a[dd+2].b[13].c.d[\"d\"]") assertTrue { theName.matches("a[.*].b[.*].c[.*].d[.*]") } assertTrue { theName.matches("a[.*].b[.*].c.d[.*]") } assertFalse { theName.matches("a[.*].b[.*].*.d") } diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/names/NameSerializationTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/names/NameSerializationTest.kt index 1fe130cf..42f42cc2 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/names/NameSerializationTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/names/NameSerializationTest.kt @@ -9,7 +9,7 @@ class NameSerializationTest { @Test fun testNameSerialization() { - val name = "aaa.bbb.ccc".toName() + val name = Name.parse("aaa.bbb.ccc") val json = Json.encodeToJsonElement(Name.serializer(), name) println(json) val reconstructed = Json.decodeFromJsonElement(Name.serializer(), json) 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 1ca681bd..decc1b3a 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 @@ -8,22 +8,22 @@ import kotlin.test.assertTrue class NameTest { @Test fun simpleName() { - val name = "token1.token2.token3".toName() + val name = Name.parse("token1.token2.token3") assertEquals("token2", name[1].toString()) } @Test fun equalityTest() { - val name1 = "token1.token2[2].token3".toName() - val name2 = "token1".toName() + "token2[2].token3" + val name1 = Name.parse("token1.token2[2].token3") + val name2 = "token1".asName() + "token2[2].token3" assertEquals(name1, name2) } @Test fun comparisonTest(){ - val name1 = "token1.token2.token3".toName() - val name2 = "token1.token2".toName() - val name3 = "token3".toName() + val name1 = Name.parse("token1.token2.token3") + val name2 = Name.parse("token1.token2") + val name3 = Name.parse("token3") assertTrue { name1.startsWith(name2) } assertTrue { name1.endsWith(name3) } assertFalse { name1.startsWith(name3) } @@ -31,11 +31,11 @@ class NameTest { @Test fun escapeTest(){ - val escapedName = "token\\.one.token2".toName() + val escapedName = Name.parse("token\\.one.token2") val unescapedName = "token\\.one.token2".asName() assertEquals(2, escapedName.length) assertEquals(1, unescapedName.length) - assertEquals(escapedName, escapedName.toString().toName()) + assertEquals(escapedName, Name.parse(escapedName.toString())) } } \ 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 32a3ab57..6f3db0aa 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 @@ -1,6 +1,5 @@ package space.kscience.dataforge.meta -import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.NameToken import space.kscience.dataforge.values.Value import space.kscience.dataforge.values.asValue @@ -8,7 +7,6 @@ import space.kscience.dataforge.values.isList //TODO add Meta wrapper for dynamic -@DFExperimental public fun Value.toDynamic(): dynamic { return if (isList()) { list.map { it.toDynamic() }.toTypedArray().asDynamic() @@ -20,7 +18,6 @@ public fun Value.toDynamic(): dynamic { /** * Represent or copy this [Meta] to dynamic object to be passed to JS libraries */ -@DFExperimental public fun Meta.toDynamic(): dynamic { if (this is DynamicMeta) return this.obj if(items.isEmpty()) return value?.toDynamic() @@ -36,7 +33,6 @@ public fun Meta.toDynamic(): dynamic { return res } -@DFExperimental public class DynamicMeta(internal val obj: dynamic) : TypedMeta { private fun keys(): Array = js("Object").keys(obj) as Array 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 8c70c29c..e5458258 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 @@ -5,7 +5,6 @@ import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.misc.Type import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.toName import space.kscience.dataforge.provider.Provider @@ -28,7 +27,7 @@ public interface Workspace : ContextAware, Provider { override fun content(target: String): Map { return when (target) { - "target", Meta.TYPE -> targets.mapKeys { it.key.toName() } + "target", Meta.TYPE -> targets.mapKeys { Name.parse(it.key)} Task.TYPE -> tasks //Data.TYPE -> data.flow().toMap() else -> emptyMap() @@ -50,10 +49,10 @@ public interface Workspace : ContextAware, Provider { } public suspend fun Workspace.produce(task: String, target: String): TaskResult<*> = - produce(task.toName(), targets[target] ?: error("Target with key $target not found in $this")) + produce(Name.parse(task), targets[target] ?: error("Target with key $target not found in $this")) public suspend fun Workspace.produce(task: String, meta: Meta): TaskResult<*> = - produce(task.toName(), meta) + produce(Name.parse(task), meta) public suspend fun Workspace.produce(task: String, block: MutableMeta.() -> Unit = {}): TaskResult<*> = produce(task, Meta(block)) 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 d2c0e48d..423a1807 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 @@ -14,7 +14,6 @@ import space.kscience.dataforge.meta.descriptors.MetaDescriptorBuilder import space.kscience.dataforge.misc.DFBuilder import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.toName import kotlin.properties.PropertyDelegateProvider import kotlin.properties.ReadOnlyProperty @@ -29,13 +28,13 @@ public inline fun TaskContainer.registerTask( name: String, noinline descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {}, noinline builder: suspend TaskResultBuilder.() -> Unit, -): Unit = registerTask(name.toName(), Task(MetaDescriptor(descriptorBuilder), builder)) +): Unit = registerTask(Name.parse(name), Task(MetaDescriptor(descriptorBuilder), builder)) public inline fun TaskContainer.task( noinline descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {}, noinline builder: suspend TaskResultBuilder.() -> Unit, ): PropertyDelegateProvider>> = PropertyDelegateProvider { _, property -> - val taskName = property.name.toName() + val taskName = Name.parse(property.name) val task = Task(MetaDescriptor(descriptorBuilder), builder) registerTask(taskName, task) ReadOnlyProperty { _, _ -> TaskReference(taskName, task) } 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 da938a21..effc43e0 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 @@ -7,7 +7,6 @@ import space.kscience.dataforge.context.PluginFactory import space.kscience.dataforge.context.PluginTag import space.kscience.dataforge.data.* import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.names.toName import kotlin.reflect.KClass import kotlin.test.Test import kotlin.test.assertEquals @@ -25,7 +24,7 @@ class DataPropagationTestPlugin : WorkspacePlugin() { val singleData by task { - workspace.data.select().getData("myData[12]".toName())?.let { + workspace.data.select().getData("myData[12]")?.let { emit("result", it) } }