diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 25f2cfd0..cde58b6d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,9 @@ name: Gradle build -on: [ push ] +on: + push: + branches: [ dev, master ] + pull_request: jobs: build: @@ -8,20 +11,22 @@ jobs: matrix: os: [ macOS-latest, windows-latest ] runs-on: ${{matrix.os}} + timeout-minutes: 40 steps: - name: Checkout the repo uses: actions/checkout@v2 - name: Set up JDK 11 - uses: actions/setup-java@v1 + uses: DeLaGuardo/setup-graalvm@4.0 with: - java-version: 11 - - name: Add msys to path - if: matrix.os == 'windows-latest' - run: SETX PATH "%PATH%;C:\msys64\mingw64\bin" + graalvm: 21.2.0 + java: java11 + arch: amd64 - name: Cache gradle uses: actions/cache@v2 with: - path: ~/.gradle/caches + path: | + ~/.gradle/caches + ~/.gradle/wrapper key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} restore-keys: | ${{ runner.os }}-gradle- @@ -33,4 +38,4 @@ jobs: restore-keys: | ${{ runner.os }}-gradle- - name: Build - run: ./gradlew build --no-daemon --stacktrace + run: ./gradlew build --build-cache --no-daemon --stacktrace diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml index 74c1bffd..23ed5435 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -2,32 +2,27 @@ name: Dokka publication on: push: - branches: - - master + branches: [ master ] jobs: build: runs-on: ubuntu-20.04 + timeout-minutes: 40 steps: - - name: Checkout the repo - uses: actions/checkout@v2 - - name: Set up JDK 11 - uses: actions/setup-java@v1 + - uses: actions/checkout@v2 + - uses: DeLaGuardo/setup-graalvm@4.0 with: - java-version: 11 - - name: Cache gradle - uses: actions/cache@v2 + graalvm: 21.2.0 + java: java11 + arch: amd64 + - uses: actions/cache@v2 with: path: ~/.gradle/caches - key: ubuntu-20.04-gradle-${{ hashFiles('*.gradle.kts') }} + key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} restore-keys: | - ubuntu-20.04-gradle- - - name: Build - run: | - ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace - mv build/dokka/htmlMultiModule/-modules.html build/dokka/htmlMultiModule/index.html - - name: Deploy to GitHub Pages - uses: JamesIves/github-pages-deploy-action@4.1.0 + ${{ runner.os }}-gradle- + - run: ./gradlew dokkaHtmlMultiModule --build-cache --no-daemon --no-parallel --stacktrace + - uses: JamesIves/github-pages-deploy-action@4.1.0 with: branch: gh-pages folder: build/dokka/htmlMultiModule diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 42fa6d3b..c5075cb0 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -3,8 +3,7 @@ name: Gradle publish on: workflow_dispatch: release: - types: - - created + types: [ created ] jobs: publish: @@ -12,22 +11,23 @@ jobs: name: publish strategy: matrix: - os: [macOS-latest, windows-latest] + os: [ macOS-latest, windows-latest ] runs-on: ${{matrix.os}} steps: - name: Checkout the repo uses: actions/checkout@v2 - name: Set up JDK 11 - uses: actions/setup-java@v1 + uses: DeLaGuardo/setup-graalvm@4.0 with: - java-version: 11 - - name: Add msys to path - if: matrix.os == 'windows-latest' - run: SETX PATH "%PATH%;C:\msys64\mingw64\bin" + graalvm: 21.2.0 + java: java11 + arch: amd64 - name: Cache gradle uses: actions/cache@v2 with: - path: ~/.gradle/caches + path: | + ~/.gradle/caches + ~/.gradle/wrapper key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} restore-keys: | ${{ runner.os }}-gradle- @@ -40,20 +40,14 @@ jobs: ${{ runner.os }}-gradle- - name: Publish Windows Artifacts if: matrix.os == 'windows-latest' + shell: cmd run: > - ./gradlew release --no-daemon - -Ppublishing.enabled=true - -Ppublishing.github.user=${{ secrets.PUBLISHING_GITHUB_USER }} - -Ppublishing.github.token=${{ secrets.PUBLISHING_GITHUB_TOKEN }} - -Ppublishing.space.user=${{ secrets.PUBLISHING_SPACE_USER }} - -Ppublishing.space.token=${{ secrets.PUBLISHING_SPACE_TOKEN }} + ./gradlew release --no-daemon --build-cache -Ppublishing.enabled=true + -Ppublishing.space.user=${{ secrets.SPACE_APP_ID }} + -Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }} - name: Publish Mac Artifacts if: matrix.os == 'macOS-latest' run: > - ./gradlew release --no-daemon - -Ppublishing.enabled=true - -Ppublishing.platform=macosX64 - -Ppublishing.github.user=${{ secrets.PUBLISHING_GITHUB_USER }} - -Ppublishing.github.token=${{ secrets.PUBLISHING_GITHUB_TOKEN }} - -Ppublishing.space.user=${{ secrets.PUBLISHING_SPACE_USER }} - -Ppublishing.space.token=${{ secrets.PUBLISHING_SPACE_TOKEN }} + ./gradlew release --no-daemon --build-cache -Ppublishing.enabled=true -Ppublishing.platform=macosX64 + -Ppublishing.space.user=${{ secrets.SPACE_APP_ID }} + -Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b4b4990..3a874fa5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,31 @@ ### Fixed +### Security +## [0.5.0] +### Added +- Experimental `listOfSpec` delegate. + +### Changed +- **API breaking** Config is deprecated, use `ObservableMeta` instead. +- **API breaking** Descriptor no has a member property `defaultValue` instead of `defaultItem()` extension. It caches default value state on the first call. It is done because computing default on each call is too expensive. +- Kotlin 1.5.10 +- Build tools 0.10.0 +- Relaxed type restriction on `MetaConverter`. Now nullables are available. +- **Huge API-breaking refactoring of Meta**. Meta now can have both value and children. There is only one kind of descriptor now. +- **API breaking** `String.toName()` is replaced by `Name.parse()` +- **API breaking** Configurable`config` changed to `meta` + +### Removed +- `Config` +- Public PluginManager mutability +- Tables and tables-exposed moved to the separate project `tables.kt` +- BinaryMetaFormat. Use CBOR encoding instead + +### Fixed +- Proper json array index treatment. +- Proper json index for single-value array. + ### Security ## [0.4.0] ### Added diff --git a/README.md b/README.md index 1b559341..b6a8a566 100644 --- a/README.md +++ b/README.md @@ -35,12 +35,6 @@ > **Maturity**: PROTOTYPE
-* ### [dataforge-tables](dataforge-tables) -> -> -> **Maturity**: PROTOTYPE -
- * ### [dataforge-workspace](dataforge-workspace) > > diff --git a/build.gradle.kts b/build.gradle.kts index 53e618df..82f63b33 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ plugins { allprojects { group = "space.kscience" - version = "0.4.0" + version = "0.5.0" } subprojects { @@ -15,10 +15,6 @@ readme { readmeTemplate = file("docs/templates/README-TEMPLATE.md") } -changelog{ - version = project.version.toString() -} - ksciencePublish { github("dataforge-core") space("https://maven.pkg.jetbrains.space/mipt-npm/p/sci/maven") diff --git a/dataforge-context/api/dataforge-context.api b/dataforge-context/api/dataforge-context.api index 3cf0970c..65bcc846 100644 --- a/dataforge-context/api/dataforge-context.api +++ b/dataforge-context/api/dataforge-context.api @@ -164,11 +164,6 @@ public final class space/kscience/dataforge/context/PluginFactory$Companion { } public final class space/kscience/dataforge/context/PluginManager : java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker, space/kscience/dataforge/context/ContextAware { - public fun (Lspace/kscience/dataforge/context/Context;)V - public final fun fetch (Lspace/kscience/dataforge/context/PluginFactory;Lspace/kscience/dataforge/meta/Meta;Z)Lspace/kscience/dataforge/context/Plugin; - public final fun fetch (Lspace/kscience/dataforge/context/PluginFactory;ZLkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/context/Plugin; - public static synthetic fun fetch$default (Lspace/kscience/dataforge/context/PluginManager;Lspace/kscience/dataforge/context/PluginFactory;Lspace/kscience/dataforge/meta/Meta;ZILjava/lang/Object;)Lspace/kscience/dataforge/context/Plugin; - public static synthetic fun fetch$default (Lspace/kscience/dataforge/context/PluginManager;Lspace/kscience/dataforge/context/PluginFactory;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/context/Plugin; public final fun find (ZLkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/context/Plugin; public static synthetic fun find$default (Lspace/kscience/dataforge/context/PluginManager;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/context/Plugin; public final fun get (Lkotlin/reflect/KClass;Lspace/kscience/dataforge/context/PluginTag;Z)Ljava/lang/Object; @@ -178,7 +173,6 @@ public final class space/kscience/dataforge/context/PluginManager : java/lang/It public fun getContext ()Lspace/kscience/dataforge/context/Context; public fun iterator ()Ljava/util/Iterator; public final fun list (Z)Ljava/util/Collection; - public final fun remove (Lspace/kscience/dataforge/context/Plugin;)V } public final class space/kscience/dataforge/context/PluginTag : space/kscience/dataforge/meta/MetaRepr { @@ -228,28 +222,6 @@ public final class space/kscience/dataforge/context/SlfLogManager$Companion : sp public fun invoke (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/context/Context;)Lspace/kscience/dataforge/context/SlfLogManager; } -public abstract interface annotation class space/kscience/dataforge/descriptors/Attribute : java/lang/annotation/Annotation { - public abstract fun key ()Ljava/lang/String; - public abstract fun value ()Ljava/lang/String; -} - -public abstract interface annotation class space/kscience/dataforge/descriptors/Attributes : java/lang/annotation/Annotation { - public abstract fun attrs ()[Lspace/kscience/dataforge/descriptors/Attribute; -} - -public abstract interface annotation class space/kscience/dataforge/descriptors/ItemDef : java/lang/annotation/Annotation { - public abstract fun info ()Ljava/lang/String; - public abstract fun multiple ()Z - public abstract fun required ()Z -} - -public abstract interface annotation class space/kscience/dataforge/descriptors/ValueDef : java/lang/annotation/Annotation { - public abstract fun allowed ()[Ljava/lang/String; - public abstract fun def ()Ljava/lang/String; - public abstract fun enumeration ()Ljava/lang/Class; - public abstract fun type ()[Lspace/kscience/dataforge/values/ValueType; -} - public final class space/kscience/dataforge/properties/PropertyKt { } diff --git a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Context.kt b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Context.kt index 2451048d..97efc76a 100644 --- a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Context.kt +++ b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Context.kt @@ -3,10 +3,7 @@ package space.kscience.dataforge.context import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job import kotlinx.coroutines.SupervisorJob -import space.kscience.dataforge.meta.Laminate -import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MetaRepr -import space.kscience.dataforge.meta.itemSequence +import space.kscience.dataforge.meta.* import space.kscience.dataforge.misc.Named import space.kscience.dataforge.names.Name import space.kscience.dataforge.provider.Provider @@ -26,6 +23,7 @@ import kotlin.jvm.Synchronized public open class Context internal constructor( final override val name: Name, public val parent: Context?, + plugins: Set, // set of unattached plugins meta: Meta, ) : Named, MetaRepr, Provider, CoroutineScope { @@ -42,20 +40,20 @@ public open class Context internal constructor( /** * A [PluginManager] for current context */ - public val plugins: PluginManager by lazy { PluginManager(this) } + public val plugins: PluginManager by lazy { PluginManager(this, plugins) } override val defaultTarget: String get() = Plugin.TARGET public fun content(target: String, inherit: Boolean): Map { return if (inherit) { when (target) { - PROPERTY_TARGET -> properties.itemSequence().toMap() + PROPERTY_TARGET -> properties.nodeSequence().toMap() Plugin.TARGET -> plugins.list(true).associateBy { it.name } else -> emptyMap() } } else { when (target) { - PROPERTY_TARGET -> properties.layers.firstOrNull()?.itemSequence()?.toMap() ?: emptyMap() + PROPERTY_TARGET -> properties.layers.firstOrNull()?.nodeSequence()?.toMap() ?: emptyMap() Plugin.TARGET -> plugins.list(false).associateBy { it.name } else -> emptyMap() } @@ -97,8 +95,8 @@ public open class Context internal constructor( override fun toMeta(): Meta = Meta { "parent" to parent?.name - "properties" put properties.layers.firstOrNull() - "plugins" put plugins.map { it.toMeta() } + properties.layers.firstOrNull()?.let { set("properties", it) } + "plugins" putIndexed plugins.map { it.toMeta() } } public companion object { 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 c302cb6b..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 @@ -1,14 +1,15 @@ package space.kscience.dataforge.context import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MetaBuilder +import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.meta.seal import space.kscience.dataforge.meta.toMutableMeta import space.kscience.dataforge.misc.DFBuilder import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.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 @@ -25,12 +26,12 @@ public class ContextBuilder internal constructor( internal val factories = HashMap, Meta>() internal var meta = meta.toMutableMeta() - public fun properties(action: MetaBuilder.() -> Unit) { + public fun properties(action: MutableMeta.() -> Unit) { meta.action() } public fun name(string: String) { - this.name = string.toName() + this.name = Name.parse(string) } @OptIn(DFExperimental::class) @@ -38,20 +39,20 @@ public class ContextBuilder internal constructor( parent.gatherInSequence>(PluginFactory.TYPE).values .find { it.tag.matches(tag) } ?: error("Can't resolve plugin factory for $tag") - public fun plugin(tag: PluginTag, metaBuilder: MetaBuilder.() -> Unit = {}) { + public fun plugin(tag: PluginTag, mutableMeta: MutableMeta.() -> Unit = {}) { val factory = findPluginFactory(tag) - factories[factory] = Meta(metaBuilder) + factories[factory] = Meta(mutableMeta) } public fun plugin(factory: PluginFactory<*>, meta: Meta) { factories[factory] = meta } - public fun plugin(factory: PluginFactory<*>, metaBuilder: MetaBuilder.() -> Unit = {}) { - factories[factory] = Meta(metaBuilder) + public fun plugin(factory: PluginFactory<*>, mutableMeta: MutableMeta.() -> Unit = {}) { + factories[factory] = Meta(mutableMeta) } - public fun plugin(name: String, group: String = "", version: String = "", action: MetaBuilder.() -> Unit = {}) { + public fun plugin(name: String, group: String = "", version: String = "", action: MutableMeta.() -> Unit = {}) { plugin(PluginTag(name, group, version), action) } @@ -63,13 +64,33 @@ public class ContextBuilder internal constructor( } public fun build(): Context { - val contextName = name ?: "@auto[${hashCode().toUInt().toString(16)}]".toName() - return Context(contextName, parent, meta.seal()).apply { - factories.forEach { (factory, meta) -> - @Suppress("DEPRECATION") - plugins.load(factory, meta) + val contextName = name ?: NameToken("@auto",hashCode().toUInt().toString(16)).asName() + val plugins = HashMap() + + fun addPlugin(factory: PluginFactory<*>, meta: Meta) { + val existing = plugins[factory.tag] + // Add if does not exist + if (existing == null) { + //TODO bypass if parent already has plugin with given meta? + val plugin = factory(meta, parent) + + for ((depFactory, deoMeta) in plugin.dependsOn()) { + addPlugin(depFactory, deoMeta) + } + + parent.logger.info { "Loading plugin ${plugin.name} into $contextName" } + plugins[plugin.tag] = plugin + } else if (existing.meta != meta) { + error("Plugin with tag ${factory.tag} and meta $meta already exists in $contextName") } + //bypass if exists with the same meta } + + factories.forEach { (factory, meta) -> + addPlugin(factory, meta) + } + + return Context(contextName, parent, plugins.values.toSet(), meta.seal()) } } diff --git a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Global.kt b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Global.kt index fe22af62..9ace5800 100644 --- a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Global.kt +++ b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/Global.kt @@ -1,6 +1,6 @@ package space.kscience.dataforge.context -import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.Job import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.names.asName @@ -13,8 +13,8 @@ internal expect val globalLoggerFactory: PluginFactory * A global root context. Closing [Global] terminates the framework. */ @ThreadLocal -private object GlobalContext : Context("GLOBAL".asName(), null, Meta.EMPTY) { - override val coroutineContext: CoroutineContext = GlobalScope.coroutineContext + Job() +private object GlobalContext : Context("GLOBAL".asName(), null, emptySet(), Meta.EMPTY) { + override val coroutineContext: CoroutineContext = Job() + CoroutineName("GlobalContext") } public val Global: Context get() = GlobalContext 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/context/PluginManager.kt b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/PluginManager.kt index 0fd1e9e1..81d455c7 100644 --- a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/PluginManager.kt +++ b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/PluginManager.kt @@ -1,7 +1,6 @@ package space.kscience.dataforge.context import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MetaBuilder import kotlin.reflect.KClass @@ -11,12 +10,10 @@ import kotlin.reflect.KClass * @property context A context for this plugin manager * @author Alexander Nozik */ -public class PluginManager(override val context: Context) : ContextAware, Iterable { - - /** - * A set of loaded plugins - */ - private val plugins: HashSet = HashSet() +public class PluginManager internal constructor( + override val context: Context, + private val plugins: Set +) : ContextAware, Iterable { init { plugins.forEach { it.attach(context) } @@ -76,70 +73,7 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab public inline operator fun get(factory: PluginFactory, recursive: Boolean = true): T? = get(factory.type, factory.tag, recursive) - /** - * Load given plugin into this manager and return loaded instance. - * Throw error if plugin of the same type and tag already exists in manager. - * - * @param plugin - * @return - */ - @Deprecated("Use immutable contexts instead") - private fun load(plugin: T): T { - if (get(plugin::class, plugin.tag, recursive = false) != null) { - error("Plugin with tag ${plugin.tag} already exists in ${context.name}") - } else { - for ((factory, meta) in plugin.dependsOn()) { - fetch(factory, meta, true) - } - - logger.info { "Loading plugin ${plugin.name} into ${context.name}" } - plugin.attach(context) - plugins.add(plugin) - return plugin - } - } - - /** - * Load a plugin using its factory - */ - @Deprecated("Use immutable contexts instead") - internal fun load(factory: PluginFactory, meta: Meta = Meta.EMPTY): T = - load(factory(meta, context)) - - /** - * Remove a plugin from [PluginManager] - */ - @Deprecated("Use immutable contexts instead") - public fun remove(plugin: Plugin) { - if (plugins.contains(plugin)) { - Global.logger.info { "Removing plugin ${plugin.name} from ${context.name}" } - plugin.detach() - plugins.remove(plugin) - } - } - - /** - * Get an existing plugin with given meta or load new one using provided factory - */ - @Deprecated("Use immutable contexts instead") - public fun fetch(factory: PluginFactory, meta: Meta = Meta.EMPTY, recursive: Boolean = true): T { - val loaded = get(factory.type, factory.tag, recursive) - return when { - loaded == null -> load(factory(meta, context)) - loaded.meta == meta -> loaded // if meta is the same, return existing plugin - else -> throw RuntimeException("Can't load plugin with tag ${factory.tag}. Plugin with this tag and different configuration already exists in context.") - } - } - - @Deprecated("Use immutable contexts instead") - public fun fetch( - factory: PluginFactory, - recursive: Boolean = true, - metaBuilder: MetaBuilder.() -> Unit, - ): T = fetch(factory, Meta(metaBuilder), recursive) - override fun iterator(): Iterator = plugins.iterator() - } /** diff --git a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/ConfigProperty.kt b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/MetaProperty.kt similarity index 50% rename from dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/ConfigProperty.kt rename to dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/MetaProperty.kt index c51f809e..23601141 100644 --- a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/ConfigProperty.kt +++ b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/MetaProperty.kt @@ -1,35 +1,34 @@ package space.kscience.dataforge.properties -import space.kscience.dataforge.meta.Config -import space.kscience.dataforge.meta.get -import space.kscience.dataforge.meta.set + +import space.kscience.dataforge.meta.* import space.kscience.dataforge.meta.transformations.MetaConverter -import space.kscience.dataforge.meta.transformations.nullableItemToObject -import space.kscience.dataforge.meta.transformations.nullableObjectToMetaItem +import space.kscience.dataforge.meta.transformations.nullableMetaToObject +import space.kscience.dataforge.meta.transformations.nullableObjectToMeta import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.startsWith @DFExperimental -public class ConfigProperty( - public val config: Config, +public class MetaProperty( + public val meta: ObservableMutableMeta, public val name: Name, public val converter: MetaConverter, ) : Property { override var value: T? - get() = converter.nullableItemToObject(config[name]) + get() = converter.nullableMetaToObject(meta[name]) set(value) { - config[name] = converter.nullableObjectToMetaItem(value) + meta[name] = converter.nullableObjectToMeta(value) ?: Meta.EMPTY } override fun onChange(owner: Any?, callback: (T?) -> Unit) { - config.onChange(owner) { name, oldItem, newItem -> - if (name.startsWith(this.name) && oldItem != newItem) callback(converter.nullableItemToObject(newItem)) + meta.onChange(owner) { name -> + if (name.startsWith(this@MetaProperty.name)) callback(converter.nullableMetaToObject(get(name))) } } override fun removeChangeListener(owner: Any?) { - config.removeListener(owner) + meta.removeListener(owner) } } \ No newline at end of file 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 798154d5..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,13 +1,14 @@ package space.kscience.dataforge.properties -import space.kscience.dataforge.meta.ItemPropertyProvider + +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) @@ -16,15 +17,15 @@ public fun

P.property(property: KMutableProp } override fun onChange(owner: Any?, callback: (T?) -> Unit) { - this@property.onChange(this) { name, oldItem, newItem -> - if (name.startsWith(property.name.toName()) && oldItem != newItem) { + 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 2a16e53f..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 /** @@ -33,11 +32,7 @@ public value class Path(public val tokens: List) : Iterable { - 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-context/src/commonTest/kotlin/space/kscience/dataforge/provider/PathTest.kt b/dataforge-context/src/commonTest/kotlin/space/kscience/dataforge/provider/PathTest.kt new file mode 100644 index 00000000..4a38697c --- /dev/null +++ b/dataforge-context/src/commonTest/kotlin/space/kscience/dataforge/provider/PathTest.kt @@ -0,0 +1,14 @@ +package space.kscience.dataforge.provider + +import kotlin.test.Test +import kotlin.test.assertEquals + +class PathTest { + @Test + fun testParse(){ + val nameString = "a.b.c.d" + val pathString = "a.b/c.d" + assertEquals(1, Path.parse(nameString).length) + assertEquals(2, Path.parse(pathString).length) + } +} \ No newline at end of file diff --git a/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/descriptors/annotations.kt b/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/descriptors/annotations.kt index 25daa096..f97cb28d 100644 --- a/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/descriptors/annotations.kt +++ b/dataforge-context/src/jvmMain/kotlin/space/kscience/dataforge/descriptors/annotations.kt @@ -16,35 +16,32 @@ package space.kscience.dataforge.descriptors -import space.kscience.dataforge.values.ValueType -import kotlin.reflect.KClass - -@MustBeDocumented -annotation class Attribute( - val key: String, - val value: String -) - -@MustBeDocumented -annotation class Attributes( - val attrs: Array -) - -@MustBeDocumented -annotation class ItemDef( - val info: String = "", - val multiple: Boolean = false, - val required: Boolean = false -) - -@Target(AnnotationTarget.PROPERTY) -@MustBeDocumented -annotation class ValueDef( - val type: Array = [ValueType.STRING], - val def: String = "", - val allowed: Array = [], - val enumeration: KClass<*> = Any::class -) +//@MustBeDocumented +//annotation class Attribute( +// val key: String, +// val value: String +//) +// +//@MustBeDocumented +//annotation class Attributes( +// val attrs: Array +//) +// +//@MustBeDocumented +//annotation class ItemDef( +// val info: String = "", +// val multiple: Boolean = false, +// val required: Boolean = false +//) +// +//@Target(AnnotationTarget.PROPERTY) +//@MustBeDocumented +//annotation class ValueDef( +// val type: Array = [ValueType.STRING], +// val def: String = "", +// val allowed: Array = [], +// val enumeration: KClass<*> = Any::class +//) ///** // * Description text for meta property, node or whole object 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 aa71ff44..0e6d6f0f 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/actions/MapAction.kt @@ -6,7 +6,7 @@ import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch import space.kscience.dataforge.data.* import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MetaBuilder +import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.meta.seal import space.kscience.dataforge.meta.toMutableMeta import space.kscience.dataforge.misc.DFBuilder @@ -29,7 +29,7 @@ public data class ActionEnv( * Action environment */ @DFBuilder -public class MapActionBuilder(public var name: Name, public var meta: MetaBuilder, public val actionMeta: Meta) { +public class MapActionBuilder(public var name: Name, public var meta: MutableMeta, public val actionMeta: Meta) { public lateinit var result: suspend ActionEnv.(T) -> R /** @@ -68,7 +68,8 @@ internal class MapAction( //getting new meta val newMeta = builder.meta.seal() - @OptIn(DFInternal::class) val newData = Data(outputType, newMeta, dependencies = listOf(data)) { + @OptIn(DFInternal::class) + val newData = Data(outputType, newMeta, dependencies = listOf(data)) { builder.result(env, data.await()) } //setting the data node 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 2607804c..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 @@ -6,19 +6,18 @@ import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.fold import space.kscience.dataforge.data.* import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MetaBuilder +import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.misc.DFBuilder import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.toName import kotlin.reflect.KType import kotlin.reflect.typeOf public class JoinGroup(public var name: String, internal val set: DataSet) { - public var meta: MetaBuilder = MetaBuilder() + public var meta: MutableMeta = MutableMeta() public lateinit var result: suspend ActionEnv.(Map) -> R @@ -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 50286a2a..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 @@ -7,12 +7,11 @@ import kotlinx.coroutines.launch import space.kscience.dataforge.data.* import space.kscience.dataforge.meta.Laminate import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MetaBuilder +import space.kscience.dataforge.meta.MutableMeta 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 @@ -20,7 +19,7 @@ import kotlin.reflect.typeOf public class SplitBuilder(public val name: Name, public val meta: Meta) { - public class FragmentRule(public val name: Name, public var meta: MetaBuilder) { + public class FragmentRule(public val name: Name, public var meta: MutableMeta) { public lateinit var result: suspend (T) -> R public fun result(f: suspend (T) -> R) { @@ -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/Data.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/Data.kt index 955af3ef..8e681678 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 @@ -49,6 +49,7 @@ public interface Data : Goal, MetaRepr { /** * An empty data containing only meta */ + @OptIn(DelicateCoroutinesApi::class) public fun empty(meta: Meta): Data = object : Data { override val type: KType = TYPE_OF_NOTHING override val meta: Meta = meta 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 580e702b..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 @@ -4,11 +4,10 @@ import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.collect import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MetaBuilder +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, - metaBuilder: MetaBuilder.() -> Unit, -): Unit = emit(name.toName(), Data.static(data, Meta(metaBuilder))) + mutableMeta: MutableMeta.() -> Unit, +): 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/GroupRule.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/GroupRule.kt index 90a85f30..a9050b3c 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/GroupRule.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/GroupRule.kt @@ -52,7 +52,9 @@ public interface GroupRule { scope.launch { set.updates.collect { name -> val data = set.getData(name) - val tagValue = data?.meta[key].string ?: defaultTagValue + + @Suppress("NULLABLE_EXTENSION_OPERATOR_WITH_SAFE_CALL_RECEIVER") + val tagValue = data?.meta?.get(key)?.string ?: defaultTagValue map.getOrPut(tagValue) { ActiveDataTree(set.dataType) }.emit(name, data) } } 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/commonMain/kotlin/space/kscience/dataforge/data/dataSetMeta.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataSetMeta.kt index b1508d29..bdbbf3a8 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataSetMeta.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataSetMeta.kt @@ -1,7 +1,7 @@ package space.kscience.dataforge.data import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MetaBuilder +import space.kscience.dataforge.meta.MutableMeta /** @@ -17,4 +17,4 @@ public suspend fun DataSetBuilder<*>.meta(meta: Meta): Unit = emit(DataSet.META_ /** * Add meta-data node to a [DataSet] */ -public suspend fun DataSetBuilder<*>.meta(metaBuilder: MetaBuilder.() -> Unit): Unit = meta(Meta(metaBuilder)) \ No newline at end of file +public suspend fun DataSetBuilder<*>.meta(mutableMeta: MutableMeta.() -> Unit): Unit = meta(Meta(mutableMeta)) \ No newline at end of file diff --git a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataTransform.kt b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataTransform.kt index a64d0790..f4c4a710 100644 --- a/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataTransform.kt +++ b/dataforge-data/src/commonMain/kotlin/space/kscience/dataforge/data/dataTransform.kt @@ -2,7 +2,7 @@ package space.kscience.dataforge.data import kotlinx.coroutines.flow.* import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MetaBuilder +import space.kscience.dataforge.meta.MutableMeta import space.kscience.dataforge.meta.seal import space.kscience.dataforge.meta.toMutableMeta import space.kscience.dataforge.misc.DFInternal @@ -140,7 +140,7 @@ public suspend inline fun Flow>.foldToDa public suspend fun DataSet.map( outputType: KType, coroutineContext: CoroutineContext = EmptyCoroutineContext, - metaTransform: MetaBuilder.() -> Unit = {}, + metaTransform: MutableMeta.() -> Unit = {}, block: suspend (T) -> R, ): DataTree = DataTree(outputType) { populate( @@ -156,7 +156,7 @@ public suspend fun DataSet.map( @OptIn(DFInternal::class) public suspend inline fun DataSet.map( coroutineContext: CoroutineContext = EmptyCoroutineContext, - noinline metaTransform: MetaBuilder.() -> Unit = {}, + noinline metaTransform: MutableMeta.() -> Unit = {}, noinline block: suspend (T) -> R, ): DataTree = map(typeOf(), coroutineContext, metaTransform, block) 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/dataforge-io-yaml/src/commonMain/kotlin/space/kscience/dataforge/io/yaml/YamlMetaFormat.kt b/dataforge-io/dataforge-io-yaml/src/commonMain/kotlin/space/kscience/dataforge/io/yaml/YamlMetaFormat.kt index 37b5658b..96c57c58 100644 --- a/dataforge-io/dataforge-io-yaml/src/commonMain/kotlin/space/kscience/dataforge/io/yaml/YamlMetaFormat.kt +++ b/dataforge-io/dataforge-io-yaml/src/commonMain/kotlin/space/kscience/dataforge/io/yaml/YamlMetaFormat.kt @@ -10,43 +10,49 @@ import space.kscience.dataforge.io.MetaFormat import space.kscience.dataforge.io.MetaFormatFactory import space.kscience.dataforge.io.readUtf8String import space.kscience.dataforge.io.writeUtf8String -import space.kscience.dataforge.meta.* -import space.kscience.dataforge.meta.descriptors.ItemDescriptor -import space.kscience.dataforge.meta.descriptors.NodeDescriptor +import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.meta.descriptors.MetaDescriptor +import space.kscience.dataforge.meta.descriptors.get +import space.kscience.dataforge.meta.isLeaf import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.NameToken import space.kscience.dataforge.names.withIndex import space.kscience.dataforge.values.ListValue import space.kscience.dataforge.values.Null +import space.kscience.dataforge.values.Value import space.kscience.dataforge.values.parseValue +import kotlin.collections.component1 +import kotlin.collections.component2 +import kotlin.collections.set public fun Meta.toYaml(): YamlMap { val map: Map = items.entries.associate { (key, item) -> - key.toString() to when (item) { - is MetaItemValue -> { - item.value.value - } - is MetaItemNode -> { - item.node.toYaml() - } + key.toString() to if (item.isLeaf) { + item.value?.value + } else { + item.toYaml() } } + return YamlMap(map) } -private class YamlMeta(private val yamlMap: YamlMap, private val descriptor: NodeDescriptor? = null) : MetaBase() { +private class YamlMeta(private val yamlMap: YamlMap, private val descriptor: MetaDescriptor? = null) : Meta { - private fun buildItems(): Map { - val map = LinkedHashMap() + override val value: Value? + get() = yamlMap.getStringOrNull(null)?.parseValue() + + private fun buildItems(): Map { + val map = LinkedHashMap() yamlMap.content.entries.forEach { (key, value) -> val stringKey = key.toString() - val itemDescriptor = descriptor?.items?.get(stringKey) + val itemDescriptor = descriptor?.get(stringKey) val token = NameToken(stringKey) when (value) { - YamlNull -> Null.asMetaItem() - is YamlLiteral -> map[token] = value.content.parseValue().asMetaItem() - is YamlMap -> map[token] = value.toMeta().asMetaItem() + YamlNull -> Meta(Null) + is YamlLiteral -> map[token] = Meta(value.content.parseValue()) + is YamlMap -> map[token] = value.toMeta() is YamlList -> if (value.all { it is YamlLiteral }) { val listValue = ListValue( value.map { @@ -54,29 +60,33 @@ private class YamlMeta(private val yamlMap: YamlMap, private val descriptor: Nod (it as YamlLiteral).content.parseValue() } ) - map[token] = MetaItemValue(listValue) + map[token] = Meta(listValue) } else value.forEachIndexed { index, yamlElement -> - val indexKey = (itemDescriptor as? NodeDescriptor)?.indexKey ?: ItemDescriptor.DEFAULT_INDEX_KEY + val indexKey = itemDescriptor?.indexKey val indexValue: String = (yamlElement as? YamlMap)?.getStringOrNull(indexKey) ?: index.toString() //In case index is non-string, the backward transformation will be broken. val tokenWithIndex = token.withIndex(indexValue) - map[tokenWithIndex] = yamlElement.toMetaItem(itemDescriptor) + map[tokenWithIndex] = yamlElement.toMeta(itemDescriptor) } } } return map } - override val items: Map get() = buildItems() + override val items: Map get() = buildItems() + + 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) } -public fun YamlElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem = when (this) { - YamlNull -> Null.asMetaItem() - is YamlLiteral -> content.parseValue().asMetaItem() - is YamlMap -> toMeta().asMetaItem() +public fun YamlElement.toMeta(descriptor: MetaDescriptor? = null): Meta = when (this) { + YamlNull -> Meta(Null) + is YamlLiteral -> Meta(content.parseValue()) + is YamlMap -> toMeta() //We can't return multiple items therefore we create top level node - is YamlList -> YamlMap(mapOf("@yamlArray" to this)).toMetaItem(descriptor) + is YamlList -> YamlMap(mapOf("@yamlArray" to this)).toMeta(descriptor) } public fun YamlMap.toMeta(): Meta = YamlMeta(this) @@ -88,13 +98,13 @@ public fun YamlMap.toMeta(): Meta = YamlMeta(this) @DFExperimental public class YamlMetaFormat(private val meta: Meta) : MetaFormat { - override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?) { + override fun writeMeta(output: Output, meta: Meta, descriptor: MetaDescriptor?) { val yaml = meta.toYaml() val string = Yaml.encodeToString(yaml) output.writeUtf8String(string) } - override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta { + override fun readMeta(input: Input, descriptor: MetaDescriptor?): Meta { val yaml = Yaml.decodeYamlMapFromString(input.readUtf8String()) return yaml.toMeta() } @@ -113,10 +123,10 @@ public class YamlMetaFormat(private val meta: Meta) : MetaFormat { private val default = YamlMetaFormat() - override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?): Unit = + override fun writeMeta(output: Output, meta: Meta, descriptor: MetaDescriptor?): Unit = default.writeMeta(output, meta, descriptor) - override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta = + override fun readMeta(input: Input, descriptor: MetaDescriptor?): Meta = default.readMeta(input, descriptor) } } \ No newline at end of file diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/BinaryMetaFormat.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/BinaryMetaFormat.kt deleted file mode 100644 index 38ca6ec2..00000000 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/BinaryMetaFormat.kt +++ /dev/null @@ -1,133 +0,0 @@ -package space.kscience.dataforge.io - -import io.ktor.utils.io.core.* -import space.kscience.dataforge.context.Context -import space.kscience.dataforge.meta.* -import space.kscience.dataforge.meta.descriptors.NodeDescriptor -import space.kscience.dataforge.values.* - -/** - * A DataForge-specific simplified binary format for meta - * TODO add description - */ -public object BinaryMetaFormat : MetaFormat, MetaFormatFactory { - override val shortName: String = "bin" - override val key: Short = 0x4249//BI - - override fun invoke(meta: Meta, context: Context): MetaFormat = this - - override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta { - return (input.readMetaItem() as MetaItemNode).node - } - - private fun Output.writeChar(char: Char) = writeByte(char.code.toByte()) - - private fun Output.writeString(str: String) { - writeInt(str.length) - writeFully(str.encodeToByteArray()) - } - - public fun Output.writeValue(value: Value): Unit = when (value.type) { - ValueType.NUMBER -> when (value.value) { - is Short -> { - writeChar('s') - writeShort(value.short) - } - is Int -> { - writeChar('i') - writeInt(value.int) - } - is Long -> { - writeChar('l') - writeLong(value.long) - } - is Float -> { - writeChar('f') - writeFloat(value.float) - } - else -> { - writeChar('d') - writeDouble(value.double) - } - } - ValueType.STRING -> { - writeChar('S') - writeString(value.string) - } - ValueType.BOOLEAN -> { - if (value.boolean) { - writeChar('+') - } else { - writeChar('-') - } - } - ValueType.NULL -> { - writeChar('N') - } - ValueType.LIST -> { - writeChar('L') - writeInt(value.list.size) - value.list.forEach { - writeValue(it) - } - } - } - - override fun writeMeta( - output: Output, - meta: Meta, - descriptor: space.kscience.dataforge.meta.descriptors.NodeDescriptor?, - ) { - output.writeChar('M') - output.writeInt(meta.items.size) - meta.items.forEach { (key, item) -> - output.writeString(key.toString()) - when (item) { - is MetaItemValue -> { - output.writeValue(item.value) - } - is MetaItemNode -> { - writeObject(output, item.node) - } - } - } - } - - private fun Input.readString(): String { - val length = readInt() - val array = readBytes(length) - return array.decodeToString() - } - - @Suppress("UNCHECKED_CAST") - public fun Input.readMetaItem(): TypedMetaItem { - return when (val keyChar = readByte().toInt().toChar()) { - 'S' -> MetaItemValue(StringValue(readString())) - 'N' -> MetaItemValue(Null) - '+' -> MetaItemValue(True) - '-' -> MetaItemValue(True) - 's' -> MetaItemValue(NumberValue(readShort())) - 'i' -> MetaItemValue(NumberValue(readInt())) - 'l' -> MetaItemValue(NumberValue(readInt())) - 'f' -> MetaItemValue(NumberValue(readFloat())) - 'd' -> MetaItemValue(NumberValue(readDouble())) - 'L' -> { - val length = readInt() - val list = (1..length).map { (readMetaItem() as MetaItemValue).value } - MetaItemValue(Value.of(list)) - } - 'M' -> { - val length = readInt() - val meta = Meta { - (1..length).forEach { _ -> - val name = readString() - val item = readMetaItem() - set(name, item) - } - } - MetaItemNode(meta) - } - else -> error("Unknown serialization key character: $keyChar") - } - } -} \ No newline at end of file diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeBuilder.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeBuilder.kt index 211b4f32..62d95b01 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeBuilder.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/EnvelopeBuilder.kt @@ -4,7 +4,7 @@ import io.ktor.utils.io.core.Output import space.kscience.dataforge.meta.* public class EnvelopeBuilder : Envelope { - private val metaBuilder = MetaBuilder() + private val metaBuilder = MutableMeta() override var data: Binary? = null override var meta: Meta @@ -13,7 +13,7 @@ public class EnvelopeBuilder : Envelope { metaBuilder.update(value) } - public fun meta(block: MetaBuilder.() -> Unit) { + public fun meta(block: MutableMeta.() -> Unit) { metaBuilder.apply(block) } 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 fece9a41..641247c3 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 node("meta".toName()) + var partMeta by node("meta".asName()) companion object : SchemeSpec(::PartDescriptor) { val MULTIPART_KEY = ENVELOPE_NODE_KEY + "multipart" @@ -86,15 +85,15 @@ public fun EnvelopeBuilder.envelopes( public fun Envelope.parts(): EnvelopeParts { if (data == null) return emptyList() //TODO add zip folder reader - val parts = meta.getIndexed(PARTS_KEY).values.mapNotNull { it.node }.map { + val parts = meta.getIndexed(PARTS_KEY).values.map { PartDescriptor.read(it) } return if (parts.isEmpty()) { - listOf(EnvelopePart(data!!, meta[MULTIPART_KEY].node)) + listOf(EnvelopePart(data!!, meta[MULTIPART_KEY])) } else { parts.map { val binary = data!!.view(it.offset, it.size) - val meta = Laminate(it.partMeta, meta[MULTIPART_KEY].node) + val meta = Laminate(it.partMeta, meta[MULTIPART_KEY]) EnvelopePart(binary, meta) } } 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 be5f97ab..c6658013 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 @@ -6,13 +6,11 @@ import space.kscience.dataforge.context.Factory import space.kscience.dataforge.io.IOFormat.Companion.NAME_KEY import space.kscience.dataforge.io.IOFormatFactory.Companion.IO_FORMAT_TYPE import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MetaItemValue 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.asName -import space.kscience.dataforge.values.Value import kotlin.reflect.KType import kotlin.reflect.typeOf @@ -117,19 +115,19 @@ public object DoubleIOFormat : IOFormat, IOFormatFactory { override fun readObject(input: Input): Double = input.readDouble() } -public object ValueIOFormat : IOFormat, IOFormatFactory { - override fun invoke(meta: Meta, context: Context): IOFormat = this - - override val name: Name = "value".asName() - - override val type: KType get() = typeOf() - - override fun writeObject(output: Output, obj: Value) { - BinaryMetaFormat.run { output.writeValue(obj) } - } - - override fun readObject(input: Input): Value { - return (BinaryMetaFormat.run { input.readMetaItem() } as? MetaItemValue)?.value - ?: error("The item is not a value") - } -} \ No newline at end of file +//public object ValueIOFormat : IOFormat, IOFormatFactory { +// override fun invoke(meta: Meta, context: Context): IOFormat = this +// +// override val name: Name = "value".asName() +// +// override val type: KType get() = typeOf() +// +// override fun writeObject(output: Output, obj: Value) { +// BinaryMetaFormat.run { output.writeValue(obj) } +// } +// +// override fun readObject(input: Input): Value { +// return (BinaryMetaFormat.run { input.readMetaItem() } as? MetaItemValue)?.value +// ?: error("The item is not a value") +// } +//} \ No newline at end of file diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/IOPlugin.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/IOPlugin.kt index 91442603..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 @@ -6,9 +6,11 @@ import space.kscience.dataforge.io.IOFormat.Companion.META_KEY import space.kscience.dataforge.io.IOFormat.Companion.NAME_KEY import space.kscience.dataforge.io.IOFormatFactory.Companion.IO_FORMAT_TYPE import space.kscience.dataforge.io.MetaFormatFactory.Companion.META_FORMAT_TYPE -import space.kscience.dataforge.meta.* +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 @@ -19,13 +21,13 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) { context.gather>(IO_FORMAT_TYPE).values } - public fun resolveIOFormat(item: MetaItem, type: KClass): IOFormat? { - val key = item.string ?: item.node[NAME_KEY]?.string ?: error("Format name not defined") - val name = key.toName() + public fun resolveIOFormat(item: Meta, type: KClass): IOFormat? { + val key = item.string ?: item[NAME_KEY]?.string ?: error("Format name not defined") + 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") - else it.invoke(item.node[META_KEY].node ?: Meta.EMPTY, context) as IOFormat + else it.invoke(item[META_KEY] ?: Meta.EMPTY, context) as IOFormat } } @@ -47,10 +49,10 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) { private fun resolveEnvelopeFormat(name: Name, meta: Meta = Meta.EMPTY): EnvelopeFormat? = envelopeFormatFactories.find { it.name == name }?.invoke(meta, context) - public fun resolveEnvelopeFormat(item: MetaItem): EnvelopeFormat? { - val name = item.string ?: item.node[NAME_KEY]?.string ?: error("Envelope format name not defined") - val meta = item.node[META_KEY].node ?: Meta.EMPTY - return resolveEnvelopeFormat(name.toName(), 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.parse(name), meta) } override fun content(target: String): Map { @@ -62,7 +64,7 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) { } public companion object : PluginFactory { - public val defaultMetaFormats: List = listOf(JsonMetaFormat, BinaryMetaFormat) + public val defaultMetaFormats: List = listOf(JsonMetaFormat) public val defaultEnvelopeFormats: List = listOf(TaggedEnvelopeFormat, TaglessEnvelopeFormat) diff --git a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/JsonMetaFormat.kt b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/JsonMetaFormat.kt index ca5d52b0..8e588666 100644 --- a/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/JsonMetaFormat.kt +++ b/dataforge-io/src/commonMain/kotlin/space/kscience/dataforge/io/JsonMetaFormat.kt @@ -10,10 +10,9 @@ import kotlinx.serialization.json.JsonObject import space.kscience.dataforge.context.Context import space.kscience.dataforge.io.IOFormat.Companion.NAME_KEY import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.descriptors.NodeDescriptor -import space.kscience.dataforge.meta.node +import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.toJson -import space.kscience.dataforge.meta.toMetaItem +import space.kscience.dataforge.meta.toMeta import kotlin.reflect.KType import kotlin.reflect.typeOf @@ -24,7 +23,7 @@ public class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat override val type: KType get() = typeOf() - override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?) { + override fun writeMeta(output: Output, meta: Meta, descriptor: MetaDescriptor?) { val jsonObject = meta.toJson(descriptor) output.writeUtf8String(json.encodeToString(JsonObject.serializer(), jsonObject)) } @@ -33,11 +32,10 @@ public class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat NAME_KEY put name.toString() } - override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta { + override fun readMeta(input: Input, descriptor: MetaDescriptor?): Meta { val str = input.readUtf8String()//readByteArray().decodeToString() val jsonElement = json.parseToJsonElement(str) - val item = jsonElement.toMetaItem(descriptor) - return item.node ?: Meta.EMPTY + return jsonElement.toMeta(descriptor) } public companion object : MetaFormatFactory { @@ -50,10 +48,10 @@ public class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat private val default = JsonMetaFormat() - override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?): Unit = + override fun writeMeta(output: Output, meta: Meta, descriptor: MetaDescriptor?): Unit = default.run { writeMeta(output, meta, descriptor) } - override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta = + override fun readMeta(input: Input, descriptor: MetaDescriptor?): Meta = default.run { readMeta(input, descriptor) } } } 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 75435649..2155eb9a 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 @@ -7,7 +7,7 @@ import io.ktor.utils.io.core.use import space.kscience.dataforge.context.Context import space.kscience.dataforge.io.MetaFormatFactory.Companion.META_FORMAT_TYPE import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.descriptors.NodeDescriptor +import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.misc.Type import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName @@ -30,10 +30,10 @@ public interface MetaFormat : IOFormat { public fun writeMeta( output: Output, meta: Meta, - descriptor: NodeDescriptor? = null, + descriptor: MetaDescriptor? = null, ) - public fun readMeta(input: Input, descriptor: NodeDescriptor? = null): Meta + public fun readMeta(input: Input, descriptor: MetaDescriptor? = null): Meta } @Type(META_FORMAT_TYPE) 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/MetaFormatTest.kt b/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/MetaFormatTest.kt index a5860d31..d142e746 100644 --- a/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/MetaFormatTest.kt +++ b/dataforge-io/src/commonTest/kotlin/space/kscience/dataforge/io/MetaFormatTest.kt @@ -2,12 +2,12 @@ package space.kscience.dataforge.io import kotlinx.serialization.json.* import space.kscience.dataforge.meta.* -import space.kscience.dataforge.meta.JsonMeta.Companion.JSON_ARRAY_KEY import space.kscience.dataforge.values.ListValue -import space.kscience.dataforge.values.number +import space.kscience.dataforge.values.double import kotlin.test.Test import kotlin.test.assertEquals + fun Meta.toByteArray(format: MetaFormat = JsonMetaFormat) = buildByteArray { format.writeObject(this@buildByteArray, this@toByteArray) } @@ -17,20 +17,6 @@ fun MetaFormat.fromByteArray(packet: ByteArray): Meta { } class MetaFormatTest { - @Test - fun testBinaryMetaFormat() { - val meta = Meta { - "a" put 22 - "node" put { - "b" put "DDD" - "c" put 11.1 - "array" put doubleArrayOf(1.0, 2.0, 3.0) - } - } - val bytes = meta.toByteArray(BinaryMetaFormat) - val result = BinaryMetaFormat.fromByteArray(bytes) - assertEquals(meta, result) - } @Test fun testJsonMetaFormat() { @@ -51,36 +37,36 @@ class MetaFormatTest { if (meta[it] != result[it]) error("${meta[it]} != ${result[it]}") } - assertEquals(meta, result) + assertEquals(meta, result) } @Test fun testJsonToMeta() { val json = buildJsonArray { //top level array - add(buildJsonArray { - add(JsonPrimitive(88)) - add(buildJsonObject { + addJsonArray { + add(88) + addJsonObject { put("c", "aasdad") put("d", true) - }) - }) + } + } add("value") - add(buildJsonArray { - add(JsonPrimitive(1.0)) - add(JsonPrimitive(2.0)) - add(JsonPrimitive(3.0)) - }) + addJsonArray { + add(1.0) + add(2.0) + add(3.0) + } } - val meta = json.toMetaItem().node!! + val meta = json.toMeta() - assertEquals(true, meta["$JSON_ARRAY_KEY[0].$JSON_ARRAY_KEY[1].d"].boolean) - assertEquals("value", meta["$JSON_ARRAY_KEY[1]"].string) - assertEquals(listOf(1.0, 2.0, 3.0), meta["$JSON_ARRAY_KEY[2"].value?.list?.map { it.number.toDouble() }) + assertEquals(true, meta["${Meta.JSON_ARRAY_KEY}[0].${Meta.JSON_ARRAY_KEY}[1].d"].boolean) + assertEquals("value", meta["${Meta.JSON_ARRAY_KEY}[1]"].string) + assertEquals(listOf(1.0, 2.0, 3.0), meta["${Meta.JSON_ARRAY_KEY}[2]"]?.value?.list?.map { it.double }) } @Test - fun testJsonStringToMeta(){ + fun testJsonStringToMeta() { val jsonString = """ { "comments": [ @@ -98,8 +84,8 @@ class MetaFormatTest { } """.trimIndent() val json = Json.parseToJsonElement(jsonString) - val meta = json.toMetaItem().node!! - assertEquals(ListValue.EMPTY, meta["comments"].value) + val meta = json.toMeta() + assertEquals(ListValue.EMPTY, meta["comments"]?.value) } } \ No newline at end of file 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 5abd6a5e..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 @@ -5,9 +5,8 @@ import kotlinx.serialization.cbor.Cbor import kotlinx.serialization.json.Json import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.MetaSerializer -import space.kscience.dataforge.meta.TypedMetaItem +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 @@ -28,7 +27,7 @@ class MetaSerializerTest { fun testMetaSerialization() { val string = JSON_PRETTY.encodeToString(MetaSerializer, meta) println(string) - val restored = JSON_PLAIN.decodeFromString(MetaSerializer, string) + val restored = JSON_PLAIN.decodeFromString(MetaSerializer, string).seal() assertEquals(meta, restored) } @@ -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) @@ -52,7 +51,7 @@ class MetaSerializerTest { @OptIn(ExperimentalSerializationApi::class) @Test fun testMetaItemDescriptor() { - val descriptor = TypedMetaItem.serializer(MetaSerializer).descriptor.getElementDescriptor(0) + val descriptor = MetaSerializer.descriptor.getElementDescriptor(0) println(descriptor) } } \ No newline at end of file diff --git a/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/fileIO.kt b/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/fileIO.kt index 454c81fe..05296047 100644 --- a/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/fileIO.kt +++ b/dataforge-io/src/jvmMain/kotlin/space/kscience/dataforge/io/fileIO.kt @@ -3,7 +3,7 @@ package space.kscience.dataforge.io import io.ktor.utils.io.core.* import io.ktor.utils.io.streams.asOutput import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.descriptors.NodeDescriptor +import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.meta.isEmpty import space.kscience.dataforge.misc.DFExperimental import java.nio.file.Files @@ -97,7 +97,7 @@ public inline fun IOPlugin.resolveIOFormat(): IOFormat? { public fun IOPlugin.readMetaFile( path: Path, formatOverride: MetaFormat? = null, - descriptor: NodeDescriptor? = null, + descriptor: MetaDescriptor? = null, ): Meta { if (!Files.exists(path)) error("Meta file $path does not exist") @@ -125,7 +125,7 @@ public fun IOPlugin.writeMetaFile( path: Path, meta: Meta, metaFormat: MetaFormatFactory = JsonMetaFormat, - descriptor: NodeDescriptor? = null, + descriptor: MetaDescriptor? = null, ) { val actualPath = if (Files.isDirectory(path)) { path.resolve("@" + metaFormat.name.toString()) diff --git a/dataforge-meta/api/dataforge-meta.api b/dataforge-meta/api/dataforge-meta.api index e3572ca2..d1792538 100644 --- a/dataforge-meta/api/dataforge-meta.api +++ b/dataforge-meta/api/dataforge-meta.api @@ -1,153 +1,38 @@ -public abstract class space/kscience/dataforge/meta/AbstractMutableMeta : space/kscience/dataforge/meta/AbstractTypedMeta, space/kscience/dataforge/meta/MutableMeta { - public fun ()V - protected final fun getChildren ()Ljava/util/Map; - public fun getItems ()Ljava/util/Map; - protected fun replaceItem (Lspace/kscience/dataforge/names/NameToken;Lspace/kscience/dataforge/meta/TypedMetaItem;Lspace/kscience/dataforge/meta/TypedMetaItem;)V - public fun setItem (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/TypedMetaItem;)V - protected abstract fun wrapNode (Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/MutableMeta; -} - -public abstract class space/kscience/dataforge/meta/AbstractTypedMeta : space/kscience/dataforge/meta/MetaBase, space/kscience/dataforge/meta/TypedMeta { - public fun ()V -} - -public final class space/kscience/dataforge/meta/Config : space/kscience/dataforge/meta/AbstractMutableMeta, space/kscience/dataforge/meta/ItemPropertyProvider { - public static final field ConfigSerializer Lspace/kscience/dataforge/meta/Config$ConfigSerializer; - public fun ()V - public synthetic fun empty$dataforge_meta ()Lspace/kscience/dataforge/meta/MutableMeta; - public fun onChange (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)V - public fun removeListener (Ljava/lang/Object;)V - public synthetic fun wrapNode (Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/MutableMeta; -} - -public final class space/kscience/dataforge/meta/Config$ConfigSerializer : kotlinx/serialization/KSerializer { - public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; - public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lspace/kscience/dataforge/meta/Config; - public final fun empty ()Lspace/kscience/dataforge/meta/Config; - public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; - public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V - public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lspace/kscience/dataforge/meta/Config;)V - public final fun serializer ()Lkotlinx/serialization/KSerializer; -} - -public final class space/kscience/dataforge/meta/ConfigKt { - public static final fun asConfig (Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/Config; - public static final fun copy (Lspace/kscience/dataforge/meta/Config;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/Config; - public static synthetic fun copy$default (Lspace/kscience/dataforge/meta/Config;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/Config; - public static final fun get (Lspace/kscience/dataforge/meta/Config;Lspace/kscience/dataforge/names/NameToken;)Lspace/kscience/dataforge/meta/TypedMetaItem; - public static final fun toConfig (Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/Config; -} - public abstract interface class space/kscience/dataforge/meta/Configurable { - public abstract fun getConfig ()Lspace/kscience/dataforge/meta/Config; + public abstract fun getMeta ()Lspace/kscience/dataforge/meta/MutableMeta; } public final class space/kscience/dataforge/meta/ConfigurableKt { - public static final fun config (Lspace/kscience/dataforge/meta/Configurable;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun config$default (Lspace/kscience/dataforge/meta/Configurable;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; public static final fun configure (Lspace/kscience/dataforge/meta/Configurable;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/Configurable; public static final fun configure (Lspace/kscience/dataforge/meta/Configurable;Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/Configurable; } -public final class space/kscience/dataforge/meta/ItemDelegateKt { - public static final fun boolean (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun boolean (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty; - public static final fun boolean (Lspace/kscience/dataforge/meta/ItemProvider;ZLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/ItemProvider;ZLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun convert (Lkotlin/properties/ReadOnlyProperty;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadOnlyProperty; - public static final fun convert (Lkotlin/properties/ReadOnlyProperty;Lspace/kscience/dataforge/meta/transformations/MetaConverter;)Lkotlin/properties/ReadOnlyProperty; - public static final fun convert (Lkotlin/properties/ReadOnlyProperty;Lspace/kscience/dataforge/meta/transformations/MetaConverter;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty; - public static final fun double (Lspace/kscience/dataforge/meta/ItemProvider;DLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun double (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun double$default (Lspace/kscience/dataforge/meta/ItemProvider;DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun double$default (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun float (Lspace/kscience/dataforge/meta/ItemProvider;FLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun float (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun float$default (Lspace/kscience/dataforge/meta/ItemProvider;FLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun float$default (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun int (Lspace/kscience/dataforge/meta/ItemProvider;ILspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun int (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun int$default (Lspace/kscience/dataforge/meta/ItemProvider;ILspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun int$default (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun item (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun item$default (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun long (Lspace/kscience/dataforge/meta/ItemProvider;JLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun long (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun long$default (Lspace/kscience/dataforge/meta/ItemProvider;JLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun long$default (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun node (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun node$default (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun number (Lspace/kscience/dataforge/meta/ItemProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun number (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun number (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun number$default (Lspace/kscience/dataforge/meta/ItemProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun number$default (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun number$default (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun string (Lspace/kscience/dataforge/meta/ItemProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun string (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static final fun string (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun string$default (Lspace/kscience/dataforge/meta/ItemProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun string$default (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun string$default (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; - public static final fun value (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; - public static synthetic fun value$default (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; -} - -public abstract interface class space/kscience/dataforge/meta/ItemPropertyProvider : space/kscience/dataforge/meta/MutableItemProvider, space/kscience/dataforge/meta/ObservableItemProvider { -} - -public abstract interface class space/kscience/dataforge/meta/ItemProvider { - public static final field Companion Lspace/kscience/dataforge/meta/ItemProvider$Companion; - public abstract fun getItem (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMetaItem; -} - -public final class space/kscience/dataforge/meta/ItemProvider$Companion { - public final fun getEMPTY ()Lspace/kscience/dataforge/meta/ItemProvider; -} - -public final class space/kscience/dataforge/meta/ItemProviderKt { - public static final fun get (Lspace/kscience/dataforge/meta/ItemProvider;Ljava/lang/String;)Lspace/kscience/dataforge/meta/TypedMetaItem; - public static final fun get (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMetaItem; - public static final fun getChild (Lspace/kscience/dataforge/meta/ItemProvider;Ljava/lang/String;)Lspace/kscience/dataforge/meta/ItemProvider; - public static final fun getChild (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/ItemProvider; - public static final fun getIndexed (Lspace/kscience/dataforge/meta/ItemProvider;Ljava/lang/String;)Ljava/util/Map; - public static final fun getIndexed (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;)Ljava/util/Map; - public static final fun getRootItem (Lspace/kscience/dataforge/meta/ItemProvider;)Lspace/kscience/dataforge/meta/TypedMetaItem; - public static final fun getRootNode (Lspace/kscience/dataforge/meta/ItemProvider;)Lspace/kscience/dataforge/meta/Meta; - public static final fun withDefault (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/meta/ItemProvider;)Lspace/kscience/dataforge/meta/ItemProvider; -} - -public final class space/kscience/dataforge/meta/JsonMeta : space/kscience/dataforge/meta/MetaBase { - public static final field Companion Lspace/kscience/dataforge/meta/JsonMeta$Companion; - public static final field JSON_ARRAY_KEY Ljava/lang/String; - public fun (Lkotlinx/serialization/json/JsonObject;Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;)V - public synthetic fun (Lkotlinx/serialization/json/JsonObject;Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public fun getItems ()Ljava/util/Map; -} - -public final class space/kscience/dataforge/meta/JsonMeta$Companion { -} - public final class space/kscience/dataforge/meta/JsonMetaKt { - public static final fun toJson (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;)Lkotlinx/serialization/json/JsonObject; - public static final fun toJson (Lspace/kscience/dataforge/values/Value;Lspace/kscience/dataforge/meta/descriptors/ValueDescriptor;)Lkotlinx/serialization/json/JsonElement; - public static synthetic fun toJson$default (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Lkotlinx/serialization/json/JsonObject; - public static synthetic fun toJson$default (Lspace/kscience/dataforge/values/Value;Lspace/kscience/dataforge/meta/descriptors/ValueDescriptor;ILjava/lang/Object;)Lkotlinx/serialization/json/JsonElement; - public static final fun toMeta (Lkotlinx/serialization/json/JsonObject;Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;)Lspace/kscience/dataforge/meta/JsonMeta; - public static synthetic fun toMeta$default (Lkotlinx/serialization/json/JsonObject;Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/JsonMeta; - public static final fun toMetaItem (Lkotlinx/serialization/json/JsonElement;Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor;)Lspace/kscience/dataforge/meta/TypedMetaItem; - public static synthetic fun toMetaItem$default (Lkotlinx/serialization/json/JsonElement;Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/TypedMetaItem; - public static final fun toValue (Lkotlinx/serialization/json/JsonPrimitive;Lspace/kscience/dataforge/meta/descriptors/ValueDescriptor;)Lspace/kscience/dataforge/values/Value; + public static final fun getJSON_ARRAY_KEY (Lspace/kscience/dataforge/meta/Meta$Companion;)Ljava/lang/String; + public static final fun toJson (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lkotlinx/serialization/json/JsonObject; + public static final fun toJson (Lspace/kscience/dataforge/values/Value;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lkotlinx/serialization/json/JsonElement; + public static synthetic fun toJson$default (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lkotlinx/serialization/json/JsonObject; + public static synthetic fun toJson$default (Lspace/kscience/dataforge/values/Value;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lkotlinx/serialization/json/JsonElement; + public static final fun toMeta (Lkotlinx/serialization/json/JsonElement;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lspace/kscience/dataforge/meta/SealedMeta; + public static final fun toMeta (Lkotlinx/serialization/json/JsonObject;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lspace/kscience/dataforge/meta/SealedMeta; + public static synthetic fun toMeta$default (Lkotlinx/serialization/json/JsonElement;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/SealedMeta; + public static synthetic fun toMeta$default (Lkotlinx/serialization/json/JsonObject;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/SealedMeta; + public static final fun toValue (Lkotlinx/serialization/json/JsonPrimitive;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Lspace/kscience/dataforge/values/Value; } -public final class space/kscience/dataforge/meta/Laminate : space/kscience/dataforge/meta/MetaBase { +public final class space/kscience/dataforge/meta/Laminate : space/kscience/dataforge/meta/TypedMeta { public static final field Companion Lspace/kscience/dataforge/meta/Laminate$Companion; - public fun (Ljava/util/List;)V + public fun equals (Ljava/lang/Object;)Z public fun getItems ()Ljava/util/Map; public final fun getLayers ()Ljava/util/List; + public fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Laminate; + public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; + public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMeta; + public fun getValue ()Lspace/kscience/dataforge/values/Value; + public fun hashCode ()I public final fun merge ()Lspace/kscience/dataforge/meta/SealedMeta; + public fun toString ()Ljava/lang/String; + public final fun top ()Lspace/kscience/dataforge/meta/SealedMeta; } public final class space/kscience/dataforge/meta/Laminate$Companion { @@ -156,136 +41,122 @@ public final class space/kscience/dataforge/meta/Laminate$Companion { } public final class space/kscience/dataforge/meta/LaminateKt { + public static final fun Laminate (Ljava/util/Collection;)Lspace/kscience/dataforge/meta/Laminate; public static final fun Laminate ([Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/Laminate; - public static final fun getFirst (Lspace/kscience/dataforge/meta/Laminate;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMetaItem; + public static final fun getFirst (Lspace/kscience/dataforge/meta/Laminate;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; public static final fun withBottom (Lspace/kscience/dataforge/meta/Laminate;Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/Laminate; public static final fun withTop (Lspace/kscience/dataforge/meta/Laminate;Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/Laminate; } public final class space/kscience/dataforge/meta/MapMetaKt { - public static final fun toMap (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;)Ljava/util/Map; - public static synthetic fun toMap$default (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Ljava/util/Map; - public static synthetic fun toMeta$default (Ljava/util/Map;Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/Meta; + public static final fun toMap (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Ljava/util/Map; + public static synthetic fun toMap$default (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Ljava/util/Map; + public static synthetic fun toMeta$default (Ljava/util/Map;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/Meta; } -public abstract interface class space/kscience/dataforge/meta/Meta : space/kscience/dataforge/meta/ItemProvider, space/kscience/dataforge/meta/MetaRepr { +public abstract interface class space/kscience/dataforge/meta/Meta : space/kscience/dataforge/meta/MetaProvider, space/kscience/dataforge/meta/MetaRepr { public static final field Companion Lspace/kscience/dataforge/meta/Meta$Companion; + public static final field INDEX_KEY Ljava/lang/String; public static final field TYPE Ljava/lang/String; public static final field VALUE_KEY Ljava/lang/String; public abstract fun equals (Ljava/lang/Object;)Z - public fun getItem (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMetaItem; public abstract fun getItems ()Ljava/util/Map; + public fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; + public abstract fun getValue ()Lspace/kscience/dataforge/values/Value; public abstract fun hashCode ()I public fun toMeta ()Lspace/kscience/dataforge/meta/Meta; public abstract fun toString ()Ljava/lang/String; } public final class space/kscience/dataforge/meta/Meta$Companion { + public static final field INDEX_KEY Ljava/lang/String; public static final field TYPE Ljava/lang/String; public static final field VALUE_KEY Ljava/lang/String; public final fun equals (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/Meta;)Z public final fun getEMPTY ()Lspace/kscience/dataforge/meta/Meta; + public final fun hashCode (Lspace/kscience/dataforge/meta/Meta;)I + public final fun toString (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/String; } -public abstract class space/kscience/dataforge/meta/MetaBase : space/kscience/dataforge/meta/Meta { - public fun ()V - public fun equals (Ljava/lang/Object;)Z - public fun hashCode ()I - public fun toString ()Ljava/lang/String; +public abstract interface annotation class space/kscience/dataforge/meta/MetaBuilder : java/lang/annotation/Annotation { } -public final class space/kscience/dataforge/meta/MetaBuilder : space/kscience/dataforge/meta/AbstractMutableMeta { - public fun ()V - public synthetic fun empty$dataforge_meta ()Lspace/kscience/dataforge/meta/MutableMeta; - public final fun put (Ljava/lang/String;Ljava/lang/Boolean;)V - public final fun put (Ljava/lang/String;Ljava/lang/Enum;)V - public final fun put (Ljava/lang/String;Ljava/lang/Number;)V - public final fun put (Ljava/lang/String;Ljava/lang/String;)V - public final fun put (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V - public final fun put (Ljava/lang/String;Lspace/kscience/dataforge/meta/Meta;)V - public final fun put (Ljava/lang/String;Lspace/kscience/dataforge/meta/MetaRepr;)V - public final fun put (Ljava/lang/String;Lspace/kscience/dataforge/meta/TypedMetaItem;)V - public final fun put (Ljava/lang/String;Lspace/kscience/dataforge/values/Value;)V - public final fun put (Ljava/lang/String;[D)V - public final fun put (Lspace/kscience/dataforge/names/Name;Ljava/lang/Boolean;)V - public final fun put (Lspace/kscience/dataforge/names/Name;Ljava/lang/Enum;)V - public final fun put (Lspace/kscience/dataforge/names/Name;Ljava/lang/Number;)V - public final fun put (Lspace/kscience/dataforge/names/Name;Ljava/lang/String;)V - public final fun put (Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V - public final fun put (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)V - public final fun put (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaRepr;)V - public final fun put (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/values/Value;)V - public final fun putMetas (Ljava/lang/String;Ljava/lang/Iterable;)V - public final fun putMetas (Lspace/kscience/dataforge/names/Name;Ljava/lang/Iterable;)V - public final fun putNumbers (Ljava/lang/String;Ljava/lang/Iterable;)V - public final fun putStrings (Ljava/lang/String;Ljava/lang/Iterable;)V - public final fun putValues (Ljava/lang/String;Ljava/lang/Iterable;)V - public final fun putValues (Lspace/kscience/dataforge/names/Name;Ljava/lang/Iterable;)V - public synthetic fun wrapNode (Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/MutableMeta; -} - -public final class space/kscience/dataforge/meta/MetaBuilderKt { - public static final fun Meta (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/MetaBuilder; - public static final fun toMutableMeta (Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/MetaBuilder; -} - -public final class space/kscience/dataforge/meta/MetaItemKt { - public static final fun asMetaItem (Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/MetaItemNode; - public static final fun asMetaItem (Lspace/kscience/dataforge/values/Value;)Lspace/kscience/dataforge/meta/MetaItemValue; - public static final fun getBoolean (Lspace/kscience/dataforge/meta/TypedMetaItem;)Ljava/lang/Boolean; - public static final fun getDouble (Lspace/kscience/dataforge/meta/TypedMetaItem;)Ljava/lang/Double; - public static final fun getFloat (Lspace/kscience/dataforge/meta/TypedMetaItem;)Ljava/lang/Float; - public static final fun getInt (Lspace/kscience/dataforge/meta/TypedMetaItem;)Ljava/lang/Integer; - public static final fun getLong (Lspace/kscience/dataforge/meta/TypedMetaItem;)Ljava/lang/Long; - public static final fun getNode (Lspace/kscience/dataforge/meta/TypedMetaItem;)Lspace/kscience/dataforge/meta/Meta; - public static final fun getNumber (Lspace/kscience/dataforge/meta/TypedMetaItem;)Ljava/lang/Number; - public static final fun getShort (Lspace/kscience/dataforge/meta/TypedMetaItem;)Ljava/lang/Short; - public static final fun getString (Lspace/kscience/dataforge/meta/TypedMetaItem;)Ljava/lang/String; - public static final fun getStringList (Lspace/kscience/dataforge/meta/TypedMetaItem;)Ljava/util/List; - public static final fun getValue (Lspace/kscience/dataforge/meta/TypedMetaItem;)Lspace/kscience/dataforge/values/Value; -} - -public final class space/kscience/dataforge/meta/MetaItemNode : space/kscience/dataforge/meta/TypedMetaItem { - public static final field Companion Lspace/kscience/dataforge/meta/MetaItemNode$Companion; - public fun (Lspace/kscience/dataforge/meta/Meta;)V - public fun equals (Ljava/lang/Object;)Z - public final fun getNode ()Lspace/kscience/dataforge/meta/Meta; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class space/kscience/dataforge/meta/MetaItemNode$Companion { - public final fun serializer (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer; -} - -public final class space/kscience/dataforge/meta/MetaItemSerializer : kotlinx/serialization/KSerializer { - public static final field INSTANCE Lspace/kscience/dataforge/meta/MetaItemSerializer; - public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; - public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lspace/kscience/dataforge/meta/TypedMetaItem; - public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; - public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V - public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lspace/kscience/dataforge/meta/TypedMetaItem;)V -} - -public final class space/kscience/dataforge/meta/MetaItemValue : space/kscience/dataforge/meta/TypedMetaItem { - public static final field Companion Lspace/kscience/dataforge/meta/MetaItemValue$Companion; - public fun (Lspace/kscience/dataforge/values/Value;)V - public fun equals (Ljava/lang/Object;)Z - public final fun getValue ()Lspace/kscience/dataforge/values/Value; - public fun hashCode ()I - public fun toString ()Ljava/lang/String; -} - -public final class space/kscience/dataforge/meta/MetaItemValue$Companion { - public final fun serializer ()Lkotlinx/serialization/KSerializer; +public final class space/kscience/dataforge/meta/MetaDelegateKt { + public static final fun boolean (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static final fun boolean (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty; + public static final fun boolean (Lspace/kscience/dataforge/meta/MetaProvider;ZLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MetaProvider;ZLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static final fun double (Lspace/kscience/dataforge/meta/MetaProvider;DLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static final fun double (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MetaProvider;DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static final fun float (Lspace/kscience/dataforge/meta/MetaProvider;FLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static final fun float (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MetaProvider;FLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static final fun int (Lspace/kscience/dataforge/meta/MetaProvider;ILspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static final fun int (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MetaProvider;ILspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static final fun long (Lspace/kscience/dataforge/meta/MetaProvider;JLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static final fun long (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MetaProvider;JLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static final fun node (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static final fun node (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/transformations/MetaConverter;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/transformations/MetaConverter;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static final fun number (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static final fun string (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static final fun value (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty; + public static final fun value (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; + public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty; } public final class space/kscience/dataforge/meta/MetaKt { - public static final fun get (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/names/NameToken;)Lspace/kscience/dataforge/meta/TypedMetaItem; + public static final fun get (Lspace/kscience/dataforge/meta/Meta;Ljava/lang/String;)Lspace/kscience/dataforge/meta/Meta; + public static final fun get (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; + public static final fun get (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/names/NameToken;)Lspace/kscience/dataforge/meta/Meta; + public static final fun get (Lspace/kscience/dataforge/meta/TypedMeta;Ljava/lang/String;)Lspace/kscience/dataforge/meta/TypedMeta; + public static final fun get (Lspace/kscience/dataforge/meta/TypedMeta;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMeta; + public static final fun get (Lspace/kscience/dataforge/meta/TypedMeta;Lspace/kscience/dataforge/names/NameToken;)Lspace/kscience/dataforge/meta/TypedMeta; + public static final fun getBoolean (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Boolean; + public static final fun getDouble (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Double; + public static final fun getFloat (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Float; + public static final fun getIndexed (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/names/Name;)Ljava/util/Map; + public static final fun getIndexed (Lspace/kscience/dataforge/meta/TypedMeta;Ljava/lang/String;)Ljava/util/Map; + public static final fun getIndexed (Lspace/kscience/dataforge/meta/TypedMeta;Lspace/kscience/dataforge/names/Name;)Ljava/util/Map; + public static final fun getInt (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Integer; + public static final fun getLong (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Long; + public static final fun getNumber (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Number; + public static final fun getSelf (Lspace/kscience/dataforge/meta/TypedMeta;)Lspace/kscience/dataforge/meta/TypedMeta; + public static final fun getShort (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Short; + public static final fun getString (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/String; + public static final fun getStringList (Lspace/kscience/dataforge/meta/Meta;)Ljava/util/List; public static final fun isEmpty (Lspace/kscience/dataforge/meta/Meta;)Z - public static final fun itemSequence (Lspace/kscience/dataforge/meta/Meta;)Lkotlin/sequences/Sequence; + public static final fun isLeaf (Lspace/kscience/dataforge/meta/Meta;)Z public static final fun iterator (Lspace/kscience/dataforge/meta/Meta;)Ljava/util/Iterator; + public static final fun nodeSequence (Lspace/kscience/dataforge/meta/Meta;)Lkotlin/sequences/Sequence; public static final fun valueSequence (Lspace/kscience/dataforge/meta/Meta;)Lkotlin/sequences/Sequence; + public static final fun withDefault (Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/Meta; +} + +public abstract interface class space/kscience/dataforge/meta/MetaProvider : space/kscience/dataforge/values/ValueProvider { + public abstract fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; + public fun getValue (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/values/Value; } public abstract interface class space/kscience/dataforge/meta/MetaRepr { @@ -301,323 +172,384 @@ public final class space/kscience/dataforge/meta/MetaSerializer : kotlinx/serial public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lspace/kscience/dataforge/meta/Meta;)V } -public final class space/kscience/dataforge/meta/MutableItemDelegateKt { - public static final fun boolean (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun boolean (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty; - public static final fun boolean (Lspace/kscience/dataforge/meta/MutableItemProvider;ZLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableItemProvider;ZLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun convert (Lkotlin/properties/ReadWriteProperty;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadWriteProperty; - public static final fun convert (Lkotlin/properties/ReadWriteProperty;Lspace/kscience/dataforge/meta/transformations/MetaConverter;)Lkotlin/properties/ReadWriteProperty; - public static final fun convert (Lkotlin/properties/ReadWriteProperty;Lspace/kscience/dataforge/meta/transformations/MetaConverter;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty; - public static final fun double (Lspace/kscience/dataforge/meta/MutableItemProvider;DLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun double (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MutableItemProvider;DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun doubleArray (Lspace/kscience/dataforge/meta/MutableItemProvider;[DLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun doubleArray$default (Lspace/kscience/dataforge/meta/MutableItemProvider;[DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun float (Lspace/kscience/dataforge/meta/MutableItemProvider;FLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun float (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MutableItemProvider;FLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun int (Lspace/kscience/dataforge/meta/MutableItemProvider;ILspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun int (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MutableItemProvider;ILspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun item (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun item$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun listValue (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun listValue$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun long (Lspace/kscience/dataforge/meta/MutableItemProvider;JLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun long (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MutableItemProvider;JLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun node (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun number (Lspace/kscience/dataforge/meta/MutableItemProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun number (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun number (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun numberList (Lspace/kscience/dataforge/meta/MutableItemProvider;[Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun numberList$default (Lspace/kscience/dataforge/meta/MutableItemProvider;[Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun string (Lspace/kscience/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun string (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun string (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun stringList (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun stringList (Lspace/kscience/dataforge/meta/MutableItemProvider;[Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun stringList$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun stringList$default (Lspace/kscience/dataforge/meta/MutableItemProvider;[Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun value (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static final fun value (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; -} - -public abstract interface class space/kscience/dataforge/meta/MutableItemProvider : space/kscience/dataforge/meta/ItemProvider { - public abstract fun setItem (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/TypedMetaItem;)V -} - -public final class space/kscience/dataforge/meta/MutableItemProviderKt { - public static final fun editChild (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/MutableItemProvider; - public static final fun getChild (Lspace/kscience/dataforge/meta/MutableItemProvider;Ljava/lang/String;)Lspace/kscience/dataforge/meta/MutableItemProvider; - public static final fun getChild (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableItemProvider; - public static final fun remove (Lspace/kscience/dataforge/meta/MutableItemProvider;Ljava/lang/String;)V - public static final fun remove (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;)V - public static final fun set (Lspace/kscience/dataforge/meta/MutableItemProvider;Ljava/lang/String;Ljava/lang/Iterable;)V - public static final fun set (Lspace/kscience/dataforge/meta/MutableItemProvider;Ljava/lang/String;Ljava/lang/Object;)V - public static final fun set (Lspace/kscience/dataforge/meta/MutableItemProvider;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V - public static final fun set (Lspace/kscience/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lspace/kscience/dataforge/meta/Meta;)V - public static final fun set (Lspace/kscience/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lspace/kscience/dataforge/meta/TypedMetaItem;)V - public static final fun set (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Ljava/lang/Iterable;)V - public static final fun set (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Ljava/lang/Object;)V - public static final fun set (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)V - public static final fun set (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/TypedMetaItem;)V - public static final fun set (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/values/Value;)V - public static final fun set (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/NameToken;Ljava/lang/Object;)V - public static final fun setIndexed (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V - public static synthetic fun setIndexed$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V - public static final fun setIndexedItems (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V - public static synthetic fun setIndexedItems$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V - public static final fun update (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/meta/Meta;)V - public static final fun withDefault (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/meta/ItemProvider;)Lspace/kscience/dataforge/meta/MutableItemProvider; -} - -public abstract interface class space/kscience/dataforge/meta/MutableMeta : space/kscience/dataforge/meta/MutableItemProvider, space/kscience/dataforge/meta/TypedMeta { +public abstract interface class space/kscience/dataforge/meta/MutableMeta : space/kscience/dataforge/meta/Meta, space/kscience/dataforge/meta/MutableMetaProvider { public abstract fun getItems ()Ljava/util/Map; + public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; + public fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMeta; + public abstract fun getOrCreate (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMeta; + public abstract fun getValue ()Lspace/kscience/dataforge/values/Value; + public fun put (Ljava/lang/String;Ljava/lang/Enum;)V + public fun put (Ljava/lang/String;Ljava/lang/Number;)V + public fun put (Ljava/lang/String;Ljava/lang/String;)V + public fun put (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V + public fun put (Ljava/lang/String;Lspace/kscience/dataforge/meta/Meta;)V + public fun put (Ljava/lang/String;Lspace/kscience/dataforge/meta/MetaRepr;)V + public fun put (Ljava/lang/String;Lspace/kscience/dataforge/values/Value;)V + public fun put (Ljava/lang/String;Z)V + public fun put (Ljava/lang/String;[D)V + public fun put (Lspace/kscience/dataforge/names/Name;Ljava/lang/Enum;)V + public fun put (Lspace/kscience/dataforge/names/Name;Ljava/lang/Number;)V + public fun put (Lspace/kscience/dataforge/names/Name;Ljava/lang/String;)V + public fun put (Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V + public fun put (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)V + public fun put (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/MetaRepr;)V + public fun put (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/values/Value;)V + public fun put (Lspace/kscience/dataforge/names/Name;Z)V + public fun putIndexed (Ljava/lang/String;Ljava/lang/Iterable;)V + public fun putIndexed (Lspace/kscience/dataforge/names/Name;Ljava/lang/Iterable;)V + public fun setValue (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/values/Value;)V + public abstract fun setValue (Lspace/kscience/dataforge/values/Value;)V +} + +public final class space/kscience/dataforge/meta/MutableMetaDelegateKt { + public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty; + public static final fun boolean (Lspace/kscience/dataforge/meta/MutableMetaProvider;ZLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun boolean$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;ZLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun double (Lspace/kscience/dataforge/meta/MutableMetaProvider;DLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static final fun double (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun double$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun doubleArray (Lspace/kscience/dataforge/meta/MutableMetaProvider;[DLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun doubleArray$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[DLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun float (Lspace/kscience/dataforge/meta/MutableMetaProvider;FLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static final fun float (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;FLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun float$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun int (Lspace/kscience/dataforge/meta/MutableMetaProvider;ILspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static final fun int (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;ILspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun int$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun listValue (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun listValue$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun long (Lspace/kscience/dataforge/meta/MutableMetaProvider;JLspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static final fun long (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;JLspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun long$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun node (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static final fun node (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/transformations/MetaConverter;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun node$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/transformations/MetaConverter;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun number (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static final fun number (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static final fun number (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun number$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun numberList (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun numberList$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/Number;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun string (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static final fun string (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static final fun string (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun string$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function0;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun stringList (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static final fun stringList (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/String;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun stringList$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun stringList$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;[Ljava/lang/String;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun value (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static final fun value (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun value$default (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; } public final class space/kscience/dataforge/meta/MutableMetaKt { - public static final fun append (Lspace/kscience/dataforge/meta/MutableItemProvider;Ljava/lang/String;Ljava/lang/Object;)V - public static final fun append (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/names/Name;Ljava/lang/Object;)V + public static final fun MutableMeta ()Lspace/kscience/dataforge/meta/ObservableMutableMeta; + public static final fun MutableMeta (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; + public static synthetic fun MutableMeta$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; + public static final fun append (Lspace/kscience/dataforge/meta/MutableMeta;Ljava/lang/String;Lspace/kscience/dataforge/meta/Meta;)V + public static final fun append (Lspace/kscience/dataforge/meta/MutableMeta;Ljava/lang/String;Lspace/kscience/dataforge/values/Value;)V + public static final fun append (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)V + public static final fun append (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/values/Value;)V + public static final fun asMutableMeta (Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/MutableMeta; + public static final fun copy (Lspace/kscience/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/Meta; + public static synthetic fun copy$default (Lspace/kscience/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/Meta; + public static final fun edit (Lspace/kscience/dataforge/meta/MutableTypedMeta;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/MutableTypedMeta; + public static final fun getOrCreate (Lspace/kscience/dataforge/meta/MutableMeta;Ljava/lang/String;)Lspace/kscience/dataforge/meta/MutableMeta; + public static final fun getOrCreate (Lspace/kscience/dataforge/meta/MutableTypedMeta;Ljava/lang/String;)Lspace/kscience/dataforge/meta/MutableTypedMeta; + public static final fun remove (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;)V + public static final fun remove (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/Name;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/lang/Iterable;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/lang/Number;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/lang/String;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/util/List;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Ljava/lang/String;Lspace/kscience/dataforge/values/Value;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Ljava/lang/String;Z)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/Name;Ljava/lang/Iterable;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/Name;Ljava/lang/Number;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/Name;Ljava/lang/String;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/Name;Ljava/util/List;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/values/Value;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/Name;Z)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/NameToken;Ljava/lang/Number;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/NameToken;Ljava/lang/String;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/NameToken;Ljava/util/List;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/NameToken;Lspace/kscience/dataforge/values/Value;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/NameToken;Z)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMetaProvider;Ljava/lang/String;Lspace/kscience/dataforge/meta/Meta;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableMetaProvider;Lspace/kscience/dataforge/names/NameToken;Lspace/kscience/dataforge/meta/Meta;)V + public static final fun set (Lspace/kscience/dataforge/meta/MutableTypedMeta;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/values/Value;)V + public static final fun setIndexed (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V + public static synthetic fun setIndexed$default (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V + public static final fun toMutableMeta (Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; + public static final fun update (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/Meta;)V + public static final fun withDefault (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/MutableMeta; } -public abstract interface class space/kscience/dataforge/meta/ObservableItemProvider : space/kscience/dataforge/meta/ItemProvider { - public abstract fun onChange (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)V +public abstract interface class space/kscience/dataforge/meta/MutableMetaProvider : space/kscience/dataforge/meta/MetaProvider, space/kscience/dataforge/values/MutableValueProvider { + public abstract fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMeta; + public abstract fun setMeta (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)V + public fun setValue (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/values/Value;)V +} + +public final class space/kscience/dataforge/meta/MutableMetaSerializer : kotlinx/serialization/KSerializer { + public static final field INSTANCE Lspace/kscience/dataforge/meta/MutableMetaSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lspace/kscience/dataforge/meta/MutableMeta; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lspace/kscience/dataforge/meta/MutableMeta;)V +} + +public abstract interface class space/kscience/dataforge/meta/MutableTypedMeta : space/kscience/dataforge/meta/MutableMeta, space/kscience/dataforge/meta/TypedMeta { + public abstract fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableTypedMeta; + public abstract fun getOrCreate (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableTypedMeta; +} + +public abstract interface class space/kscience/dataforge/meta/ObservableMeta : space/kscience/dataforge/meta/Meta { + public abstract fun invalidate (Lspace/kscience/dataforge/names/Name;)V + public abstract fun onChange (Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V public abstract fun removeListener (Ljava/lang/Object;)V } -public final class space/kscience/dataforge/meta/ObservableItemProviderKt { - public static synthetic fun useProperty$default (Lspace/kscience/dataforge/meta/ObservableItemProvider;Lkotlin/reflect/KProperty1;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V +public final class space/kscience/dataforge/meta/ObservableMetaKt { + public static final fun useProperty (Lspace/kscience/dataforge/meta/Scheme;Lkotlin/reflect/KProperty1;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V + public static synthetic fun useProperty$default (Lspace/kscience/dataforge/meta/Scheme;Lkotlin/reflect/KProperty1;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V +} + +public final class space/kscience/dataforge/meta/ObservableMetaWrapperKt { + public static final fun asObservable (Lspace/kscience/dataforge/meta/MutableMeta;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; +} + +public abstract interface class space/kscience/dataforge/meta/ObservableMutableMeta : space/kscience/dataforge/meta/MutableMeta, space/kscience/dataforge/meta/MutableTypedMeta, space/kscience/dataforge/meta/ObservableMeta { + public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; + public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMeta; + public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableTypedMeta; + public fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; + public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMeta; + public abstract fun getOrCreate (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/ObservableMutableMeta; } public abstract interface class space/kscience/dataforge/meta/ReadOnlySpecification { - public abstract fun empty ()Lspace/kscience/dataforge/meta/ItemProvider; - public fun invoke (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/ItemProvider; - public abstract fun read (Lspace/kscience/dataforge/meta/ItemProvider;)Lspace/kscience/dataforge/meta/ItemProvider; + public abstract fun empty ()Ljava/lang/Object; + public fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public abstract fun read (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Object; } -public class space/kscience/dataforge/meta/Scheme : space/kscience/dataforge/meta/ItemPropertyProvider, space/kscience/dataforge/meta/MetaRepr, space/kscience/dataforge/meta/descriptors/Described { +public class space/kscience/dataforge/meta/Scheme : space/kscience/dataforge/meta/Configurable, space/kscience/dataforge/meta/MetaRepr, space/kscience/dataforge/meta/MutableMetaProvider, space/kscience/dataforge/meta/descriptors/Described { public fun ()V - public fun getDefaultLayer ()Lspace/kscience/dataforge/meta/Meta; - public synthetic fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor; - public final fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor; - public fun getItem (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMetaItem; - public fun onChange (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)V - public fun removeListener (Ljava/lang/Object;)V - public final fun setDescriptor (Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;)V - public fun setItem (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/TypedMetaItem;)V + public final fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; + public synthetic fun getMeta ()Lspace/kscience/dataforge/meta/MutableMeta; + public final fun getMeta ()Lspace/kscience/dataforge/meta/ObservableMutableMeta; + public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; + public fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/MutableMeta; + public fun setMeta (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)V + public fun setValue (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/values/Value;)V public fun toMeta ()Lspace/kscience/dataforge/meta/Laminate; public synthetic fun toMeta ()Lspace/kscience/dataforge/meta/Meta; - public fun validateItem (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/TypedMetaItem;)Z + public fun validate (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)Z } public final class space/kscience/dataforge/meta/SchemeKt { public static final fun invoke (Lspace/kscience/dataforge/meta/Scheme;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/Scheme; - public static final fun isEmpty (Lspace/kscience/dataforge/meta/Scheme;)Z - public static final fun retarget (Lspace/kscience/dataforge/meta/Scheme;Lspace/kscience/dataforge/meta/MutableItemProvider;)Lspace/kscience/dataforge/meta/Scheme; - public static final fun wrap (Lspace/kscience/dataforge/meta/Specification;Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;)Lspace/kscience/dataforge/meta/Scheme; - public static synthetic fun wrap$default (Lspace/kscience/dataforge/meta/Specification;Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/Scheme; + public static final fun retarget (Lspace/kscience/dataforge/meta/Scheme;Lspace/kscience/dataforge/meta/MutableMeta;)Lspace/kscience/dataforge/meta/Scheme; } public class space/kscience/dataforge/meta/SchemeSpec : space/kscience/dataforge/meta/Specification, space/kscience/dataforge/meta/descriptors/Described { public fun (Lkotlin/jvm/functions/Function0;)V - public synthetic fun empty ()Lspace/kscience/dataforge/meta/ItemProvider; + public synthetic fun empty ()Ljava/lang/Object; public fun empty ()Lspace/kscience/dataforge/meta/Scheme; - public synthetic fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor; - public fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor; - public synthetic fun invoke (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/ItemProvider; + public fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; + public synthetic fun invoke (Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; public final fun invoke (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/Scheme; - public synthetic fun read (Lspace/kscience/dataforge/meta/ItemProvider;)Lspace/kscience/dataforge/meta/ItemProvider; - public fun read (Lspace/kscience/dataforge/meta/ItemProvider;)Lspace/kscience/dataforge/meta/Scheme; - public synthetic fun write (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/meta/ItemProvider;)Lspace/kscience/dataforge/meta/MutableItemProvider; - public fun write (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/meta/ItemProvider;)Lspace/kscience/dataforge/meta/Scheme; + public synthetic fun read (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Object; + public fun read (Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/Scheme; + public synthetic fun write (Lspace/kscience/dataforge/meta/MutableMeta;)Ljava/lang/Object; + public fun write (Lspace/kscience/dataforge/meta/MutableMeta;)Lspace/kscience/dataforge/meta/Scheme; } -public final class space/kscience/dataforge/meta/SealedMeta : space/kscience/dataforge/meta/AbstractTypedMeta { +public final class space/kscience/dataforge/meta/SealedMeta : space/kscience/dataforge/meta/TypedMeta { + public static final field Companion Lspace/kscience/dataforge/meta/SealedMeta$Companion; + public synthetic fun (ILspace/kscience/dataforge/values/Value;Ljava/util/Map;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V + public fun equals (Ljava/lang/Object;)Z public fun getItems ()Ljava/util/Map; + public fun getValue ()Lspace/kscience/dataforge/values/Value; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; + public static final fun write$Self (Lspace/kscience/dataforge/meta/SealedMeta;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V +} + +public final class space/kscience/dataforge/meta/SealedMeta$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lspace/kscience/dataforge/meta/SealedMeta$$serializer; + public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor; + public fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lspace/kscience/dataforge/meta/SealedMeta; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lspace/kscience/dataforge/meta/SealedMeta;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; +} + +public final class space/kscience/dataforge/meta/SealedMeta$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; } public final class space/kscience/dataforge/meta/SealedMetaKt { + public static final fun Meta (Ljava/lang/Number;)Lspace/kscience/dataforge/meta/SealedMeta; + public static final fun Meta (Ljava/lang/String;)Lspace/kscience/dataforge/meta/SealedMeta; + public static final fun Meta (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/SealedMeta; + public static final fun Meta (Lspace/kscience/dataforge/values/Value;)Lspace/kscience/dataforge/meta/SealedMeta; + public static final fun Meta (Z)Lspace/kscience/dataforge/meta/SealedMeta; public static final fun seal (Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/SealedMeta; - public static final fun seal (Lspace/kscience/dataforge/meta/TypedMetaItem;)Lspace/kscience/dataforge/meta/TypedMetaItem; } public abstract interface class space/kscience/dataforge/meta/Specification : space/kscience/dataforge/meta/ReadOnlySpecification { - public abstract fun write (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/meta/ItemProvider;)Lspace/kscience/dataforge/meta/MutableItemProvider; - public static synthetic fun write$default (Lspace/kscience/dataforge/meta/Specification;Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/meta/ItemProvider;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/MutableItemProvider; + public abstract fun write (Lspace/kscience/dataforge/meta/MutableMeta;)Ljava/lang/Object; } public final class space/kscience/dataforge/meta/SpecificationKt { - public static final fun spec (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/meta/Specification;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; - public static synthetic fun spec$default (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/meta/Specification;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; - public static final fun update (Lspace/kscience/dataforge/meta/Configurable;Lspace/kscience/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)V - public static final fun update (Lspace/kscience/dataforge/meta/MutableItemProvider;Lspace/kscience/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)V - public static final fun withSpec (Lspace/kscience/dataforge/meta/TypedMetaItem;Lspace/kscience/dataforge/meta/Specification;)Lspace/kscience/dataforge/meta/MutableItemProvider; + public static synthetic fun listOfSpec$default (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/Specification;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun spec (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/Specification;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static final fun spec (Lspace/kscience/dataforge/meta/Scheme;Lspace/kscience/dataforge/meta/Specification;Lspace/kscience/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun spec$default (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/Specification;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static synthetic fun spec$default (Lspace/kscience/dataforge/meta/Scheme;Lspace/kscience/dataforge/meta/Specification;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty; + public static final fun updateWith (Lspace/kscience/dataforge/meta/Configurable;Lspace/kscience/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; + public static final fun updateWith (Lspace/kscience/dataforge/meta/MutableMeta;Lspace/kscience/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Ljava/lang/Object; } public abstract interface class space/kscience/dataforge/meta/TypedMeta : space/kscience/dataforge/meta/Meta { - public fun getItem (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMetaItem; public abstract fun getItems ()Ljava/util/Map; -} - -public abstract class space/kscience/dataforge/meta/TypedMetaItem { - public static final field Companion Lspace/kscience/dataforge/meta/TypedMetaItem$Companion; - public abstract fun equals (Ljava/lang/Object;)Z - public abstract fun hashCode ()I -} - -public final class space/kscience/dataforge/meta/TypedMetaItem$Companion { - public final fun of (Ljava/lang/Object;)Lspace/kscience/dataforge/meta/TypedMetaItem; - public final fun serializer (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer; -} - -public final class space/kscience/dataforge/meta/TypedMetaKt { - public static final fun get (Lspace/kscience/dataforge/meta/TypedMeta;Ljava/lang/String;)Lspace/kscience/dataforge/meta/TypedMetaItem; - public static final fun get (Lspace/kscience/dataforge/meta/TypedMeta;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMetaItem; - public static final fun get (Lspace/kscience/dataforge/meta/TypedMeta;Lspace/kscience/dataforge/names/NameToken;)Lspace/kscience/dataforge/meta/TypedMetaItem; -} - -public abstract interface class space/kscience/dataforge/meta/descriptors/Described { - public static final field Companion Lspace/kscience/dataforge/meta/descriptors/Described$Companion; - public abstract fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor; -} - -public final class space/kscience/dataforge/meta/descriptors/Described$Companion { -} - -public final class space/kscience/dataforge/meta/descriptors/DescriptorMetaKt { - public static final fun defaultItem (Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor;)Lspace/kscience/dataforge/meta/TypedMetaItem; - public static final fun defaultMeta (Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;)Lspace/kscience/dataforge/meta/Laminate; -} - -public abstract interface class space/kscience/dataforge/meta/descriptors/ItemDescriptor : space/kscience/dataforge/meta/MetaRepr { - public static final field Companion Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor$Companion; - public static final field DEFAULT_INDEX_KEY Ljava/lang/String; - public abstract fun getAttributes ()Lspace/kscience/dataforge/meta/Meta; - public abstract fun getIndexKey ()Ljava/lang/String; - public abstract fun getInfo ()Ljava/lang/String; - public abstract fun getMultiple ()Z - public abstract fun getRequired ()Z -} - -public final class space/kscience/dataforge/meta/descriptors/ItemDescriptor$Companion { - public static final field DEFAULT_INDEX_KEY Ljava/lang/String; -} - -public abstract class space/kscience/dataforge/meta/descriptors/ItemDescriptorBuilder : space/kscience/dataforge/meta/Configurable, space/kscience/dataforge/meta/descriptors/ItemDescriptor { - public static final field Companion Lspace/kscience/dataforge/meta/descriptors/ItemDescriptorBuilder$Companion; - public static final field DEFAULT_INDEX_KEY Ljava/lang/String; - public synthetic fun (Lspace/kscience/dataforge/meta/Config;Lkotlin/jvm/internal/DefaultConstructorMarker;)V - public abstract fun build ()Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor; - public fun getAttributes ()Lspace/kscience/dataforge/meta/Config; - public synthetic fun getAttributes ()Lspace/kscience/dataforge/meta/Meta; - public final fun getConfig ()Lspace/kscience/dataforge/meta/Config; - public fun getIndexKey ()Ljava/lang/String; - public fun getInfo ()Ljava/lang/String; - public fun getMultiple ()Z - public abstract fun getRequired ()Z - public fun setAttributes (Lspace/kscience/dataforge/meta/Config;)V - public fun setIndexKey (Ljava/lang/String;)V - public fun setInfo (Ljava/lang/String;)V - public fun setMultiple (Z)V - public abstract fun setRequired (Z)V + public synthetic fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/Meta; + public fun getMeta (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMeta; public fun toMeta ()Lspace/kscience/dataforge/meta/Meta; } -public final class space/kscience/dataforge/meta/descriptors/ItemDescriptorBuilder$Companion { +public abstract interface class space/kscience/dataforge/meta/descriptors/Described { + public abstract fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; } -public final class space/kscience/dataforge/meta/descriptors/ItemDescriptorKt { - public static final fun attributes (Lspace/kscience/dataforge/meta/descriptors/ItemDescriptorBuilder;Lkotlin/jvm/functions/Function1;)V - public static final fun get (Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor;Ljava/lang/String;)Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor; - public static final fun get (Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor; - public static final fun validateItem (Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor;Lspace/kscience/dataforge/meta/TypedMetaItem;)Z -} - -public abstract interface class space/kscience/dataforge/meta/descriptors/NodeDescriptor : space/kscience/dataforge/meta/descriptors/ItemDescriptor { - public static final field Companion Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor$Companion; - public abstract fun getDefault ()Lspace/kscience/dataforge/meta/Config; - public abstract fun getItems ()Ljava/util/Map; - public abstract fun getNodes ()Ljava/util/Map; - public abstract fun getRequired ()Z - public abstract fun getValues ()Ljava/util/Map; -} - -public final class space/kscience/dataforge/meta/descriptors/NodeDescriptor$Companion { -} - -public final class space/kscience/dataforge/meta/descriptors/NodeDescriptorBuilder : space/kscience/dataforge/meta/descriptors/ItemDescriptorBuilder, space/kscience/dataforge/meta/descriptors/NodeDescriptor { - public static final field Companion Lspace/kscience/dataforge/meta/descriptors/NodeDescriptorBuilder$Companion; +public final class space/kscience/dataforge/meta/descriptors/MetaDescriptor { + public static final field Companion Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor$Companion; public fun ()V - public fun (Lspace/kscience/dataforge/meta/Config;)V - public synthetic fun (Lspace/kscience/dataforge/meta/Config;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public synthetic fun build ()Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor; - public fun build ()Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor; - public fun getDefault ()Lspace/kscience/dataforge/meta/Config; - public fun getItems ()Ljava/util/Map; - public fun getNodes ()Ljava/util/Map; - public fun getRequired ()Z - public fun getValues ()Ljava/util/Map; - public final fun item (Ljava/lang/String;Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor;)V - public final fun item (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor;)V - public final fun node (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V - public final fun node (Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V - public fun setDefault (Lspace/kscience/dataforge/meta/Config;)V - public fun setRequired (Z)V - public final fun value (Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V - public final fun value (Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V + public synthetic fun (ILjava/lang/String;Ljava/util/Map;ZLspace/kscience/dataforge/meta/descriptors/ValueRequirement;Ljava/util/List;Ljava/lang/String;Lspace/kscience/dataforge/values/Value;Lspace/kscience/dataforge/meta/Meta;Lkotlinx/serialization/internal/SerializationConstructorMarker;)V + public fun (Ljava/lang/String;Ljava/util/Map;ZLspace/kscience/dataforge/meta/descriptors/ValueRequirement;Ljava/util/List;Ljava/lang/String;Lspace/kscience/dataforge/values/Value;Lspace/kscience/dataforge/meta/Meta;)V + public synthetic fun (Ljava/lang/String;Ljava/util/Map;ZLspace/kscience/dataforge/meta/descriptors/ValueRequirement;Ljava/util/List;Ljava/lang/String;Lspace/kscience/dataforge/values/Value;Lspace/kscience/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V + public final fun component1 ()Ljava/lang/String; + public final fun component2 ()Ljava/util/Map; + public final fun component3 ()Z + public final fun component4 ()Lspace/kscience/dataforge/meta/descriptors/ValueRequirement; + public final fun component5 ()Ljava/util/List; + public final fun component6 ()Ljava/lang/String; + public final fun component7 ()Lspace/kscience/dataforge/values/Value; + public final fun component8 ()Lspace/kscience/dataforge/meta/Meta; + public final fun copy (Ljava/lang/String;Ljava/util/Map;ZLspace/kscience/dataforge/meta/descriptors/ValueRequirement;Ljava/util/List;Ljava/lang/String;Lspace/kscience/dataforge/values/Value;Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; + public static synthetic fun copy$default (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Ljava/lang/String;Ljava/util/Map;ZLspace/kscience/dataforge/meta/descriptors/ValueRequirement;Ljava/util/List;Ljava/lang/String;Lspace/kscience/dataforge/values/Value;Lspace/kscience/dataforge/meta/Meta;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; + public fun equals (Ljava/lang/Object;)Z + public final fun getAttributes ()Lspace/kscience/dataforge/meta/Meta; + public final fun getChildren ()Ljava/util/Map; + public final fun getDefaultNode ()Lspace/kscience/dataforge/meta/Meta; + public final fun getDefaultValue ()Lspace/kscience/dataforge/values/Value; + public final fun getIndexKey ()Ljava/lang/String; + public final fun getInfo ()Ljava/lang/String; + public final fun getMultiple ()Z + public final fun getValueRequirement ()Lspace/kscience/dataforge/meta/descriptors/ValueRequirement; + public final fun getValueTypes ()Ljava/util/List; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; + public static final fun write$Self (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lkotlinx/serialization/encoding/CompositeEncoder;Lkotlinx/serialization/descriptors/SerialDescriptor;)V } -public final class space/kscience/dataforge/meta/descriptors/NodeDescriptorBuilder$Companion { +public final class space/kscience/dataforge/meta/descriptors/MetaDescriptor$$serializer : kotlinx/serialization/internal/GeneratedSerializer { + public static final field INSTANCE Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor$$serializer; + public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor; + public fun childSerializers ()[Lkotlinx/serialization/KSerializer; + public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; + public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; + public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor; + public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V + public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)V + public fun typeParametersSerializers ()[Lkotlinx/serialization/KSerializer; } -public final class space/kscience/dataforge/meta/descriptors/NodeDescriptorKt { - public static final fun NodeDescriptor (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor; - public static final fun plus (Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;)Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor; +public final class space/kscience/dataforge/meta/descriptors/MetaDescriptor$Companion { + public final fun serializer ()Lkotlinx/serialization/KSerializer; } -public abstract interface class space/kscience/dataforge/meta/descriptors/ValueDescriptor : space/kscience/dataforge/meta/descriptors/ItemDescriptor { - public abstract fun getAllowedValues ()Ljava/util/List; - public abstract fun getDefault ()Lspace/kscience/dataforge/values/Value; - public abstract fun getRequired ()Z - public abstract fun getType ()Ljava/util/List; - public fun isAllowedValue (Lspace/kscience/dataforge/values/Value;)Z -} - -public final class space/kscience/dataforge/meta/descriptors/ValueDescriptorBuilder : space/kscience/dataforge/meta/descriptors/ItemDescriptorBuilder, space/kscience/dataforge/meta/descriptors/ValueDescriptor { - public fun ()V - public fun (Lspace/kscience/dataforge/meta/Config;)V - public synthetic fun (Lspace/kscience/dataforge/meta/Config;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public final fun allow ([Ljava/lang/Object;)V - public synthetic fun build ()Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor; - public fun build ()Lspace/kscience/dataforge/meta/descriptors/ValueDescriptor; +public final class space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder { + public final fun allowedValues ([Ljava/lang/Object;)V + public final fun attributes (Lkotlin/jvm/functions/Function1;)V public final fun default (Ljava/lang/Object;)V - public fun getAllowedValues ()Ljava/util/List; - public fun getDefault ()Lspace/kscience/dataforge/values/Value; - public fun getRequired ()Z - public fun getType ()Ljava/util/List; - public fun isAllowedValue (Lspace/kscience/dataforge/values/Value;)Z - public fun setAllowedValues (Ljava/util/List;)V - public fun setDefault (Lspace/kscience/dataforge/values/Value;)V - public fun setRequired (Z)V - public fun setType (Ljava/util/List;)V - public final fun type ([Lspace/kscience/dataforge/values/ValueType;)V + public final fun getAllowedValues ()Ljava/util/List; + public final fun getAttributes ()Lspace/kscience/dataforge/meta/MutableMeta; + public final fun getChildren ()Ljava/util/Map; + public final fun getDefault ()Lspace/kscience/dataforge/values/Value; + public final fun getIndexKey ()Ljava/lang/String; + public final fun getInfo ()Ljava/lang/String; + public final fun getMultiple ()Z + public final fun getType ()Ljava/util/List; + public final fun getValueRequirement ()Lspace/kscience/dataforge/meta/descriptors/ValueRequirement; + public final fun item (Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder; + public static synthetic fun item$default (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder; + public final fun node (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder; + public static synthetic fun node$default (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder; + public final fun setAllowedValues (Ljava/util/List;)V + public final fun setAttributes (Lspace/kscience/dataforge/meta/MutableMeta;)V + public final fun setChildren (Ljava/util/Map;)V + public final fun setDefault (Lspace/kscience/dataforge/values/Value;)V + public final fun setIndexKey (Ljava/lang/String;)V + public final fun setInfo (Ljava/lang/String;)V + public final fun setMultiple (Z)V + public final fun setType (Ljava/util/List;)V + public final fun setValueRequirement (Lspace/kscience/dataforge/meta/descriptors/ValueRequirement;)V + public final fun type (Lspace/kscience/dataforge/values/ValueType;[Lspace/kscience/dataforge/values/ValueType;)V +} + +public final class space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilderKt { + public static final fun MetaDescriptor (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; + public static final fun copy (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; + public static synthetic fun copy$default (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; + public static final fun item (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder; + public static final fun node (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V + public static final fun node (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder;Ljava/lang/String;Lspace/kscience/dataforge/meta/descriptors/Described;Lkotlin/jvm/functions/Function1;)V + public static final fun node (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder;Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder; + public static synthetic fun node$default (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder;Ljava/lang/String;Lspace/kscience/dataforge/meta/descriptors/Described;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V + public static final fun required (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder;)V + public static final fun value (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder;Ljava/lang/String;Lspace/kscience/dataforge/values/ValueType;[Lspace/kscience/dataforge/values/ValueType;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder; + public static final fun value (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/values/ValueType;[Lspace/kscience/dataforge/values/ValueType;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder; + public static synthetic fun value$default (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder;Ljava/lang/String;Lspace/kscience/dataforge/values/ValueType;[Lspace/kscience/dataforge/values/ValueType;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder; + public static synthetic fun value$default (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder;Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/values/ValueType;[Lspace/kscience/dataforge/values/ValueType;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder; +} + +public final class space/kscience/dataforge/meta/descriptors/MetaDescriptorKt { + public static final fun get (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Ljava/lang/String;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; + public static final fun get (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor; + public static final fun getAllowedValues (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Ljava/util/List; + public static final fun getRequired (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;)Z + public static final fun validate (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lspace/kscience/dataforge/meta/Meta;)Z + public static final fun validate (Lspace/kscience/dataforge/meta/descriptors/MetaDescriptor;Lspace/kscience/dataforge/values/Value;)Z +} + +public final class space/kscience/dataforge/meta/descriptors/ValueRequirement : java/lang/Enum { + public static final field ABSENT Lspace/kscience/dataforge/meta/descriptors/ValueRequirement; + public static final field NONE Lspace/kscience/dataforge/meta/descriptors/ValueRequirement; + public static final field REQUIRED Lspace/kscience/dataforge/meta/descriptors/ValueRequirement; + public static fun valueOf (Ljava/lang/String;)Lspace/kscience/dataforge/meta/descriptors/ValueRequirement; + public static fun values ()[Lspace/kscience/dataforge/meta/descriptors/ValueRequirement; } public final class space/kscience/dataforge/meta/transformations/KeepTransformationRule : space/kscience/dataforge/meta/transformations/TransformationRule { @@ -628,16 +560,16 @@ public final class space/kscience/dataforge/meta/transformations/KeepTransformat public fun equals (Ljava/lang/Object;)Z public final fun getSelector ()Lkotlin/jvm/functions/Function1; public fun hashCode ()I - public fun matches (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/TypedMetaItem;)Z + public fun matches (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)Z public fun selectItems (Lspace/kscience/dataforge/meta/Meta;)Lkotlin/sequences/Sequence; public fun toString ()Ljava/lang/String; - public fun transformItem (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/TypedMetaItem;Lspace/kscience/dataforge/meta/MutableMeta;)V + public fun transformItem (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/MutableMeta;)V } public abstract interface class space/kscience/dataforge/meta/transformations/MetaConverter { public static final field Companion Lspace/kscience/dataforge/meta/transformations/MetaConverter$Companion; - public abstract fun itemToObject (Lspace/kscience/dataforge/meta/TypedMetaItem;)Ljava/lang/Object; - public abstract fun objectToMetaItem (Ljava/lang/Object;)Lspace/kscience/dataforge/meta/TypedMetaItem; + public abstract fun metaToObject (Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Object; + public abstract fun objectToMeta (Ljava/lang/Object;)Lspace/kscience/dataforge/meta/Meta; } public final class space/kscience/dataforge/meta/transformations/MetaConverter$Companion { @@ -645,7 +577,6 @@ public final class space/kscience/dataforge/meta/transformations/MetaConverter$C public final fun getDouble ()Lspace/kscience/dataforge/meta/transformations/MetaConverter; public final fun getFloat ()Lspace/kscience/dataforge/meta/transformations/MetaConverter; public final fun getInt ()Lspace/kscience/dataforge/meta/transformations/MetaConverter; - public final fun getItem ()Lspace/kscience/dataforge/meta/transformations/MetaConverter; public final fun getLong ()Lspace/kscience/dataforge/meta/transformations/MetaConverter; public final fun getMeta ()Lspace/kscience/dataforge/meta/transformations/MetaConverter; public final fun getNumber ()Lspace/kscience/dataforge/meta/transformations/MetaConverter; @@ -656,16 +587,15 @@ public final class space/kscience/dataforge/meta/transformations/MetaConverter$C } public final class space/kscience/dataforge/meta/transformations/MetaConverterKt { - public static final fun metaToObject (Lspace/kscience/dataforge/meta/transformations/MetaConverter;Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Object; - public static final fun nullableItemToObject (Lspace/kscience/dataforge/meta/transformations/MetaConverter;Lspace/kscience/dataforge/meta/TypedMetaItem;)Ljava/lang/Object; - public static final fun nullableObjectToMetaItem (Lspace/kscience/dataforge/meta/transformations/MetaConverter;Ljava/lang/Object;)Lspace/kscience/dataforge/meta/TypedMetaItem; + public static final fun nullableMetaToObject (Lspace/kscience/dataforge/meta/transformations/MetaConverter;Lspace/kscience/dataforge/meta/Meta;)Ljava/lang/Object; + public static final fun nullableObjectToMeta (Lspace/kscience/dataforge/meta/transformations/MetaConverter;Ljava/lang/Object;)Lspace/kscience/dataforge/meta/Meta; public static final fun valueToObject (Lspace/kscience/dataforge/meta/transformations/MetaConverter;Lspace/kscience/dataforge/values/Value;)Ljava/lang/Object; } public final class space/kscience/dataforge/meta/transformations/MetaTransformation { public static final field Companion Lspace/kscience/dataforge/meta/transformations/MetaTransformation$Companion; public static final fun apply-impl (Ljava/util/Collection;Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/meta/Meta; - public static final fun bind-impl (Ljava/util/Collection;Lspace/kscience/dataforge/meta/Config;Lspace/kscience/dataforge/meta/MutableMeta;)V + public static final fun bind-impl (Ljava/util/Collection;Lspace/kscience/dataforge/meta/ObservableMeta;Lspace/kscience/dataforge/meta/MutableMeta;)V public static final synthetic fun box-impl (Ljava/util/Collection;)Lspace/kscience/dataforge/meta/transformations/MetaTransformation; public static fun constructor-impl (Ljava/util/Collection;)Ljava/util/Collection; public fun equals (Ljava/lang/Object;)Z @@ -703,9 +633,9 @@ public final class space/kscience/dataforge/meta/transformations/RegexItemTransf public final fun getFrom ()Lkotlin/text/Regex; public final fun getTransform ()Lkotlin/jvm/functions/Function4; public fun hashCode ()I - public fun matches (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/TypedMetaItem;)Z + public fun matches (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)Z public fun toString ()Ljava/lang/String; - public fun transformItem (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/TypedMetaItem;Lspace/kscience/dataforge/meta/MutableMeta;)V + public fun transformItem (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/MutableMeta;)V } public final class space/kscience/dataforge/meta/transformations/SingleItemTransformationRule : space/kscience/dataforge/meta/transformations/TransformationRule { @@ -718,16 +648,20 @@ public final class space/kscience/dataforge/meta/transformations/SingleItemTrans public final fun getFrom ()Lspace/kscience/dataforge/names/Name; public final fun getTransform ()Lkotlin/jvm/functions/Function3; public fun hashCode ()I - public fun matches (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/TypedMetaItem;)Z + public fun matches (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)Z public fun selectItems (Lspace/kscience/dataforge/meta/Meta;)Lkotlin/sequences/Sequence; public fun toString ()Ljava/lang/String; - public fun transformItem (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/TypedMetaItem;Lspace/kscience/dataforge/meta/MutableMeta;)V + public fun transformItem (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/MutableMeta;)V } public abstract interface class space/kscience/dataforge/meta/transformations/TransformationRule { - public abstract fun matches (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/TypedMetaItem;)Z + public abstract fun matches (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;)Z public fun selectItems (Lspace/kscience/dataforge/meta/Meta;)Lkotlin/sequences/Sequence; - public abstract fun transformItem (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/TypedMetaItem;Lspace/kscience/dataforge/meta/MutableMeta;)V + public abstract fun transformItem (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/meta/MutableMeta;)V +} + +public final class space/kscience/dataforge/misc/CastJvmKt { + public static final fun unsafeCast (Ljava/lang/Object;)Ljava/lang/Object; } public abstract interface annotation class space/kscience/dataforge/misc/DFBuilder : java/lang/annotation/Annotation { @@ -770,6 +704,8 @@ public final class space/kscience/dataforge/names/Name$Companion { public final fun getEMPTY ()Lspace/kscience/dataforge/names/Name; public final fun getMATCH_ALL_TOKEN ()Lspace/kscience/dataforge/names/NameToken; public final fun getMATCH_ANY_TOKEN ()Lspace/kscience/dataforge/names/NameToken; + public final fun of ([Ljava/lang/String;)Lspace/kscience/dataforge/names/Name; + public final fun parse (Ljava/lang/String;)Lspace/kscience/dataforge/names/Name; public final fun serializer ()Lkotlinx/serialization/KSerializer; } @@ -781,6 +717,7 @@ public final class space/kscience/dataforge/names/NameKt { 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;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; public static final fun firstOrNull (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/names/NameToken; public static final fun get (Ljava/util/Map;Ljava/lang/String;)Ljava/lang/Object; public static final fun get (Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object; @@ -797,7 +734,6 @@ public final class space/kscience/dataforge/names/NameKt { 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;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 toName (Ljava/lang/String;)Lspace/kscience/dataforge/names/Name; public static final fun withIndex (Lspace/kscience/dataforge/names/Name;Ljava/lang/String;)Lspace/kscience/dataforge/names/Name; } @@ -910,6 +846,10 @@ public final class space/kscience/dataforge/values/ListValue$Companion { public final fun getEMPTY ()Lspace/kscience/dataforge/values/ListValue; } +public abstract interface class space/kscience/dataforge/values/MutableValueProvider : space/kscience/dataforge/values/ValueProvider { + public abstract fun setValue (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/values/Value;)V +} + public final class space/kscience/dataforge/values/Null : space/kscience/dataforge/values/Value { public static final field INSTANCE Lspace/kscience/dataforge/values/Null; public fun equals (Ljava/lang/Object;)Z @@ -930,13 +870,21 @@ public final class space/kscience/dataforge/values/NumberValue : space/kscience/ } public final class space/kscience/dataforge/values/StringValue : space/kscience/dataforge/values/Value { - public fun (Ljava/lang/String;)V + public static final synthetic fun box-impl (Ljava/lang/String;)Lspace/kscience/dataforge/values/StringValue; + public static fun constructor-impl (Ljava/lang/String;)Ljava/lang/String; public fun equals (Ljava/lang/Object;)Z + public static fun equals-impl (Ljava/lang/String;Ljava/lang/Object;)Z + public static final fun equals-impl0 (Ljava/lang/String;Ljava/lang/String;)Z public final fun getString ()Ljava/lang/String; public fun getType ()Lspace/kscience/dataforge/values/ValueType; + public static fun getType-impl (Ljava/lang/String;)Lspace/kscience/dataforge/values/ValueType; public fun getValue ()Ljava/lang/Object; + public static fun getValue-impl (Ljava/lang/String;)Ljava/lang/Object; public fun hashCode ()I + public static fun hashCode-impl (Ljava/lang/String;)I public fun toString ()Ljava/lang/String; + public static fun toString-impl (Ljava/lang/String;)Ljava/lang/String; + public final synthetic fun unbox-impl ()Ljava/lang/String; } public final class space/kscience/dataforge/values/True : space/kscience/dataforge/values/Value { @@ -975,10 +923,12 @@ public final class space/kscience/dataforge/values/ValueExtensionsKt { public static final fun getStringList (Lspace/kscience/dataforge/values/Value;)Ljava/util/List; public static final fun isList (Lspace/kscience/dataforge/values/Value;)Z public static final fun isNull (Lspace/kscience/dataforge/values/Value;)Z - public static final fun toMeta (Lspace/kscience/dataforge/values/Value;)Lspace/kscience/dataforge/meta/MetaBuilder; + public static final fun toMeta (Lspace/kscience/dataforge/values/Value;)Lspace/kscience/dataforge/meta/Meta; } public final class space/kscience/dataforge/values/ValueKt { + public static final fun ListValue ([Ljava/lang/Number;)Lspace/kscience/dataforge/values/ListValue; + public static final fun ListValue ([Ljava/lang/String;)Lspace/kscience/dataforge/values/ListValue; public static final fun asValue (Ljava/lang/Enum;)Lspace/kscience/dataforge/values/Value; public static final fun asValue (Ljava/lang/Iterable;)Lspace/kscience/dataforge/values/Value; public static final fun asValue (Ljava/lang/Number;)Lspace/kscience/dataforge/values/Value; @@ -995,6 +945,15 @@ public final class space/kscience/dataforge/values/ValueKt { public static final fun parseValue (Ljava/lang/String;)Lspace/kscience/dataforge/values/Value; } +public abstract interface class space/kscience/dataforge/values/ValueProvider { + public abstract fun getValue (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/values/Value; +} + +public final class space/kscience/dataforge/values/ValueProviderKt { + public static final fun getValue (Lspace/kscience/dataforge/values/ValueProvider;Ljava/lang/String;)Lspace/kscience/dataforge/values/Value; + public static final fun setValue (Lspace/kscience/dataforge/values/MutableValueProvider;Ljava/lang/String;Lspace/kscience/dataforge/values/Value;)V +} + public final class space/kscience/dataforge/values/ValueSerializer : kotlinx/serialization/KSerializer { public static final field INSTANCE Lspace/kscience/dataforge/values/ValueSerializer; public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object; diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Config.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Config.kt deleted file mode 100644 index 14beb87b..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Config.kt +++ /dev/null @@ -1,110 +0,0 @@ -package space.kscience.dataforge.meta - -import kotlinx.serialization.KSerializer -import kotlinx.serialization.Serializable -import kotlinx.serialization.descriptors.SerialDescriptor -import kotlinx.serialization.encoding.Decoder -import kotlinx.serialization.encoding.Encoder -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 kotlin.collections.set -import kotlin.jvm.Synchronized - -//TODO add validator to configuration - -/** - * Mutable meta representing object state - */ -@Serializable(Config.Companion::class) -public class Config : AbstractMutableMeta(), ItemPropertyProvider { - - private val listeners = HashSet() - - @Synchronized - private fun itemChanged(name: Name, oldItem: MetaItem?, newItem: MetaItem?) { - listeners.forEach { it.action(name, oldItem, newItem) } - } - - /** - * Add change listener to this meta. Owner is declared to be able to remove listeners later. Listener without owner could not be removed - */ - @Synchronized - override fun onChange(owner: Any?, action: (Name, MetaItem?, MetaItem?) -> Unit) { - listeners.add(ItemListener(owner, action)) - } - - /** - * Remove all listeners belonging to given owner - */ - @Synchronized - override fun removeListener(owner: Any?) { - listeners.removeAll { it.owner === owner } - } - - override fun replaceItem(key: NameToken, oldItem: TypedMetaItem?, newItem: TypedMetaItem?) { - if (newItem == null) { - children.remove(key) - if (oldItem != null && oldItem is MetaItemNode) { - oldItem.node.removeListener(this) - } - } else { - children[key] = newItem - if (newItem is MetaItemNode) { - newItem.node.onChange(this) { name, oldChild, newChild -> - itemChanged(key + name, oldChild, newChild) - } - } - } - itemChanged(key.asName(), oldItem, newItem) - } - - /** - * Attach configuration node instead of creating one - */ - override fun wrapNode(meta: Meta): Config = meta.asConfig() - - override fun empty(): Config = Config() - - public companion object ConfigSerializer : KSerializer { - - public fun empty(): Config = Config() - override val descriptor: SerialDescriptor get() = MetaSerializer.descriptor - - override fun deserialize(decoder: Decoder): Config { - return MetaSerializer.deserialize(decoder).asConfig() - } - - override fun serialize(encoder: Encoder, value: Config) { - MetaSerializer.serialize(encoder, value) - } - } -} - -public operator fun Config.get(token: NameToken): TypedMetaItem? = items[token] - -/** - * Create a mutable copy of this [Meta]. The copy is created event if initial [Meta] is a [Config]. - * Listeners are not preserved - */ -public fun Meta.toConfig(): Config = Config().also { builder -> - this.items.mapValues { entry -> - val item = entry.value - builder[entry.key.asName()] = when (item) { - is MetaItemValue -> item.value - is MetaItemNode -> MetaItemNode(item.node.asConfig()) - } - } -} - -/** - * Create a copy of this config, optionally applying the given [block]. - * The listeners of the original Config are not retained. - */ -public inline fun Config.copy(block: Config.() -> Unit = {}): Config = toConfig().apply(block) - -/** - * Return this [Meta] as [Config] if it is [Config] and create a new copy otherwise - */ -public fun Meta.asConfig(): Config = this as? Config ?: toConfig() \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Configurable.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Configurable.kt index 3f4b154e..94f66381 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Configurable.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Configurable.kt @@ -1,25 +1,19 @@ package space.kscience.dataforge.meta import space.kscience.dataforge.misc.DFBuilder -import space.kscience.dataforge.names.Name -import kotlin.properties.ReadWriteProperty /** - * A container that holds a [Config]. + * A container that holds a [ObservableMeta]. */ public interface Configurable { /** * Backing config */ - public val config: Config + public val meta: MutableMeta } -public fun T.configure(meta: Meta): T = this.apply { config.update(meta) } +public fun T.configure(meta: Meta): T = this.apply { this.meta.update(meta) } @DFBuilder -public inline fun T.configure(action: Config.() -> Unit): T = apply { config.apply(action) } - -/* Node delegates */ - -public fun Configurable.config(key: Name? = null): ReadWriteProperty = config.node(key) +public inline fun T.configure(action: MutableMeta.() -> Unit): T = apply { meta.apply(action) } \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ItemDelegate.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ItemDelegate.kt deleted file mode 100644 index 81340807..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ItemDelegate.kt +++ /dev/null @@ -1,111 +0,0 @@ -package space.kscience.dataforge.meta - -import space.kscience.dataforge.meta.transformations.MetaConverter -import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.asName -import space.kscience.dataforge.values.Value -import kotlin.properties.ReadOnlyProperty - -/* Meta delegates */ - -public typealias ItemDelegate = ReadOnlyProperty - -public fun ItemProvider.item(key: Name? = null): ItemDelegate = ReadOnlyProperty { _, property -> - get(key ?: property.name.asName()) -} - -//TODO add caching for sealed nodes - - -/** - * Apply a converter to this delegate creating a delegate with a custom type - */ -public fun ItemDelegate.convert( - converter: MetaConverter, -): ReadOnlyProperty = ReadOnlyProperty { thisRef, property -> - this@convert.getValue(thisRef, property)?.let(converter::itemToObject) -} - -/* - * - */ -public fun ItemDelegate.convert( - converter: MetaConverter, - default: () -> R, -): ReadOnlyProperty = ReadOnlyProperty { thisRef, property -> - this@convert.getValue(thisRef, property)?.let(converter::itemToObject) ?: default() -} - -/** - * A converter with a custom reader transformation - */ -public fun ItemDelegate.convert( - reader: (MetaItem?) -> R, -): ReadOnlyProperty = ReadOnlyProperty { thisRef, property -> - this@convert.getValue(thisRef, property).let(reader) -} - -/* Read-only delegates for [ItemProvider] */ - -/** - * A property delegate that uses custom key - */ -public fun ItemProvider.value(key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.value) - -public fun ItemProvider.string(key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.string) - -public fun ItemProvider.boolean(key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.boolean) - -public fun ItemProvider.number(key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.number) - -public fun ItemProvider.double(key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.double) - -public fun ItemProvider.float(key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.float) - -public fun ItemProvider.int(key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.int) - -public fun ItemProvider.long(key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.long) - -public fun ItemProvider.node(key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.meta) - -public fun ItemProvider.string(default: String, key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.string) { default } - -public fun ItemProvider.boolean(default: Boolean, key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.boolean) { default } - -public fun ItemProvider.number(default: Number, key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.number) { default } - -public fun ItemProvider.double(default: Double, key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.double) { default } - -public fun ItemProvider.float(default: Float, key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.float) { default } - -public fun ItemProvider.int(default: Int, key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.int) { default } - -public fun ItemProvider.long(default: Long, key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.long) { default } - -public inline fun > ItemProvider.enum(default: E, key: Name? = null): ReadOnlyProperty = - item(key).convert(MetaConverter.enum()) { default } - -public fun ItemProvider.string(key: Name? = null, default: () -> String): ReadOnlyProperty = - item(key).convert(MetaConverter.string, default) - -public fun ItemProvider.boolean(key: Name? = null, default: () -> Boolean): ReadOnlyProperty = - item(key).convert(MetaConverter.boolean, default) - -public fun ItemProvider.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/ItemProvider.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ItemProvider.kt deleted file mode 100644 index 1201e9da..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ItemProvider.kt +++ /dev/null @@ -1,88 +0,0 @@ -package space.kscience.dataforge.meta - -import space.kscience.dataforge.names.* - -public fun interface ItemProvider { - //getItem used instead of get in order to provide extension freedom - public fun getItem(name: Name): MetaItem? - - public companion object { - public val EMPTY: ItemProvider = ItemProvider { null } - } -} - - -/* Get operations*/ - -/** - * Perform recursive item search using given [name]. Each [NameToken] is treated as a name in [Meta.items] of a parent node. - * - * If [name] is empty return current [Meta] as a [MetaItemNode] - */ -public operator fun ItemProvider?.get(name: Name): MetaItem? = this?.getItem(name) - -/** - * Root item of this provider - */ -public val ItemProvider.rootItem: MetaItem? get() = get(Name.EMPTY) - -/** - * The root node of this item provider if it is present - */ -public val ItemProvider.rootNode: Meta? get() = rootItem.node - -/** - * Parse [Name] from [key] using full name notation and pass it to [Meta.get] - */ -public operator fun ItemProvider?.get(key: String): MetaItem? = this?.get(key.toName()) - -/** - * Create a provider that uses given provider for default values if those are not found in this provider - */ -public fun ItemProvider.withDefault(default: ItemProvider?): ItemProvider = if (default == null) { - this -} else { - ItemProvider { - this[it] ?: default[it] - } -} - -/** - * Get all items matching given name. The index of the last element, if present is used as a [Regex], - * against which indexes of elements are matched. - */ -public fun ItemProvider.getIndexed(name: Name): Map { - val root: Meta = when (name.length) { - 0 -> error("Can't use empty name for 'getIndexed'") - 1 -> this.rootNode ?: return emptyMap() - else -> this[name.cutLast()].node ?: return emptyMap() - } - - val (body, index) = name.lastOrNull()!! - return if (index == null) { - root.items.filter { it.key.body == body }.mapKeys { it.key.index } - } else { - val regex = index.toRegex() - root.items.filter { it.key.body == body && (regex.matches(it.key.index ?: "")) } - .mapKeys { it.key.index } - } -} - -public fun ItemProvider.getIndexed(name: String): Map = this@getIndexed.getIndexed(name.toName()) - -/** - * Return a provider referencing a child node - */ -public fun ItemProvider.getChild(childName: Name): ItemProvider = get(childName).node ?: ItemProvider.EMPTY - -public fun ItemProvider.getChild(childName: String): ItemProvider = getChild(childName.toName()) - -///** -// * Get all items matching given name. -// */ -//@Suppress("UNCHECKED_CAST") -//public fun > M.getIndexed(name: Name): Map> = -// (this as Meta).getIndexed(name) as Map> -// -//public fun > M.getIndexed(name: String): Map> = -// getIndexed(name.toName()) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/JsonMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/JsonMeta.kt index 3e708314..1b4b1a55 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/JsonMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/JsonMeta.kt @@ -3,177 +3,240 @@ package space.kscience.dataforge.meta import kotlinx.serialization.json.* -import space.kscience.dataforge.meta.JsonMeta.Companion.JSON_ARRAY_KEY -import space.kscience.dataforge.meta.descriptors.ItemDescriptor -import space.kscience.dataforge.meta.descriptors.ItemDescriptor.Companion.DEFAULT_INDEX_KEY -import space.kscience.dataforge.meta.descriptors.NodeDescriptor -import space.kscience.dataforge.meta.descriptors.ValueDescriptor +import space.kscience.dataforge.meta.descriptors.MetaDescriptor +import space.kscience.dataforge.meta.descriptors.get import space.kscience.dataforge.names.NameToken -import space.kscience.dataforge.names.withIndex import space.kscience.dataforge.values.* +private const val jsonArrayKey: String = "@jsonArray" + +public val Meta.Companion.JSON_ARRAY_KEY: String get() = jsonArrayKey /** * @param descriptor reserved for custom serialization in future */ -public fun Value.toJson(descriptor: ValueDescriptor? = null): JsonElement = when (type) { +public fun Value.toJson(descriptor: MetaDescriptor? = null): JsonElement = when (type) { ValueType.NUMBER -> JsonPrimitive(numberOrNull) ValueType.STRING -> JsonPrimitive(string) ValueType.BOOLEAN -> JsonPrimitive(boolean) - ValueType.LIST -> JsonArray(list.map { it.toJson() }) + ValueType.LIST -> JsonArray(list.map { it.toJson(descriptor) }) ValueType.NULL -> JsonNull } //Use these methods to customize JSON key mapping @Suppress("NULLABLE_EXTENSION_OPERATOR_WITH_SAFE_CALL_RECEIVER") -private fun String.toJsonKey(descriptor: ItemDescriptor?) = descriptor?.attributes?.get("jsonName").string ?: toString() +private fun String.toJsonKey(descriptor: MetaDescriptor?) = descriptor?.attributes?.get("jsonName").string ?: toString() -//private fun NodeDescriptor?.getDescriptor(key: String) = this?.items?.get(key) - -/** - * Convert given [Meta] to [JsonObject]. Primitives and nodes are copied as is, same name siblings are treated as json arrays - */ -private fun Meta.toJsonWithIndex(descriptor: NodeDescriptor?, indexValue: String?): JsonObject { - - val elementMap = HashMap() - - fun MetaItem.toJsonElement(itemDescriptor: ItemDescriptor?, index: String?): JsonElement = when (this) { - is MetaItemValue -> { - value.toJson(itemDescriptor as? ValueDescriptor) - } - is MetaItemNode -> { - node.toJsonWithIndex(itemDescriptor as? NodeDescriptor, index) +private fun Meta.toJsonWithIndex(descriptor: MetaDescriptor?, index: String?): JsonElement = if (items.isEmpty()) { + value?.toJson(descriptor) ?: JsonObject(emptyMap()) +} else { + val pairs: MutableList> = items.entries.groupBy { + it.key.body + }.mapTo(ArrayList()) { (body, list) -> + val childDescriptor = descriptor?.children?.get(body) + if (list.size == 1) { + val (token, element) = list.first() + //do not add empty element + val child: JsonElement = element.toJsonWithIndex(childDescriptor, token.index) + body to child + } else { + val elements: List = list.sortedBy { it.key.index }.mapIndexed { index, entry -> + //Use index if it is not equal to the item order + val actualIndex = if (index.toString() != entry.key.index) entry.key.index else null + entry.value.toJsonWithIndex(childDescriptor, actualIndex) + } + body to JsonArray(elements) } } - fun addElement(key: String) { - val itemDescriptor = descriptor?.items?.get(key) - val jsonKey = key.toJsonKey(itemDescriptor) - val items: Map = getIndexed(key) - when (items.size) { - 0 -> { - //do nothing - } - 1 -> { - elementMap[jsonKey] = items.values.first().toJsonElement(itemDescriptor, null) - } - else -> { - val array = buildJsonArray { - items.forEach { (index, item) -> - add(item.toJsonElement(itemDescriptor, index)) - } - } - elementMap[jsonKey] = array - } - } + //Add index if needed + if (index != null) { + pairs += (descriptor?.indexKey ?: Meta.INDEX_KEY) to JsonPrimitive(index) } - ((descriptor?.items?.keys ?: emptySet()) + items.keys.map { it.body }).forEach(::addElement) - - - if (indexValue != null) { - val indexKey = descriptor?.indexKey ?: DEFAULT_INDEX_KEY - elementMap[indexKey] = JsonPrimitive(indexValue) + //Add value if needed + if (value != null) { + pairs += Meta.VALUE_KEY to value!!.toJson(descriptor) } - return JsonObject(elementMap) + JsonObject(pairs.toMap()) } -public fun Meta.toJson(descriptor: NodeDescriptor? = null): JsonObject = toJsonWithIndex(descriptor, null) +public fun Meta.toJson(descriptor: MetaDescriptor? = null): JsonObject { + val element = toJsonWithIndex(descriptor, null) + return if (element is JsonObject) { + element + } else { + buildJsonObject { + put("@value", element) + } + } +} -public fun JsonObject.toMeta(descriptor: NodeDescriptor? = null): JsonMeta = JsonMeta(this, descriptor) - -public fun JsonPrimitive.toValue(descriptor: ValueDescriptor?): Value { +/** + * Convert a Json primitive to a [Value] + */ +public fun JsonPrimitive.toValue(descriptor: MetaDescriptor?): Value { return when (this) { JsonNull -> Null else -> { if (isString) { StringValue(content) } else { + //consider using LazyParse content.parseValue() } } } } -public fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): TypedMetaItem = when (this) { - is JsonPrimitive -> { - val value = this.toValue(descriptor as? ValueDescriptor) - MetaItemValue(value) - } - is JsonObject -> { - val meta = JsonMeta(this, descriptor as? NodeDescriptor) - MetaItemNode(meta) - } +/** + * Turn this [JsonElement] into a [ListValue] with recursion or return null if it contains objects + */ +private fun JsonElement.toValueOrNull(descriptor: MetaDescriptor?): Value? = when (this) { + is JsonPrimitive -> toValue(descriptor) + is JsonObject -> get(Meta.VALUE_KEY)?.toValueOrNull(descriptor) is JsonArray -> { - if (this.all { it is JsonPrimitive }) { - val value = if (isEmpty()) { - Null - } else { - map { - //We already checked that all values are primitives - (it as JsonPrimitive).toValue(descriptor as? ValueDescriptor) - }.asValue() - } - MetaItemValue(value) - } else { - //We can't return multiple items therefore we create top level node - buildJsonObject { put(JSON_ARRAY_KEY, this@toMetaItem) }.toMetaItem(descriptor) + if (isEmpty()) ListValue.EMPTY else { + val values = map { it.toValueOrNull(descriptor) } + values.map { it ?: return null }.asValue() } } } /** - * A meta wrapping json object + * Fill a mutable map with children produced from [element] with given top level [key] */ -public class JsonMeta(private val json: JsonObject, private val descriptor: NodeDescriptor? = null) : MetaBase() { - - private fun buildItems(): Map> { - val map = LinkedHashMap>() - - json.forEach { (jsonKey, value) -> - val key = NameToken(jsonKey) - val itemDescriptor = descriptor?.items?.get(jsonKey) - when (value) { - is JsonPrimitive -> { - map[key] = MetaItemValue(value.toValue(itemDescriptor as? ValueDescriptor)) - } - is JsonObject -> { - map[key] = MetaItemNode( - JsonMeta( - value, - itemDescriptor as? NodeDescriptor - ) - ) - } - is JsonArray -> if (value.all { it is JsonPrimitive }) { - val listValue = ListValue( - value.map { - //We already checked that all values are primitives - (it as JsonPrimitive).toValue(itemDescriptor as? ValueDescriptor) +private fun MutableMap.addJsonElement( + key: String, + element: JsonElement, + descriptor: MetaDescriptor? +) { + when (element) { + is JsonPrimitive -> put(NameToken(key), Meta(element.toValue(descriptor))) + is JsonArray -> { + val value = element.toValueOrNull(descriptor) + if (value != null) { + put(NameToken(key), Meta(value)) + } else { + val indexKey = descriptor?.indexKey ?: Meta.INDEX_KEY + element.forEachIndexed { serial, childElement -> + val index = (childElement as? JsonObject)?.get(indexKey)?.jsonPrimitive?.content + ?: serial.toString() + val child: SealedMeta = when (childElement) { + is JsonObject -> childElement.toMeta(descriptor) + is JsonArray -> { + val childValue = childElement.toValueOrNull(null) + if (childValue == null) { + SealedMeta(null, + hashMapOf().apply { + addJsonElement(Meta.JSON_ARRAY_KEY, childElement, null) + } + ) + } else { + Meta(childValue) + } } - ) - map[key] = MetaItemValue(listValue) - } else value.forEachIndexed { index, jsonElement -> - val indexKey = (itemDescriptor as? NodeDescriptor)?.indexKey ?: DEFAULT_INDEX_KEY - val indexValue: String = (jsonElement as? JsonObject) - ?.get(indexKey)?.jsonPrimitive?.contentOrNull - ?: index.toString() //In case index is non-string, the backward transformation will be broken. - - val token = key.withIndex(indexValue) - map[token] = jsonElement.toMetaItem(itemDescriptor) + is JsonPrimitive -> Meta(childElement.toValue(null)) + } + put(NameToken(key, index), child) } } } - return map + is JsonObject -> { + val indexKey = descriptor?.indexKey ?: Meta.INDEX_KEY + val index = element[indexKey]?.jsonPrimitive?.content + put(NameToken(key, index), element.toMeta(descriptor)) + } } +} - override val items: Map> by lazy(::buildItems) - - public companion object { - /** - * A key representing top-level json array of nodes, which could not be directly represented by a meta node - */ - public const val JSON_ARRAY_KEY: String = "@jsonArray" +public fun JsonObject.toMeta(descriptor: MetaDescriptor? = null): SealedMeta { + val map = LinkedHashMap() + forEach { (key, element) -> + if (key != Meta.VALUE_KEY) { + map.addJsonElement(key, element, descriptor?.get(key)) + } } -} \ No newline at end of file + return SealedMeta(get(Meta.VALUE_KEY)?.toValueOrNull(descriptor), map) +} + +public fun JsonElement.toMeta(descriptor: MetaDescriptor? = null): SealedMeta = when (this) { + is JsonPrimitive -> Meta(toValue(descriptor)) + is JsonObject -> toMeta(descriptor) + is JsonArray -> SealedMeta(null, + linkedMapOf().apply { + addJsonElement(Meta.JSON_ARRAY_KEY, this@toMeta, null) + } + ) +} + +// +///** +// * A meta wrapping json object +// */ +//public class JsonMeta( +// private val json: JsonElement, +// private val descriptor: MetaDescriptor? = null +//) : TypedMeta { +// +// private val indexName by lazy { descriptor?.indexKey ?: Meta.INDEX_KEY } +// +// override val value: Value? by lazy { +// json.toValueOrNull(descriptor) +// } +// +// private fun MutableMap.appendArray(json: JsonArray, key: String) { +// json.forEachIndexed { index, child -> +// if (child is JsonArray) { +// appendArray(child, key) +// } else { +// //Use explicit index or order for index +// val tokenIndex = (child as? JsonObject) +// ?.get(indexName) +// ?.jsonPrimitive?.content +// ?: index.toString() +// val token = NameToken(key, tokenIndex) +// this[token] = JsonMeta(child) +// } +// } +// } +// +// override val items: Map by lazy { +// val map = HashMap() +// when (json) { +// is JsonObject -> json.forEach { (name, child) -> +// //skip value key +// if (name != Meta.VALUE_KEY) { +// if (child is JsonArray && child.any { it is JsonObject }) { +// map.appendArray(child, name) +// } else { +// +// val index = (child as? JsonObject)?.get(indexName)?.jsonPrimitive?.content +// val token = NameToken(name, index) +// map[token] = JsonMeta(child, descriptor?.get(name)) +// } +// } +// } +// is JsonArray -> { +// //return children only if it is not value +// if (value == null) map.appendArray(json, JSON_ARRAY_KEY) +// } +// else -> { +// //do nothing +// } +// } +// map +// } +// +// 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) +// +// public companion object { +// /** +// * A key representing top-level json array of nodes, which could not be directly represented by a meta node +// */ +// public const val JSON_ARRAY_KEY: String = "@jsonArray" +// } +//} \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Laminate.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Laminate.kt index 044c5699..30f6d542 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Laminate.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Laminate.kt @@ -2,37 +2,53 @@ package space.kscience.dataforge.meta import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.NameToken +import space.kscience.dataforge.values.Value /** * A meta laminate consisting of multiple immutable meta layers. For mutable front layer, use [Scheme]. * If [layers] list contains a [Laminate] it is flat-mapped. */ -public class Laminate(layers: List) : MetaBase() { +public class Laminate internal constructor(public val layers: List) : TypedMeta { - public val layers: List = layers.flatMap { - if (it is Laminate) { - it.layers - } else { - listOf(it) + override val value: Value? = layers.firstNotNullOfOrNull { it.value } + + override val items: Map by lazy { + layers.map { it.items.keys }.flatten().associateWith { key -> + Laminate(layers.mapNotNull { it.items[key] }) } } - override val items: Map> by lazy { - layers.map { it.items.keys }.flatten().associateWith { key -> - layers.asSequence().map { it.items[key] }.filterNotNull().let(replaceRule) - } + override fun getMeta(name: Name): Laminate? { + val childLayers = layers.mapNotNull { it.getMeta(name) } + return if (childLayers.isEmpty()) null else Laminate(childLayers) } /** - * Generate sealed meta using [mergeRule] + * Generate sealed meta by interweaving all layers. If a value is present in at least on layer, it will be present + * in the result. */ public fun merge(): SealedMeta { val items = layers.map { it.items.keys }.flatten().associateWith { key -> layers.asSequence().map { it.items[key] }.filterNotNull().merge() } - return SealedMeta(items) + return SealedMeta(value, items) } + /** + * Generate sealed meta by stacking layers. If node is present in the upper layer, then the lower layers will be + * ignored event if they have values that are not present on top layer. + */ + public fun top(): SealedMeta { + val items = layers.map { it.items.keys }.flatten().associateWith { key -> + layers.asSequence().map { it.items[key] }.filterNotNull().first().seal() + } + return SealedMeta(value, items) + } + + 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) + public companion object { /** @@ -40,33 +56,21 @@ public class Laminate(layers: List) : MetaBase() { * * TODO add picture */ - public val replaceRule: (Sequence) -> TypedMetaItem = { it.first().seal() } + public val replaceRule: (Sequence) -> SealedMeta? = { it.firstOrNull()?.seal() } - private fun Sequence.merge(): TypedMetaItem { - return when { - all { it is MetaItemValue } -> //If all items are values, take first - first().seal() - all { it is MetaItemNode } -> { - //list nodes in item - val nodes = map { (it as MetaItemNode).node } - //represent as key->value entries - val entries = nodes.flatMap { it.items.entries.asSequence() } - //group by keys - val groups = entries.groupBy { it.key } - // recursively apply the rule - val items = groups.mapValues { entry -> - entry.value.asSequence().map { it.value }.merge() - } - MetaItemNode(SealedMeta(items)) - - } - else -> map { - when (it) { - is MetaItemValue -> MetaItemNode(Meta { Meta.VALUE_KEY put it.value }) - is MetaItemNode -> it - } - }.merge() + private fun Sequence.merge(): SealedMeta { + val value = firstNotNullOfOrNull { it.value } + //list nodes in item + val nodes = toList() + //represent as key->value entries + val entries = nodes.flatMap { it.items.entries.asSequence() } + //group by keys + val groups = entries.groupBy { it.key } + // recursively apply the rule + val items = groups.mapValues { entry -> + entry.value.asSequence().map { it.value }.merge() } + return SealedMeta(value, items) } @@ -74,17 +78,27 @@ public class Laminate(layers: List) : MetaBase() { * The values a replaced but meta children are joined * TODO add picture */ - public val mergeRule: (Sequence) -> TypedMetaItem = { it.merge() } + public val mergeRule: (Sequence) -> SealedMeta? = { it.merge() } } } -@Suppress("FunctionName") -public fun Laminate(vararg layers: Meta?): Laminate = Laminate(layers.filterNotNull()) +public fun Laminate(layers: Collection): Laminate { + val flatLayers = layers.flatMap { + if (it is Laminate) { + it.layers + } else { + listOf(it) + } + }.filterNotNull() + return Laminate(flatLayers) +} + +public fun Laminate(vararg layers: Meta?): Laminate = Laminate(listOf(*layers)) /** * Performance optimized version of get method */ -public fun Laminate.getFirst(name: Name): MetaItem? { +public fun Laminate.getFirst(name: Name): Meta? { layers.forEach { layer -> layer[name]?.let { return it } } 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 12a03a62..48a65c6d 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 @@ -1,50 +1,57 @@ package space.kscience.dataforge.meta import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json +import space.kscience.dataforge.misc.Type +import space.kscience.dataforge.misc.unsafeCast import space.kscience.dataforge.names.* -import space.kscience.dataforge.values.Value +import space.kscience.dataforge.values.* /** * The object that could be represented as [Meta]. Meta provided by [toMeta] method should fully represent object state. * Meaning that two states with the same meta are equal. */ -@Serializable(MetaSerializer::class) + public interface MetaRepr { public fun toMeta(): Meta } /** - * Generic meta tree representation. Elements are [TypedMetaItem] objects that could be represented by three different entities: - * * [MetaItemValue] (leaf) - * * [MetaItemNode] single node - * - * * Same name siblings are supported via elements with the same [Name] but different queries + * A container for meta nodes */ -public interface Meta : MetaRepr, ItemProvider { - /** - * Top level items of meta tree - */ - public val items: Map +public fun interface MetaProvider : ValueProvider { + public fun getMeta(name: Name): Meta? - override fun getItem(name: Name): MetaItem? { - if (name.isEmpty()) return MetaItemNode(this) - return name.firstOrNull()?.let { token -> - val tail = name.cutFirst() - when (tail.length) { - 0 -> items[token] - else -> items[token]?.node?.get(tail) - } + override fun getValue(name: Name): Value? = getMeta(name)?.value +} + +/** + * A meta node + * TODO add documentation + * Same name siblings are supported via elements with the same [Name] but different indices. + */ +@Type(Meta.TYPE) +@Serializable(MetaSerializer::class) +public interface Meta : MetaRepr, MetaProvider { + public val value: Value? + public val items: Map + + override fun getMeta(name: Name): Meta? { + tailrec fun Meta.find(name: Name): Meta? = if (name.isEmpty()) { + this + } else { + items[name.firstOrNull()!!]?.find(name.cutFirst()) } + + return find(name) } override fun toMeta(): Meta = this - override fun equals(other: Any?): Boolean - - override fun hashCode(): Int - override fun toString(): String + override fun equals(other: Any?): Boolean + override fun hashCode(): Int public companion object { public const val TYPE: String = "meta" @@ -53,43 +60,194 @@ public interface Meta : MetaRepr, ItemProvider { * A key for single value node */ public const val VALUE_KEY: String = "@value" + public const val INDEX_KEY: String = "@index" - public fun equals(meta1: Meta, meta2: Meta): Boolean = meta1.items == meta2.items - - public val EMPTY: Meta = object : MetaBase() { - override val items: Map = emptyMap() + public fun hashCode(meta: Meta): Int { + var result = meta.value?.hashCode() ?: 0 + result = 31 * result + meta.items.hashCode() + return result } - } -} -public operator fun Meta.get(token: NameToken): MetaItem? = items.get(token) - -/** - * Get a sequence of [Name]-[Value] pairs - */ -public fun Meta.valueSequence(): Sequence> { - return items.asSequence().flatMap { (key, item) -> - when (item) { - is MetaItemValue -> sequenceOf(key.asName() to item.value) - is MetaItemNode -> item.node.valueSequence().map { pair -> (key.asName() + pair.first) to pair.second } + public fun equals(meta1: Meta?, meta2: Meta?): Boolean { + if (meta1 == null && meta2 == null) return true + if (meta1 == null || meta2 == null) return false + if (meta1.value != meta2.value) return false + if (meta1.items.keys != meta2.items.keys) return false + return meta1.items.keys.all { + equals(meta1[it], meta2[it]) + } } + + private val json = Json { + prettyPrint = true + useArrayPolymorphism = true + } + + public fun toString(meta: Meta): String = json.encodeToString(MetaSerializer, meta) + + public val EMPTY: Meta = SealedMeta(null, emptyMap()) } } /** - * Get a sequence of all [Name]-[TypedMetaItem] pairs for all items including nodes + * True if this [Meta] does not have children */ -public fun Meta.itemSequence(): Sequence> = sequence { +public val Meta.isLeaf: Boolean get() = items.isEmpty() + + +public operator fun Meta.get(token: NameToken): Meta? = items[token] + +/** + * Perform recursive item search using given [name]. Each [NameToken] is treated as a name in [Meta.items] of a parent node. + * + * If [name] is empty return current [Meta] + */ +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[Name.parse(key)] + +/** + * Get all items matching given name. The index of the last element, if present is used as a [Regex], + * against which indexes of elements are matched. + */ +public fun Meta.getIndexed(name: Name): Map { + val root: Meta = when (name.length) { + 0 -> error("Can't use empty name for 'getIndexed'") + 1 -> this + else -> this[name.cutLast()] ?: return emptyMap() + } + + val (body, index) = name.lastOrNull()!! + return if (index == null) { + root.items + .filter { it.key.body == body } + .mapKeys { it.key.index } + } else { + val regex = index.toRegex() + root.items + .filter { it.key.body == body && (regex.matches(it.key.index ?: "")) } + .mapKeys { it.key.index } + } +} + + +/** + * A meta node that ensures that all of its descendants has at least the same type. + * + */ +public interface TypedMeta> : Meta { + + override val items: Map + + override fun getMeta(name: Name): M? { + tailrec fun M.find(name: Name): M? = if (name.isEmpty()) { + this + } else { + items[name.firstOrNull()!!]?.find(name.cutFirst()) + } + + return self.find(name) + } + + override fun toMeta(): Meta = this +} + +/** + * Access self as a recursive type instance + */ +public inline val > TypedMeta.self: M get() = unsafeCast() + +//public typealias Meta = TypedMeta<*> + +public operator fun > TypedMeta.get(token: NameToken): M? = items[token] + +/** + * Perform recursive item search using given [name]. Each [NameToken] is treated as a name in [TypedMeta.items] of a parent node. + * + * If [name] is empty return current [Meta] + */ +public tailrec operator fun > TypedMeta.get(name: Name): M? = if (name.isEmpty()) { + self +} else { + get(name.firstOrNull()!!)?.get(name.cutFirst()) +} + +/** + * Parse [Name] from [key] using full name notation and pass it to [TypedMeta.get] + */ +public operator fun > TypedMeta.get(key: String): M? = this[Name.parse(key)] + + +/** + * Get a sequence of [Name]-[Value] pairs using top-down traversal of the tree + */ +public fun Meta.valueSequence(): Sequence> = sequence { + items.forEach { (key, item) -> + item.value?.let { itemValue -> + yield(key.asName() to itemValue) + } + yieldAll(item.valueSequence().map { pair -> (key.asName() + pair.first) to pair.second }) + } +} + +/** + * Get a sequence of all [Name]-[TypedMeta] pairs in a top-down traversal + */ +public fun Meta.nodeSequence(): Sequence> = sequence { items.forEach { (key, item) -> yield(key.asName() to item) - if (item is MetaItemNode) { - yieldAll(item.node.itemSequence().map { (innerKey, innerItem) -> - (key + innerKey) to innerItem - }) - } + yieldAll(item.nodeSequence().map { (innerKey, innerItem) -> + (key + innerKey) to innerItem + }) } } -public operator fun Meta.iterator(): Iterator> = itemSequence().iterator() +public operator fun Meta.iterator(): Iterator> = nodeSequence().iterator() -public fun Meta.isEmpty(): Boolean = this === Meta.EMPTY || this.items.isEmpty() \ No newline at end of file +public fun Meta.isEmpty(): Boolean = this === Meta.EMPTY + || (value == null && (items.isEmpty() || items.values.all { it.isEmpty() })) + + +/* Get operations*/ + +/** + * Get all items matching given name. The index of the last element, if present is used as a [Regex], + * against which indexes of elements are matched. + */ +@Suppress("UNCHECKED_CAST") +public fun > TypedMeta.getIndexed(name: Name): Map = + (this as Meta).getIndexed(name) as Map + +public fun > TypedMeta.getIndexed(name: String): Map = getIndexed(Name.parse(name)) + + +public val Meta?.string: String? get() = this?.value?.string +public val Meta?.boolean: Boolean? get() = this?.value?.boolean +public val Meta?.number: Number? get() = this?.value?.numberOrNull +public val Meta?.double: Double? get() = number?.toDouble() +public val Meta?.float: Float? get() = number?.toFloat() +public val Meta?.int: Int? get() = number?.toInt() +public val Meta?.long: Long? get() = number?.toLong() +public val Meta?.short: Short? get() = number?.toShort() + +public inline fun > Meta?.enum(): E? = this?.value?.let { + if (it is EnumValue<*>) { + it.value as E + } else { + string?.let { str -> enumValueOf(str) } + } +} + +public val Meta.stringList: List? get() = value?.list?.map { it.string } + +/** + * Create a provider that uses given provider for default values if those are not found in this provider + */ +public fun Meta.withDefault(default: Meta?): Meta = if (default == null) { + this +} else { + Laminate(this, default) +} \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaBuilder.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaBuilder.kt deleted file mode 100644 index 2f32e187..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaBuilder.kt +++ /dev/null @@ -1,141 +0,0 @@ -package space.kscience.dataforge.meta - -import space.kscience.dataforge.misc.DFBuilder -import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.asName -import space.kscience.dataforge.values.EnumValue -import space.kscience.dataforge.values.Value -import space.kscience.dataforge.values.asValue -import kotlin.jvm.JvmName - -/** - * DSL builder for meta. Is not intended to store mutable state - */ -@DFBuilder -public class MetaBuilder : AbstractMutableMeta() { - override fun wrapNode(meta: Meta): MetaBuilder = if (meta is MetaBuilder) meta else meta.toMutableMeta() - override fun empty(): MetaBuilder = MetaBuilder() - - public infix fun String.put(item: MetaItem?) { - set(this, item) - } - - public infix fun String.put(value: Value?) { - set(this, value) - } - - public infix fun String.put(string: String?) { - set(this, string?.asValue()) - } - - public infix fun String.put(number: Number?) { - set(this, number?.asValue()) - } - - public infix fun String.put(boolean: Boolean?) { - set(this, boolean?.asValue()) - } - - public infix fun String.put(enum: Enum<*>) { - set(this, EnumValue(enum)) - } - - @JvmName("putValues") - public infix fun String.put(iterable: Iterable) { - set(this, iterable.asValue()) - } - - @JvmName("putNumbers") - public infix fun String.put(iterable: Iterable) { - set(this, iterable.map { it.asValue() }.asValue()) - } - - @JvmName("putStrings") - public infix fun String.put(iterable: Iterable) { - set(this, iterable.map { it.asValue() }.asValue()) - } - - public infix fun String.put(array: DoubleArray) { - set(this, array.asValue()) - } - - public infix fun String.put(meta: Meta?) { - this@MetaBuilder[this] = meta - } - - public infix fun String.put(repr: MetaRepr?) { - set(this, repr?.toMeta()) - } - - @JvmName("putMetas") - public infix fun String.put(value: Iterable) { - set(this,value.toList()) - } - - public inline infix fun String.put(metaBuilder: MetaBuilder.() -> Unit) { - this@MetaBuilder[this] = MetaBuilder().apply(metaBuilder) - } - - public infix fun Name.put(value: Value?) { - set(this, value) - } - - public infix fun Name.put(string: String?) { - set(this, string?.asValue()) - } - - public infix fun Name.put(number: Number?) { - set(this, number?.asValue()) - } - - public infix fun Name.put(boolean: Boolean?) { - set(this, boolean?.asValue()) - } - - public infix fun Name.put(enum: Enum<*>) { - set(this, EnumValue(enum)) - } - - @JvmName("putValues") - public infix fun Name.put(iterable: Iterable) { - set(this, iterable.asValue()) - } - - public infix fun Name.put(meta: Meta?) { - this@MetaBuilder[this] = meta - } - - public infix fun Name.put(repr: MetaRepr?) { - set(this, repr?.toMeta()) - } - - @JvmName("putMetas") - public infix fun Name.put(value: Iterable) { - set(this, value.toList()) - } - - public infix fun Name.put(metaBuilder: MetaBuilder.() -> Unit) { - this@MetaBuilder[this] = MetaBuilder().apply(metaBuilder) - } -} - -/** - * For safety, builder always copies the initial meta even if it is builder itself - */ -public fun Meta.toMutableMeta(): MetaBuilder { - return MetaBuilder().also { builder -> - items.mapValues { entry -> - val item = entry.value - builder[entry.key.asName()] = when (item) { - is MetaItemValue -> item.value - is MetaItemNode -> MetaItemNode(item.node.toMutableMeta()) - } - } - } -} - -/** - * Build a [MetaBuilder] using given transformation - */ -@Suppress("FunctionName") -public inline fun Meta(builder: MetaBuilder.() -> Unit): MetaBuilder = MetaBuilder().apply(builder) \ No newline at end of file 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 new file mode 100644 index 00000000..92e0c3d4 --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaDelegate.kt @@ -0,0 +1,85 @@ +package space.kscience.dataforge.meta + +import space.kscience.dataforge.meta.transformations.MetaConverter +import space.kscience.dataforge.names.Name +import space.kscience.dataforge.names.asName +import space.kscience.dataforge.values.* +import kotlin.properties.ReadOnlyProperty + +/* Meta delegates */ + +public fun MetaProvider.node(key: Name? = null): ReadOnlyProperty = ReadOnlyProperty { _, property -> + getMeta(key ?: property.name.asName()) +} + +public fun MetaProvider.node( + key: Name? = null, + converter: MetaConverter +): ReadOnlyProperty = ReadOnlyProperty { _, property -> + getMeta(key ?: property.name.asName())?.let { converter.metaToObject(it) } +} + +/** + * A property delegate that uses custom key + */ +public fun MetaProvider.value(key: Name? = null): ReadOnlyProperty = ReadOnlyProperty { _, property -> + getMeta(key ?: property.name.asName())?.value +} + +public fun MetaProvider.value( + key: Name? = null, + reader: (Value?) -> R +): ReadOnlyProperty = ReadOnlyProperty { _, property -> + reader(getMeta(key ?: property.name.asName())?.value) +} + +//TODO add caching for sealed nodes + +/* Read-only delegates for [Meta] */ + +public fun MetaProvider.string(key: Name? = null): ReadOnlyProperty = value(key) { it?.string } + +public fun MetaProvider.boolean(key: Name? = null): ReadOnlyProperty = value(key) { it?.boolean } + +public fun MetaProvider.number(key: Name? = null): ReadOnlyProperty = value(key) { it?.numberOrNull } + +public fun MetaProvider.double(key: Name? = null): ReadOnlyProperty = value(key) { it?.double } + +public fun MetaProvider.float(key: Name? = null): ReadOnlyProperty = value(key) { it?.float } + +public fun MetaProvider.int(key: Name? = null): ReadOnlyProperty = value(key) { it?.int } + +public fun MetaProvider.long(key: Name? = null): ReadOnlyProperty = value(key) { it?.long } + +public fun MetaProvider.string(default: String, key: Name? = null): ReadOnlyProperty = + value(key) { it?.string ?: default } + +public fun MetaProvider.boolean(default: Boolean, key: Name? = null): ReadOnlyProperty = + value(key) { it?.boolean ?: default } + +public fun MetaProvider.number(default: Number, key: Name? = null): ReadOnlyProperty = + value(key) { it?.numberOrNull ?: default } + +public fun MetaProvider.double(default: Double, key: Name? = null): ReadOnlyProperty = + value(key) { it?.double ?: default } + +public fun MetaProvider.float(default: Float, key: Name? = null): ReadOnlyProperty = + value(key) { it?.float ?: default } + +public fun MetaProvider.int(default: Int, key: Name? = null): ReadOnlyProperty = + value(key) { it?.int ?: default } + +public fun MetaProvider.long(default: Long, key: Name? = null): ReadOnlyProperty = + value(key) { it?.long ?: default } + +public inline fun > MetaProvider.enum(default: E, key: Name? = null): ReadOnlyProperty = + value(key) { it?.enum() ?: default } + +public fun MetaProvider.string(key: Name? = null, default: () -> String): ReadOnlyProperty = + value(key) { it?.string ?: default() } + +public fun MetaProvider.boolean(key: Name? = null, default: () -> Boolean): ReadOnlyProperty = + value(key) { it?.boolean ?: default() } + +public fun MetaProvider.number(key: Name? = null, default: () -> Number): ReadOnlyProperty = + value(key) { it?.numberOrNull ?: default() } diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaItem.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaItem.kt deleted file mode 100644 index bf43119c..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaItem.kt +++ /dev/null @@ -1,90 +0,0 @@ -package space.kscience.dataforge.meta - -import kotlinx.serialization.Serializable -import space.kscience.dataforge.values.* - -/** - * A member of the meta tree. Could be represented as one of following: - * * a [MetaItemValue] (leaf) - * * a [MetaItemNode] (node) - */ -@Serializable(MetaItemSerializer::class) -public sealed class TypedMetaItem() { - - abstract override fun equals(other: Any?): Boolean - - abstract override fun hashCode(): Int - - public companion object { - public fun of(arg: Any?): MetaItem { - return when (arg) { - null -> Null.asMetaItem() - is MetaItem -> arg - is Meta -> arg.asMetaItem() - is ItemProvider -> arg.rootItem ?: Null.asMetaItem() - else -> Value.of(arg).asMetaItem() - } - } - } -} - -public typealias MetaItem = TypedMetaItem<*> - -@Serializable(MetaItemSerializer::class) -public class MetaItemValue(public val value: Value) : TypedMetaItem() { - override fun toString(): String = value.toString() - - override fun equals(other: Any?): Boolean { - return this.value == (other as? MetaItemValue)?.value - } - - override fun hashCode(): Int { - return value.hashCode() - } -} - -@Serializable(MetaItemSerializer::class) -public class MetaItemNode(public val node: M) : TypedMetaItem() { - //Fixing serializer for node could cause class cast problems, but it should not since Meta descendants are not serializable - override fun toString(): String = node.toString() - - override fun equals(other: Any?): Boolean = node == (other as? MetaItemNode<*>)?.node - - override fun hashCode(): Int = node.hashCode() -} - -public fun Value.asMetaItem(): MetaItemValue = MetaItemValue(this) -public fun M.asMetaItem(): MetaItemNode = MetaItemNode(this) - - -/** - * Unsafe methods to access values and nodes directly from [TypedMetaItem] - */ -public val MetaItem?.value: Value? - get() = (this as? MetaItemValue)?.value - ?: (this?.node?.get(Meta.VALUE_KEY) as? MetaItemValue)?.value - -public val MetaItem?.string: String? get() = value?.string -public val MetaItem?.boolean: Boolean? get() = value?.boolean -public val MetaItem?.number: Number? get() = value?.numberOrNull -public val MetaItem?.double: Double? get() = number?.toDouble() -public val MetaItem?.float: Float? get() = number?.toFloat() -public val MetaItem?.int: Int? get() = number?.toInt() -public val MetaItem?.long: Long? get() = number?.toLong() -public val MetaItem?.short: Short? get() = number?.toShort() - -public inline fun > MetaItem?.enum(): E? = - if (this is MetaItemValue && this.value is EnumValue<*>) { - this.value.value as E - } else { - string?.let { enumValueOf(it) } - } - -public val MetaItem.stringList: List? get() = value?.list?.map { it.string } - -public val TypedMetaItem?.node: M? - get() = when (this) { - null -> null - is MetaItemValue -> null//error("Trying to interpret value meta item as node item") - is MetaItemNode -> node - } \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaSerializer.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaSerializer.kt index 3285dc65..557cd5ef 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaSerializer.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MetaSerializer.kt @@ -1,80 +1,48 @@ package space.kscience.dataforge.meta -import kotlinx.serialization.ExperimentalSerializationApi -import kotlinx.serialization.InternalSerializationApi import kotlinx.serialization.KSerializer -import kotlinx.serialization.builtins.MapSerializer -import kotlinx.serialization.descriptors.* -import kotlinx.serialization.encoding.* +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder import kotlinx.serialization.json.JsonDecoder import kotlinx.serialization.json.JsonEncoder -import kotlinx.serialization.json.JsonObject -import space.kscience.dataforge.names.NameToken -import space.kscience.dataforge.names.NameTokenSerializer -import space.kscience.dataforge.values.ValueSerializer -public object MetaItemSerializer : KSerializer { +/** + * Serialized for [Meta] + */ +public object MetaSerializer : KSerializer { + private val genericMetaSerializer = SealedMeta.serializer() - @OptIn(InternalSerializationApi::class, ExperimentalSerializationApi::class) - override val descriptor: SerialDescriptor = buildSerialDescriptor("MetaItem", PolymorphicKind.SEALED) { - element("isNode") - element("value", buildSerialDescriptor("MetaItem.value", SerialKind.CONTEXTUAL)) + override val descriptor: SerialDescriptor = genericMetaSerializer.descriptor + + override fun deserialize(decoder: Decoder): Meta = if (decoder is JsonDecoder) { + decoder.decodeJsonElement().toMeta() + } else { + genericMetaSerializer.deserialize(decoder) } - override fun deserialize(decoder: Decoder): MetaItem { - decoder.decodeStructure(descriptor) { - //Force strict serialization order - require(decodeElementIndex(descriptor) == 0) { "Node flag must be first item serialized" } - val isNode = decodeBooleanElement(descriptor, 0) - require(decodeElementIndex(descriptor) == 1) { "Missing MetaItem content" } - val item = if (isNode) { - decodeSerializableElement(descriptor,1, MetaSerializer).asMetaItem() - } else { - decodeSerializableElement(descriptor,1, ValueSerializer).asMetaItem() - } - require(decodeElementIndex(descriptor) == CompositeDecoder.DECODE_DONE){"Serialized MetaItem contains additional fields"} - return item - } - } - - override fun serialize(encoder: Encoder, value: MetaItem) { - encoder.encodeStructure(descriptor) { - encodeBooleanElement(descriptor, 0, value is MetaItemNode) - when (value) { - is MetaItemValue -> encodeSerializableElement(descriptor, 1, ValueSerializer, value.value) - is MetaItemNode -> encodeSerializableElement(descriptor, 1, MetaSerializer, value.node) - } + override fun serialize(encoder: Encoder, value: Meta) { + if (encoder is JsonEncoder) { + encoder.encodeJsonElement(value.toJson()) + } else { + genericMetaSerializer.serialize(encoder, value.seal()) } } } /** - * Serialized for meta + * A serializer for [MutableMeta] */ -public object MetaSerializer : KSerializer { +public object MutableMetaSerializer : KSerializer { - private val mapSerializer: KSerializer>> = MapSerializer( - NameTokenSerializer, - MetaItemSerializer//MetaItem.serializer(MetaSerializer) - ) + override val descriptor: SerialDescriptor = MetaSerializer.descriptor - override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Meta") - - override fun deserialize(decoder: Decoder): Meta { - return if (decoder is JsonDecoder) { - JsonObject.serializer().deserialize(decoder).toMeta() - } else { - object : MetaBase() { - override val items: Map = mapSerializer.deserialize(decoder) - } - } + override fun deserialize(decoder: Decoder): MutableMeta { + val meta = decoder.decodeSerializableValue(MetaSerializer) + return (meta as? MutableMeta) ?: meta.toMutableMeta() } - override fun serialize(encoder: Encoder, value: Meta) { - if (encoder is JsonEncoder) { - JsonObject.serializer().serialize(encoder, value.toJson()) - } else { - mapSerializer.serialize(encoder, value.items) - } + override fun serialize(encoder: Encoder, value: MutableMeta) { + encoder.encodeSerializableValue(MetaSerializer, value) } } \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableItemDelegate.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableItemDelegate.kt deleted file mode 100644 index 075e9a04..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableItemDelegate.kt +++ /dev/null @@ -1,194 +0,0 @@ -package space.kscience.dataforge.meta - -import space.kscience.dataforge.meta.transformations.MetaConverter -import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.asName -import space.kscience.dataforge.values.* -import kotlin.properties.ReadWriteProperty -import kotlin.reflect.KProperty - -/* Read-write delegates */ - -public typealias MutableItemDelegate = ReadWriteProperty - -public fun MutableItemProvider.item(key: Name? = null): MutableItemDelegate = object : MutableItemDelegate { - override fun getValue(thisRef: Any?, property: KProperty<*>): MetaItem? { - return get(key ?: property.name.asName()) - } - - override fun setValue(thisRef: Any?, property: KProperty<*>, value: MetaItem?) { - val name = key ?: property.name.asName() - set(name, value) - } -} - -/* Mutable converters */ - -/** - * A type converter for a mutable [TypedMetaItem] delegate - */ -public fun MutableItemDelegate.convert( - converter: MetaConverter, -): ReadWriteProperty = object : ReadWriteProperty { - - override fun getValue(thisRef: Any?, property: KProperty<*>): R? = - this@convert.getValue(thisRef, property)?.let(converter::itemToObject) - - override fun setValue(thisRef: Any?, property: KProperty<*>, value: R?) { - val item = value?.let(converter::objectToMetaItem) - this@convert.setValue(thisRef, property, item) - } -} - -public fun MutableItemDelegate.convert( - converter: MetaConverter, - default: () -> R, -): ReadWriteProperty = object : ReadWriteProperty { - - override fun getValue(thisRef: Any?, property: KProperty<*>): R = - this@convert.getValue(thisRef, property)?.let(converter::itemToObject) ?: default() - - override fun setValue(thisRef: Any?, property: KProperty<*>, value: R) { - val item = value.let(converter::objectToMetaItem) - this@convert.setValue(thisRef, property, item) - } -} - -public fun MutableItemDelegate.convert( - reader: (MetaItem?) -> R, - writer: (R) -> MetaItem?, -): ReadWriteProperty = object : ReadWriteProperty { - - override fun getValue(thisRef: Any?, property: KProperty<*>): R = - this@convert.getValue(thisRef, property).let(reader) - - override fun setValue(thisRef: Any?, property: KProperty<*>, value: R) { - val item = value?.let(writer) - this@convert.setValue(thisRef, property, item) - } -} - - -/* Read-write delegates for [MutableItemProvider] */ - -/** - * A property delegate that uses custom key - */ -public fun MutableItemProvider.value(key: Name? = null): ReadWriteProperty = - item(key).convert(MetaConverter.value) - -public fun MutableItemProvider.string(key: Name? = null): ReadWriteProperty = - item(key).convert(MetaConverter.string) - -public fun MutableItemProvider.boolean(key: Name? = null): ReadWriteProperty = - item(key).convert(MetaConverter.boolean) - -public fun MutableItemProvider.number(key: Name? = null): ReadWriteProperty = - item(key).convert(MetaConverter.number) - -public fun MutableItemProvider.string(default: String, key: Name? = null): ReadWriteProperty = - item(key).convert(MetaConverter.string) { default } - -public fun MutableItemProvider.boolean(default: Boolean, key: Name? = null): ReadWriteProperty = - item(key).convert(MetaConverter.boolean) { default } - -public fun MutableItemProvider.number(default: Number, key: Name? = null): ReadWriteProperty = - item(key).convert(MetaConverter.number) { default } - -public fun MutableItemProvider.value(key: Name? = null, default: () -> Value): ReadWriteProperty = - item(key).convert(MetaConverter.value, default) - -public fun MutableItemProvider.string(key: Name? = null, default: () -> String): ReadWriteProperty = - item(key).convert(MetaConverter.string, default) - -public fun MutableItemProvider.boolean(key: Name? = null, default: () -> Boolean): ReadWriteProperty = - item(key).convert(MetaConverter.boolean, default) - -public fun MutableItemProvider.number(key: Name? = null, default: () -> Number): ReadWriteProperty = - item(key).convert(MetaConverter.number, default) - -public inline fun > MutableItemProvider.enum( - default: E, - key: Name? = null, -): ReadWriteProperty = - item(key).convert(MetaConverter.enum()) { default } - -public fun MutableItemProvider.node(key: Name? = null): ReadWriteProperty = item(key).convert( - reader = { it.node }, - writer = { it?.asMetaItem() } -) - -public inline fun > M.node(key: Name? = null): ReadWriteProperty = - item(key).convert(reader = { it?.let { it.node as M } }, writer = { it?.let { MetaItemNode(it) } }) - -/* Number delegates */ - -public fun MutableItemProvider.int(key: Name? = null): ReadWriteProperty = - item(key).convert(MetaConverter.int) - -public fun MutableItemProvider.double(key: Name? = null): ReadWriteProperty = - item(key).convert(MetaConverter.double) - -public fun MutableItemProvider.long(key: Name? = null): ReadWriteProperty = - item(key).convert(MetaConverter.long) - -public fun MutableItemProvider.float(key: Name? = null): ReadWriteProperty = - item(key).convert(MetaConverter.float) - - -/* Safe number delegates*/ - -public fun MutableItemProvider.int(default: Int, key: Name? = null): ReadWriteProperty = - item(key).convert(MetaConverter.int) { default } - -public fun MutableItemProvider.double(default: Double, key: Name? = null): ReadWriteProperty = - item(key).convert(MetaConverter.double) { default } - -public fun MutableItemProvider.long(default: Long, key: Name? = null): ReadWriteProperty = - item(key).convert(MetaConverter.long) { default } - -public fun MutableItemProvider.float(default: Float, key: Name? = null): ReadWriteProperty = - item(key).convert(MetaConverter.float) { default } - - -/* Extra delegates for special cases */ - -public fun MutableItemProvider.stringList( - vararg default: String, - key: Name? = null, -): ReadWriteProperty> = item(key).convert( - reader = { it?.stringList ?: listOf(*default) }, - writer = { it.map { str -> str.asValue() }.asValue().asMetaItem() } -) - -public fun MutableItemProvider.stringList( - key: Name? = null, -): ReadWriteProperty?> = item(key).convert( - reader = { it?.stringList }, - writer = { it?.map { str -> str.asValue() }?.asValue()?.asMetaItem() } -) - -public fun MutableItemProvider.numberList( - vararg default: Number, - key: Name? = null, -): ReadWriteProperty> = item(key).convert( - reader = { it?.value?.list?.map { value -> value.numberOrNull ?: Double.NaN } ?: listOf(*default) }, - writer = { it.map { num -> num.asValue() }.asValue().asMetaItem() } -) - -/* A special delegate for double arrays */ - - -public fun MutableItemProvider.doubleArray( - vararg default: Double, - key: Name? = null, -): ReadWriteProperty = item(key).convert( - reader = { it?.value?.doubleArray ?: doubleArrayOf(*default) }, - writer = { DoubleArrayValue(it).asMetaItem() } -) - -public fun MutableItemProvider.listValue( - key: Name? = null, - writer: (T) -> Value = { Value.of(it) }, - reader: (Value) -> T, -): ReadWriteProperty?> = item(key).convert(MetaConverter.valueList(writer, reader)) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableItemProvider.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableItemProvider.kt deleted file mode 100644 index 46a47ad5..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableItemProvider.kt +++ /dev/null @@ -1,129 +0,0 @@ -package space.kscience.dataforge.meta - -import space.kscience.dataforge.names.* -import space.kscience.dataforge.values.Value - -public interface MutableItemProvider : ItemProvider { - public fun setItem(name: Name, item: MetaItem?) -} - -public operator fun MutableItemProvider.set(name: Name, item: MetaItem?): Unit = setItem(name, item) - -public operator fun MutableItemProvider.set(name: Name, value: Value?): Unit = set(name, value?.asMetaItem()) - -public operator fun MutableItemProvider.set(name: Name, meta: Meta?): Unit = set(name, meta?.asMetaItem()) - -public operator fun MutableItemProvider.set(key: String, item: MetaItem?): Unit = set(key.toName(), item) - -public operator fun MutableItemProvider.set(key: String, meta: Meta?): Unit = set(key, meta?.asMetaItem()) - -@Suppress("NOTHING_TO_INLINE") -public inline fun MutableItemProvider.remove(name: Name): Unit = setItem(name, null) - -@Suppress("NOTHING_TO_INLINE") -public inline fun MutableItemProvider.remove(name: String): Unit = remove(name.toName()) - -/** - * Universal unsafe set method - */ -public operator fun MutableItemProvider.set(name: Name, value: Any?) { - when (value) { - null -> remove(name) - else -> set(name, MetaItem.of(value)) - } -} - -public operator fun MutableItemProvider.set(name: NameToken, value: Any?): Unit = - set(name.asName(), value) - -public operator fun MutableItemProvider.set(key: String, value: Any?): Unit = - set(key.toName(), value) - -public operator fun MutableItemProvider.set(key: String, index: String, value: Any?): Unit = - set(key.toName().withIndex(index), value) - - -/* Same name siblings generation */ - -public fun MutableItemProvider.setIndexedItems( - name: Name, - items: Iterable, - indexFactory: (MetaItem, index: Int) -> String = { _, index -> index.toString() }, -) { - val tokens = name.tokens.toMutableList() - val last = tokens.last() - items.forEachIndexed { index, meta -> - val indexedToken = NameToken(last.body, last.index + indexFactory(meta, index)) - tokens[tokens.lastIndex] = indexedToken - set(Name(tokens), meta) - } -} - -public fun MutableItemProvider.setIndexed( - name: Name, - metas: Iterable, - indexFactory: (Meta, index: Int) -> String = { _, index -> index.toString() }, -) { - setIndexedItems(name, metas.map { MetaItemNode(it) }) { item, index -> indexFactory(item.node!!, index) } -} - -public operator fun MutableItemProvider.set(name: Name, metas: Iterable): Unit = setIndexed(name, metas) -public operator fun MutableItemProvider.set(name: String, metas: Iterable): Unit = - setIndexed(name.toName(), metas) - -/** - * Get a [MutableItemProvider] referencing a child node - */ -public fun MutableItemProvider.getChild(childName: Name): MutableItemProvider { - fun createProvider() = object : MutableItemProvider { - override fun setItem(name: Name, item: MetaItem?) { - this@getChild.setItem(childName + name, item) - } - - override fun getItem(name: Name): MetaItem? = this@getChild.getItem(childName + name) - } - - return when { - childName.isEmpty() -> this - this is MutableMeta<*> -> { - get(childName).node ?: createProvider() - } - else -> { - createProvider() - } - } -} - -public fun MutableItemProvider.getChild(childName: String): MutableItemProvider = getChild(childName.toName()) - -/** - * Update existing mutable node with another node. The rules are following: - * * value replaces anything - * * node updates node and replaces anything but node - * * node list updates node list if number of nodes in the list is the same and replaces anything otherwise - */ -public fun MutableItemProvider.update(meta: Meta) { - meta.valueSequence().forEach { (name, value) -> set(name, value) } -} - -/** - * Edit a provider child at given name location - */ -public fun MutableItemProvider.editChild(name: Name, builder: MutableItemProvider.() -> Unit): MutableItemProvider = - getChild(name).apply(builder) - -/** - * Create a mutable item provider that uses given provider for default values if those are not found in this provider. - * Changes are propagated only to this provider. - */ -public fun MutableItemProvider.withDefault(default: ItemProvider?): MutableItemProvider = - if (default == null || (default is Meta && default.isEmpty())) { - //Optimize for use with empty default - this - } else object : MutableItemProvider { - override fun setItem(name: Name, item: MetaItem?) { - this@withDefault.setItem(name, item) - } - - override fun getItem(name: Name): MetaItem? = this@withDefault.getItem(name) ?: default.getItem(name) - } diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMeta.kt index b54c6534..527b6cbe 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 @@ -1,66 +1,365 @@ package space.kscience.dataforge.meta +import kotlinx.serialization.Serializable import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.* +import space.kscience.dataforge.values.EnumValue +import space.kscience.dataforge.values.MutableValueProvider +import space.kscience.dataforge.values.Value +import space.kscience.dataforge.values.asValue +import kotlin.js.JsName +import kotlin.jvm.Synchronized -public interface MutableMeta> : TypedMeta, MutableItemProvider { - override val items: Map> + +/** + * Mark a meta builder + */ +@DslMarker +public annotation class MetaBuilder + +/** + * A generic interface that gives access to getting and setting meta notes and values + */ +public interface MutableMetaProvider : MetaProvider, MutableValueProvider { + override fun getMeta(name: Name): MutableMeta? + public fun setMeta(name: Name, node: Meta?) + override fun setValue(name: Name, value: Value?) { + getMeta(name)?.value = value + } } /** - * A mutable meta node with attachable change listener. - * - * Changes in Meta are not thread safe. + * Mutable variant of [Meta] + * TODO documentation */ -public abstract class AbstractMutableMeta> : AbstractTypedMeta(), MutableMeta { - protected val children: MutableMap> = LinkedHashMap() +@Serializable(MutableMetaSerializer::class) +@MetaBuilder +public interface MutableMeta : Meta, MutableMetaProvider { - override val items: Map> - get() = children + override val items: Map - //protected abstract fun itemChanged(name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) + /** + * Get or set value of this node + */ + override var value: Value? - protected open fun replaceItem(key: NameToken, oldItem: TypedMetaItem?, newItem: TypedMetaItem?) { - if (newItem == null) { - children.remove(key) + override fun getMeta(name: Name): MutableMeta? { + tailrec fun MutableMeta.find(name: Name): MutableMeta? = if (name.isEmpty()) { + this } else { - children[key] = newItem + items[name.firstOrNull()!!]?.find(name.cutFirst()) } - //itemChanged(key.asName(), oldItem, newItem) + + return find(name) } - private fun wrapItem(item: MetaItem?): TypedMetaItem? = when (item) { - null -> null - is MetaItemValue -> item - is MetaItemNode -> MetaItemNode(wrapNode(item.node)) + override fun setValue(name: Name, value: Value?) { + getOrCreate(name).value = value } /** - * Transform given meta to node type of this meta tree + * Get existing node or create a new one */ - protected abstract fun wrapNode(meta: Meta): M + public fun getOrCreate(name: Name): MutableMeta + //TODO to be moved to extensions with multi-receivers + + public infix fun Name.put(value: Value?) { + setValue(this, value) + } + + public infix fun Name.put(string: String) { + setValue(this, string.asValue()) + } + + public infix fun Name.put(number: Number) { + setValue(this, number.asValue()) + } + + public infix fun Name.put(boolean: Boolean) { + setValue(this, boolean.asValue()) + } + + public infix fun Name.put(enum: Enum<*>) { + setValue(this, EnumValue(enum)) + } + + public infix fun Name.putIndexed(iterable: Iterable) { + setIndexed(this, iterable) + } + + public infix fun Name.put(meta: Meta) { + setMeta(this, meta) + } + + public infix fun Name.put(repr: MetaRepr) { + setMeta(this, repr.toMeta()) + } + + public infix fun Name.put(mutableMeta: MutableMeta.() -> Unit) { + setMeta(this, Meta(mutableMeta)) + } + + public infix fun String.put(meta: Meta) { + setMeta(Name.parse(this), meta) + } + + public infix fun String.put(value: Value?) { + setValue(Name.parse(this), value) + } + + public infix fun String.put(string: String) { + setValue(Name.parse(this), string.asValue()) + } + + public infix fun String.put(number: Number) { + setValue(Name.parse(this), number.asValue()) + } + + public infix fun String.put(boolean: Boolean) { + setValue(Name.parse(this), boolean.asValue()) + } + + public infix fun String.put(enum: Enum<*>) { + setValue(Name.parse(this), EnumValue(enum)) + } + + public infix fun String.put(array: DoubleArray) { + setValue(Name.parse(this), array.asValue()) + } + + public infix fun String.put(repr: MetaRepr) { + setMeta(Name.parse(this), repr.toMeta()) + } + + public infix fun String.putIndexed(iterable: Iterable) { + setIndexed(Name.parse(this), iterable) + } + + public infix fun String.put(builder: MutableMeta.() -> Unit) { + setMeta(Name.parse(this), MutableMeta(builder)) + } +} + +/** + * Set or replace node at given [name] + */ +public operator fun MutableMeta.set(name: Name, meta: Meta): Unit = setMeta(name, meta) + +/** + * Set or replace value at given [name] + */ +public operator fun MutableMeta.set(name: Name, value: Value?): Unit = setValue(name, value) + +public fun MutableMeta.getOrCreate(key: String): MutableMeta = getOrCreate(Name.parse(key)) + +public interface MutableTypedMeta> : TypedMeta, MutableMeta { /** - * Create empty node + * Zero-copy attach or replace existing node. Node is used with any additional state, listeners, etc. + * In some cases it is possible to have the same node as a child to several others */ - internal abstract fun empty(): M + @DFExperimental + public fun attach(name: Name, node: M) + override fun getMeta(name: Name): M? + override fun getOrCreate(name: Name): M +} - override fun setItem(name: Name, item: MetaItem?) { +public fun > M.getOrCreate(key: String): M = getOrCreate(Name.parse(key)) + +public fun MutableMetaProvider.remove(name: Name) { + setMeta(name, null) +} + +public fun MutableMetaProvider.remove(key: String) { + setMeta(Name.parse(key), null) +} + +// node setters + +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(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(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(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(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(Name.parse(key), value.asValue()) + +//public fun MutableMeta.set(key: String, index: String, value: Value?): Unit = +// set(key.toName().withIndex(index), value) + + +/* Same name siblings generation */ + + +public fun MutableMeta.setIndexed( + name: Name, + metas: Iterable, + indexFactory: (Meta, index: Int) -> String = { _, index -> index.toString() }, +) { + val tokens = name.tokens.toMutableList() + val last = tokens.last() + metas.forEachIndexed { index, meta -> + val indexedToken = NameToken(last.body, (last.index ?: "") + indexFactory(meta, index)) + tokens[tokens.lastIndex] = indexedToken + set(Name(tokens), meta) + } +} + +public operator fun MutableMeta.set(name: Name, metas: Iterable): Unit = + setIndexed(name, metas) + +public operator fun MutableMeta.set(key: String, metas: Iterable): Unit = + setIndexed(Name.parse(key), metas) + + +/** + * Update existing mutable node with another node. The rules are following: + * * value replaces anything + * * node updates node and replaces anything but node + * * node list updates node list if number of nodes in the list is the same and replaces anything otherwise + */ +public fun MutableMeta.update(meta: Meta) { + meta.valueSequence().forEach { (name, value) -> + set(name, value) + } +} + +///** +// * Get child with given name or create a new one +// */ +//public fun > MutableTypedMeta.getOrCreate(name: Name): M = +// get(name) ?: empty().also { attach(name, it) } + +/** + * Edit node at [name] + */ +public fun > MutableTypedMeta.edit(name: Name, builder: M.() -> Unit): M = + getOrCreate(name).apply(builder) + +/** + * Set a value at a given [name]. If node does not exist, create it. + */ +public operator fun > MutableTypedMeta.set(name: Name, value: Value?) { + edit(name) { + this.value = value + } +} + +/** + * A general implementation of mutable [Meta] which implements both [MutableTypedMeta] and [ObservableMeta]. + * The implementation uses blocking synchronization on mutation on JVM + */ +private class MutableMetaImpl( + value: Value?, + children: Map = emptyMap() +) : AbstractObservableMeta(), ObservableMutableMeta { + override var value = value + @Synchronized set(value) { + val oldValue = field + field = value + if (oldValue != value) { + invalidate(Name.EMPTY) + } + } + + private val children: LinkedHashMap = + LinkedHashMap(children.mapValues { (key, meta) -> + MutableMetaImpl(meta.value, meta.items).apply { adoptBy(this, key) } + }) + + override val items: Map get() = children + + private fun ObservableMeta.adoptBy(parent: MutableMetaImpl, key: NameToken) { + onChange(parent) { name -> + parent.invalidate(key + name) + } + } + + @DFExperimental + override fun attach(name: Name, node: ObservableMutableMeta) { when (name.length) { - 0 -> error("Can't set a meta item for empty name") + 0 -> error("Can't set a meta with empty name") 1 -> { - val token = name.firstOrNull()!! - val oldItem: TypedMetaItem? = getItem(name) - replaceItem(token, oldItem, wrapItem(item)) + replaceItem(name.first(), get(name), node) } - else -> { - val token = name.firstOrNull()!! - //get existing or create new node. Query is ignored for new node - if (items[token] == null) { - replaceItem(token, null, MetaItemNode(empty())) + else -> get(name.cutLast())?.attach(name.lastOrNull()!!.asName(), node) + } + } + + /** + * Create and attach empty node + */ + private fun createNode(name: Name): ObservableMutableMeta = when (name.length) { + 0 -> throw IllegalArgumentException("Can't create a node with empty name") + 1 -> { + val newNode = MutableMetaImpl(null) + children[name.first()] = newNode + newNode.adoptBy(this, name.first()) + newNode + } //do not notify, no value changed + else -> getOrCreate(name.first().asName()).getOrCreate(name.cutFirst()) + } + + override fun getOrCreate(name: Name): ObservableMutableMeta = + if (name.isEmpty()) this else get(name) ?: createNode(name) + + @Synchronized + private fun replaceItem( + key: NameToken, + oldItem: ObservableMutableMeta?, + newItem: ObservableMutableMeta? + ) { + if (oldItem != newItem) { + if (newItem == null) { + //remove child and remove stale listener + children.remove(key)?.removeListener(this) + } else { + newItem.adoptBy(this, key) + children[key] = newItem + } + invalidate(key.asName()) + } + } + + private fun wrapItem(meta: Meta): MutableMetaImpl = + MutableMetaImpl(meta.value, meta.items.mapValuesTo(LinkedHashMap()) { wrapItem(it.value) }) + + + override fun setMeta(name: Name, node: Meta?) { + val oldItem: ObservableMutableMeta? = get(name) + if (oldItem != node) { + when (name.length) { + 0 -> error("Can't set a meta with empty name") + 1 -> { + val token = name.firstOrNull()!! + replaceItem(token, oldItem, node?.let { wrapItem(node) }) + } + else -> { + val token = name.firstOrNull()!! + //get existing or create new node. Index is ignored for new node + if (items[token] == null) { + replaceItem(token, null, MutableMetaImpl(null)) + } + items[token]?.setMeta(name.cutFirst(), node) } - items[token]?.node!!.set(name.cutFirst(), item) } + invalidate(name) } } } @@ -68,28 +367,94 @@ public abstract class AbstractMutableMeta> : AbstractTypedMet /** * Append the node with a same-name-sibling, automatically generating numerical index */ -public fun MutableItemProvider.append(name: Name, value: Any?) { +public fun MutableMeta.append(name: Name, meta: Meta) { require(!name.isEmpty()) { "Name could not be empty for append operation" } val newIndex = name.lastOrNull()!!.index if (newIndex != null) { - set(name, value) + set(name, meta) } else { val index = (getIndexed(name).keys.mapNotNull { it?.toIntOrNull() }.maxOrNull() ?: -1) + 1 - set(name.withIndex(index.toString()), value) + set(name.withIndex(index.toString()), meta) } } -public fun MutableItemProvider.append(name: String, value: Any?): Unit = append(name.toName(), value) +public fun MutableMeta.append(key: String, meta: Meta): Unit = append(Name.parse(key), meta) + +public fun MutableMeta.append(name: Name, value: Value): Unit = append(name, Meta(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. +// */ +//@DFExperimental +//public fun MutableMeta.edit(name: Name, builder: MutableMeta.() -> Unit) { +// val item = when (val existingItem = get(name)) { +// null -> MutableMeta().also { set(name, it) } +// is MetaItemNode -> existingItem.node +// else -> error("Can't edit value meta item") +// } +// item.apply(builder) +//} /** - * Apply existing node with given [builder] or create a new element with it. + * Create a mutable copy of this meta. The copy is created even if the Meta is already mutable */ -@DFExperimental -public fun > M.edit(name: Name, builder: M.() -> Unit) { - val item = when (val existingItem = get(name)) { - null -> empty().also { set(name, it) } - is MetaItemNode -> existingItem.node - else -> error("Can't edit value meta item") - } - item.apply(builder) -} \ No newline at end of file +public fun Meta.toMutableMeta(): ObservableMutableMeta = MutableMetaImpl(value, items) + +public fun Meta.asMutableMeta(): MutableMeta = (this as? MutableMeta) ?: toMutableMeta() + +@Suppress("FunctionName") +@JsName("newMutableMeta") +public fun MutableMeta(): ObservableMutableMeta = MutableMetaImpl(null) + +/** + * Build a [MutableMeta] using given transformation + */ +@Suppress("FunctionName") +public inline fun MutableMeta(builder: MutableMeta.() -> Unit = {}): ObservableMutableMeta = + MutableMeta().apply(builder) + + +/** + * Create a copy of this [Meta], optionally applying the given [block]. + * The listeners of the original Config are not retained. + */ +public inline fun Meta.copy(block: MutableMeta.() -> Unit = {}): Meta = + toMutableMeta().apply(block) + + +private class MutableMetaWithDefault( + val source: MutableMeta, val default: Meta, val rootName: Name +) : MutableMeta by source { + override val items: Map + get() { + val sourceKeys: Collection = source[rootName]?.items?.keys ?: emptyList() + val defaultKeys: Collection = default[rootName]?.items?.keys ?: emptyList() + //merging keys for primary and default node + return (sourceKeys + defaultKeys).associateWith { + MutableMetaWithDefault(source, default, rootName + it) + } + } + + override var value: Value? + get() = source[rootName]?.value ?: default[rootName]?.value + set(value) { + source[rootName] = value + } + + override fun getMeta(name: Name): MutableMeta = MutableMetaWithDefault(source, default, rootName + 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) +} + +/** + * Create a mutable item provider that uses given provider for default values if those are not found in this provider. + * Changes are propagated only to this provider. + */ +public fun MutableMeta.withDefault(default: Meta?): MutableMeta = if (default == null || default.isEmpty()) { + //Optimize for use with empty default + this +} else MutableMetaWithDefault(this, default, Name.EMPTY) 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 new file mode 100644 index 00000000..d9677515 --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/MutableMetaDelegate.kt @@ -0,0 +1,171 @@ +package space.kscience.dataforge.meta + +import space.kscience.dataforge.meta.transformations.MetaConverter +import space.kscience.dataforge.names.Name +import space.kscience.dataforge.names.asName +import space.kscience.dataforge.values.* +import kotlin.properties.ReadWriteProperty +import kotlin.reflect.KProperty + +/* Read-write delegates */ + +public fun MutableMetaProvider.node(key: Name? = null): ReadWriteProperty = + object : ReadWriteProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Meta? { + return getMeta(key ?: property.name.asName()) + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Meta?) { + val name = key ?: property.name.asName() + setMeta(name, value) + } + } + +public fun MutableMetaProvider.node(key: Name? = null, converter: MetaConverter): ReadWriteProperty = + object : ReadWriteProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): T? { + return getMeta(key ?: property.name.asName())?.let { converter.metaToObject(it) } + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) { + val name = key ?: property.name.asName() + setMeta(name, value?.let { converter.objectToMeta(it) }) + } + } + +public fun MutableMetaProvider.value(key: Name? = null): ReadWriteProperty = + object : ReadWriteProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Value? = + getMeta(key ?: property.name.asName())?.value + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: Value?) { + setValue(key ?: property.name.asName(), value) + } + } + +public fun MutableMetaProvider.value( + key: Name? = null, + writer: (T) -> Value? = { Value.of(it) }, + reader: (Value?) -> T +): ReadWriteProperty = object : ReadWriteProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): T = + reader(getMeta(key ?: property.name.asName())?.value) + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { + setValue(key ?: property.name.asName(), writer(value)) + } +} + +/* Read-write delegates for [MutableItemProvider] */ + +public fun MutableMetaProvider.string(key: Name? = null): ReadWriteProperty = + value(key) { it?.string } + +public fun MutableMetaProvider.boolean(key: Name? = null): ReadWriteProperty = + value(key) { it?.boolean } + +public fun MutableMetaProvider.number(key: Name? = null): ReadWriteProperty = + value(key) { it?.number } + +public fun MutableMetaProvider.string(default: String, key: Name? = null): ReadWriteProperty = + value(key) { it?.string ?: default } + +public fun MutableMetaProvider.boolean(default: Boolean, key: Name? = null): ReadWriteProperty = + value(key) { it?.boolean ?: default } + +public fun MutableMetaProvider.number(default: Number, key: Name? = null): ReadWriteProperty = + value(key) { it?.number ?: default } + +public fun MutableMetaProvider.string(key: Name? = null, default: () -> String): ReadWriteProperty = + value(key) { it?.string ?: default() } + +public fun MutableMetaProvider.boolean(key: Name? = null, default: () -> Boolean): ReadWriteProperty = + value(key) { it?.boolean ?: default() } + +public fun MutableMetaProvider.number(key: Name? = null, default: () -> Number): ReadWriteProperty = + value(key) { it?.number ?: default() } + +public inline fun > MutableMetaProvider.enum( + default: E, + key: Name? = null, +): ReadWriteProperty = value(key) { value -> value?.string?.let { enumValueOf(it) } ?: default } + +/* Number delegates */ + +public fun MutableMetaProvider.int(key: Name? = null): ReadWriteProperty = + value(key) { it?.int } + +public fun MutableMetaProvider.double(key: Name? = null): ReadWriteProperty = + value(key) { it?.double } + +public fun MutableMetaProvider.long(key: Name? = null): ReadWriteProperty = + value(key) { it?.long } + +public fun MutableMetaProvider.float(key: Name? = null): ReadWriteProperty = + value(key) { it?.float } + + +/* Safe number delegates*/ + +public fun MutableMetaProvider.int(default: Int, key: Name? = null): ReadWriteProperty = + value(key) { it?.int ?: default } + +public fun MutableMetaProvider.double(default: Double, key: Name? = null): ReadWriteProperty = + value(key) { it?.double ?: default } + +public fun MutableMetaProvider.long(default: Long, key: Name? = null): ReadWriteProperty = + value(key) { it?.long ?: default } + +public fun MutableMetaProvider.float(default: Float, key: Name? = null): ReadWriteProperty = + value(key) { it?.float ?: default } + + +/* Extra delegates for special cases */ + +public fun MutableMetaProvider.stringList( + vararg default: String, + key: Name? = null, +): ReadWriteProperty> = value( + key, + writer = { list -> list.map { str -> str.asValue() }.asValue() }, + reader = { it?.stringList ?: listOf(*default) }, +) + +public fun MutableMetaProvider.stringList( + key: Name? = null, +): ReadWriteProperty?> = value( + key, + writer = { it -> it?.map { str -> str.asValue() }?.asValue() }, + reader = { it?.stringList }, +) + +public fun MutableMetaProvider.numberList( + vararg default: Number, + key: Name? = null, +): ReadWriteProperty> = value( + key, + writer = { it.map { num -> num.asValue() }.asValue() }, + reader = { it?.list?.map { value -> value.numberOrNull ?: Double.NaN } ?: listOf(*default) }, +) + +/* A special delegate for double arrays */ + + +public fun MutableMetaProvider.doubleArray( + vararg default: Double, + key: Name? = null, +): ReadWriteProperty = value( + key, + writer = { DoubleArrayValue(it) }, + reader = { it?.doubleArray ?: doubleArrayOf(*default) }, +) + +public fun MutableMetaProvider.listValue( + key: Name? = null, + writer: (T) -> Value = { Value.of(it) }, + reader: (Value) -> T, +): ReadWriteProperty?> = value( + key, + writer = { it?.map(writer)?.asValue() }, + reader = { it?.list?.map(reader) } +) diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableItemProvider.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableItemProvider.kt deleted file mode 100644 index d5183fb9..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableItemProvider.kt +++ /dev/null @@ -1,42 +0,0 @@ -package space.kscience.dataforge.meta - -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.KProperty1 - - -internal data class ItemListener( - val owner: Any? = null, - val action: (name: Name, oldItem: MetaItem?, newItem: MetaItem?) -> Unit, -) - - -public interface ObservableItemProvider : ItemProvider { - public fun onChange(owner: Any?, action: (name: Name, oldItem: MetaItem?, newItem: MetaItem?) -> Unit) - public fun removeListener(owner: Any?) -} - -public interface ItemPropertyProvider: ObservableItemProvider, MutableItemProvider - -/** - * Use the value of the property in a [callBack]. - * The callback is called once immediately after subscription to pass the initial value. - * - * Optional [owner] property is used for - */ -@DFExperimental -public fun O.useProperty( - property: KProperty1, - owner: Any? = null, - callBack: O.(T) -> Unit, -) { - //Pass initial value. - callBack(property.get(this)) - onChange(owner) { name, oldItem, newItem -> - if (name.startsWith(property.name.toName()) && oldItem != newItem) { - callBack(property.get(this)) - } - } -} \ No newline at end of file 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 new file mode 100644 index 00000000..73ec03b6 --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMeta.kt @@ -0,0 +1,90 @@ +package space.kscience.dataforge.meta + +import space.kscience.dataforge.names.* +import kotlin.jvm.Synchronized +import kotlin.reflect.KProperty1 + + +internal data class MetaListener( + val owner: Any? = null, + val callback: Meta.(name: Name) -> Unit, +) + +/** + * An item provider that could be observed and mutated + */ +public interface ObservableMeta : Meta { + /** + * Add change listener to this meta. Owner is declared to be able to remove listeners later. Listener without owner could not be removed + */ + public fun onChange(owner: Any?, callback: Meta.(name: Name) -> Unit) + + /** + * Remove all listeners belonging to given owner + */ + public fun removeListener(owner: Any?) + + /** + * Force-send invalidation signal for given name to all listeners + */ + public fun invalidate(name: Name) +} + +/** + * A [Meta] which is both observable and mutable + */ +public interface ObservableMutableMeta : ObservableMeta, MutableMeta, MutableTypedMeta { + override fun getOrCreate(name: Name): ObservableMutableMeta + + override fun getMeta(name: Name): ObservableMutableMeta? { + tailrec fun ObservableMutableMeta.find(name: Name): ObservableMutableMeta? = if (name.isEmpty()) { + this + } else { + items[name.firstOrNull()!!]?.find(name.cutFirst()) + } + + return find(name) + } +} + +internal abstract class AbstractObservableMeta : ObservableMeta { + private val listeners = HashSet() + + override fun invalidate(name: Name) { + listeners.forEach { it.callback(this, name) } + } + + @Synchronized + override fun onChange(owner: Any?, callback: Meta.(name: Name) -> Unit) { + listeners.add(MetaListener(owner, callback)) + } + + @Synchronized + override fun removeListener(owner: Any?) { + listeners.removeAll { it.owner === owner } + } + + 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) +} + +/** + * Use the value of the property in a [callBack]. + * The callback is called once immediately after subscription to pass the initial value. + * + * Optional [owner] property is used for + */ +public fun S.useProperty( + property: KProperty1, + owner: Any? = null, + callBack: S.(T) -> Unit, +) { + //Pass initial value. + callBack(property.get(this)) + meta.onChange(owner) { name -> + if (name.startsWith(property.name.asName())) { + callBack(property.get(this@useProperty)) + } + } +} \ No newline at end of file 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 new file mode 100644 index 00000000..53e427ef --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableMetaWrapper.kt @@ -0,0 +1,82 @@ +package space.kscience.dataforge.meta + +import space.kscience.dataforge.misc.DFExperimental +import space.kscience.dataforge.names.* +import space.kscience.dataforge.values.Value +import kotlin.jvm.Synchronized + +/** + * A class that takes [MutableMeta] provider and adds obsevability on top of that + */ +private class ObservableMetaWrapper( + val root: MutableMeta, + val absoluteName: Name, + val listeners: MutableSet +) : ObservableMutableMeta { + override val items: Map + get() = root.items.mapValues { + ObservableMetaWrapper(root, absoluteName + it.key, listeners) + } + + override fun getMeta(name: Name): ObservableMutableMeta? = + root.getMeta(name)?.let { ObservableMetaWrapper(root, this.absoluteName + name, listeners) } + + @Synchronized + 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.removeHeadOrNull(absoluteName)!!) + } + } + ) + } + + override fun removeListener(owner: Any?) { + listeners.removeAll { it.owner === Pair(owner, absoluteName) } + } + + override fun invalidate(name: Name) { + listeners.forEach { it.callback(this, name) } + } + + override var value: Value? + get() = root.value + set(value) { + root.value = value + invalidate(Name.EMPTY) + } + + override fun getOrCreate(name: Name): ObservableMutableMeta = + ObservableMetaWrapper(root, this.absoluteName + name, listeners) + + override fun setMeta(name: Name, node: Meta?) { + val oldMeta = get(name) + root.setMeta(absoluteName + name, node) + if (oldMeta != node) { + invalidate(name) + } + } + + override fun toMeta(): Meta = root[absoluteName]?.toMeta() ?: Meta.EMPTY + + 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) + + @DFExperimental + override fun attach(name: Name, node: ObservableMutableMeta) { + set(name, node) + node.onChange(this) { changeName -> + setMeta(name + changeName, node[changeName]) + } + } +} + + +/** + * Cast this [MutableMeta] to [ObservableMutableMeta] or create an observable wrapper. Only changes made to the result + * are guaranteed to be observed. + */ +public fun MutableMeta.asObservable(): ObservableMutableMeta = + (this as? ObservableMutableMeta) ?: ObservableMetaWrapper(this, Name.EMPTY, hashSetOf()) 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 07816965..d4f40eb4 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 @@ -1,132 +1,136 @@ 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.names.asName +import space.kscience.dataforge.misc.DFExperimental +import space.kscience.dataforge.names.* +import space.kscience.dataforge.values.Value import kotlin.jvm.Synchronized /** * 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() : Described, MetaRepr, ItemPropertyProvider { - - private var items: MutableItemProvider = Config() - - private val listeners = HashSet() - - private var default: ItemProvider? = null - - final override var descriptor: NodeDescriptor? = null - +public open class Scheme : Described, MetaRepr, MutableMetaProvider, Configurable { /** - * Add a listener to this scheme changes. If the inner provider is observable, then listening will be delegated to it. - * Otherwise, local listeners will be created. + * Meta to be mutated by this schme */ - @Synchronized - override fun onChange(owner: Any?, action: (Name, MetaItem?, MetaItem?) -> Unit) { - (items as? ObservableItemProvider)?.onChange(owner, action) - ?: run { listeners.add(ItemListener(owner, action)) } - } + private var targetMeta: MutableMeta = MutableMeta() /** - * Remove all listeners belonging to given owner + * Default values provided by this scheme */ - @Synchronized - override fun removeListener(owner: Any?) { - (items as? ObservableItemProvider)?.removeListener(owner) - ?: listeners.removeAll { it.owner === owner } - } + private var defaultMeta: Meta? = null + + final override val meta: ObservableMutableMeta = SchemeMeta(Name.EMPTY) + + final override var descriptor: MetaDescriptor? = null + internal set internal fun wrap( - items: MutableItemProvider, - default: ItemProvider? = null, - descriptor: NodeDescriptor? = null, + newMeta: MutableMeta, + preserveDefault: Boolean = false ) { - //use properties in the init block as default - this.default = this.items.withDefault(default) - //reset values, defaults are already saved - this.items = items - this.descriptor = descriptor - } - - private fun getDefaultItem(name: Name): MetaItem? { - return default?.get(name) ?: descriptor?.get(name)?.defaultItem() + if (preserveDefault) { + defaultMeta = targetMeta.seal() + } + targetMeta = newMeta } /** - * Get a property with default + * Check if property with given [name] could be assigned to [meta] */ - override fun getItem(name: Name): MetaItem? = items[name] ?: getDefaultItem(name) - - /** - * Check if property with given [name] could be assigned to [item] - */ - public open fun validateItem(name: Name, item: MetaItem?): Boolean { + public open fun validate(name: Name, meta: Meta?): Boolean { val descriptor = descriptor?.get(name) - return descriptor?.validateItem(item) ?: true + return descriptor?.validate(meta) ?: true } - /** - * Set a configurable property - */ - override fun setItem(name: Name, item: MetaItem?) { - val oldItem = items[name] - if (validateItem(name, item)) { - items[name] = item - listeners.forEach { it.action(name, oldItem, item) } + override fun getMeta(name: Name): MutableMeta? = meta.getMeta(name) + + override fun setMeta(name: Name, node: Meta?) { + if (validate(name, meta)) { + meta.setMeta(name, node) } else { - error("Validation failed for property $name with value $item") + error("Validation failed for node $node at $name") } } + override fun setValue(name: Name, value: Value?) { + val valueDescriptor = descriptor?.get(name) + if (valueDescriptor?.validate(value) != false) { + meta.setValue(name, value) + } else error("Value $value is not validated by $valueDescriptor") + } - /** - * Provide a default layer which returns items from [default] and falls back to descriptor - * values if default value is unavailable. - * Values from [default] completely replace - */ - public open val defaultLayer: Meta - get() = object : MetaBase() { - override val items: Map = buildMap { - descriptor?.items?.forEach { (key, itemDescriptor) -> - val token = NameToken(key) - val name = token.asName() - val item = default?.get(name) ?: itemDescriptor.defaultItem() - if (item != null) { - put(token, item) - } + override fun toMeta(): Laminate = Laminate(meta, descriptor?.defaultNode) + + private val listeners = HashSet() + + private inner class SchemeMeta(val pathName: Name) : ObservableMutableMeta { + override var value: Value? + get() = targetMeta[pathName]?.value + ?: defaultMeta?.get(pathName)?.value + ?: descriptor?.get(pathName)?.defaultValue + set(value) { + val oldValue = targetMeta[pathName]?.value + targetMeta[pathName] = value + if (oldValue != value) { + invalidate(Name.EMPTY) } } + + override val items: Map + get() { + val targetKeys = targetMeta[pathName]?.items?.keys ?: emptySet() + val defaultKeys = defaultMeta?.get(pathName)?.items?.keys ?: emptySet() + return (targetKeys + defaultKeys).associateWith { SchemeMeta(pathName + it) } + } + + override fun invalidate(name: Name) { + listeners.forEach { it.callback(this@Scheme.meta, pathName + name) } } - override fun toMeta(): Laminate = Laminate(items[Name.EMPTY].node, defaultLayer) + @Synchronized + override fun onChange(owner: Any?, callback: Meta.(name: Name) -> Unit) { + listeners.add(MetaListener(owner) { changedName -> + if (changedName.startsWith(pathName)) { + this@Scheme.meta.callback(changedName.removeHeadOrNull(pathName)!!) + } + }) + } + + @Synchronized + override fun removeListener(owner: Any?) { + listeners.removeAll { it.owner === owner } + } + + 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) + + override fun setMeta(name: Name, node: Meta?) { + targetMeta.setMeta(name, node) + invalidate(name) + } + + override fun getOrCreate(name: Name): ObservableMutableMeta = SchemeMeta(pathName + name) + + @DFExperimental + override fun attach(name: Name, node: ObservableMutableMeta) { + TODO("Not yet implemented") + } + + + } } /** - * The scheme is considered empty only if its root item does not exist. - */ -public fun Scheme.isEmpty(): Boolean = rootItem == null - -/** - * Create a new empty [Scheme] object (including defaults) and inflate it around existing [MutableItemProvider]. - * Items already present in the scheme are used as defaults. - */ -public fun > S.wrap( - items: MutableItemProvider, - default: ItemProvider? = null, - descriptor: NodeDescriptor? = null, -): T = empty().apply { - wrap(items, default, descriptor) -} - -/** - * Relocate scheme target onto given [MutableItemProvider]. Old provider does not get updates anymore. + * Relocate scheme target onto given [MutableMeta]. Old provider does not get updates anymore. * Current state of the scheme used as a default. */ -public fun T.retarget(provider: MutableItemProvider): T = apply { wrap(provider) } +public fun T.retarget(provider: MutableMeta): T = apply { + wrap(provider, true) +} /** * A shortcut to edit a [Scheme] object in-place @@ -140,16 +144,22 @@ public open class SchemeSpec( private val builder: () -> T, ) : Specification, Described { - override fun empty(): T = builder() + override fun read(source: Meta): T = builder().also { + it.wrap(MutableMeta().withDefault(source)) + } - override fun read(items: ItemProvider): T = wrap(Config(), items, descriptor) - - override fun write(target: MutableItemProvider, defaultProvider: ItemProvider): T = - wrap(target, defaultProvider, descriptor) + override fun write(target: MutableMeta): T = empty().also { + it.wrap(target) + } //TODO Generate descriptor from Scheme class - override val descriptor: NodeDescriptor? get() = null + override val descriptor: MetaDescriptor? get() = null + + override fun empty(): T = builder().also { + it.descriptor = descriptor + } @Suppress("OVERRIDE_BY_INLINE") final override inline operator fun invoke(action: T.() -> Unit): T = empty().apply(action) + } \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/SealedMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/SealedMeta.kt index 4d258e72..df9afc12 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/SealedMeta.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/SealedMeta.kt @@ -1,23 +1,47 @@ package space.kscience.dataforge.meta +import kotlinx.serialization.Serializable import space.kscience.dataforge.names.NameToken +import space.kscience.dataforge.values.Value +import space.kscience.dataforge.values.asValue /** * The meta implementation which is guaranteed to be immutable. * - * If the argument is possibly mutable node, it is copied on creation */ +@Serializable public class SealedMeta internal constructor( - override val items: Map>, -) : AbstractTypedMeta() + override val value: Value?, + override val items: Map +) : TypedMeta { + 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) +} /** - * Generate sealed node from [this]. If it is already sealed return it as is + * Generate sealed node from [this]. If it is already sealed return it as is. */ -public fun Meta.seal(): SealedMeta = this as? SealedMeta ?: SealedMeta(items.mapValues { entry -> entry.value.seal() }) +public fun Meta.seal(): SealedMeta = this as? SealedMeta ?: SealedMeta( + value, + items.mapValues { entry -> + entry.value.seal() + } +) + +@Suppress("FunctionName") +public fun Meta(value: Value): SealedMeta = SealedMeta(value, emptyMap()) + +@Suppress("FunctionName") +public fun Meta(value: Number): SealedMeta = Meta(value.asValue()) + +@Suppress("FunctionName") +public fun Meta(value: String): SealedMeta = Meta(value.asValue()) + +@Suppress("FunctionName") +public fun Meta(value: Boolean): SealedMeta = Meta(value.asValue()) + +@Suppress("FunctionName") +public inline fun Meta(builder: MutableMeta.() -> Unit): SealedMeta = + MutableMeta(builder).seal() -@Suppress("UNCHECKED_CAST") -public fun MetaItem.seal(): TypedMetaItem = when (this) { - is MetaItemValue -> this - is MetaItemNode -> MetaItemNode(node.seal()) -} \ No newline at end of file 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 865b2f31..d92b4a3b 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 @@ -1,17 +1,18 @@ package space.kscience.dataforge.meta +import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.asName import kotlin.properties.ReadWriteProperty import kotlin.reflect.KProperty -public interface ReadOnlySpecification { +public interface ReadOnlySpecification { /** * Read generic read-only meta with this [Specification] producing instance of desired type. + * The source is not mutated even if it is in theory mutable */ - public fun read(items: ItemProvider): T - + public fun read(source: Meta): T /** * Generate an empty object @@ -30,44 +31,74 @@ public interface ReadOnlySpecification { * By convention [Scheme] companion should inherit this class * */ -public interface Specification: ReadOnlySpecification { +public interface Specification : ReadOnlySpecification { /** - * Wrap [MutableItemProvider], using it as inner storage (changes to [Specification] are reflected on [MutableItemProvider] + * Wrap [MutableMeta], using it as inner storage (changes to [Specification] are reflected on [MutableMeta] */ - public fun write(target: MutableItemProvider, defaultProvider: ItemProvider = ItemProvider.EMPTY): T + public fun write(target: MutableMeta): T } /** - * Update a [MutableItemProvider] using given specification + * Update a [MutableMeta] using given specification */ -public fun MutableItemProvider.update(spec: Specification, action: T.() -> Unit) { - spec.write(this).apply(action) -} +public fun MutableMeta.updateWith( + spec: Specification, + action: T.() -> Unit +): T = spec.write(this).apply(action) + /** * Update configuration using given specification */ -public fun > Configurable.update( - spec: S, - action: C.() -> Unit, -) { - config.update(spec, action) -} +public fun Configurable.updateWith( + spec: Specification, + action: T.() -> Unit, +): T = spec.write(meta).apply(action) -public fun TypedMetaItem>.withSpec(spec: Specification): T? = - node?.let { spec.write(it) } +// +//public fun > MutableMeta.withSpec(spec: Specification): M? = +// spec.write(it) -public fun MutableItemProvider.spec( +/** + * A delegate that uses a [Specification] to wrap a child of this provider + */ +public fun MutableMeta.spec( spec: Specification, key: Name? = null, ): ReadWriteProperty = object : ReadWriteProperty { override fun getValue(thisRef: Any?, property: KProperty<*>): T { val name = key ?: property.name.asName() - return getChild(name).let { spec.write(it) } + return spec.write(getOrCreate(name)) } override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) { val name = key ?: property.name.asName() - set(name, value.toMeta().asMetaItem()) + set(name, value.toMeta()) + } +} + +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. + * The list is a snapshot of children state, so change in structure is not reflected on its composition. + */ +@DFExperimental +public fun MutableMeta.listOfSpec( + spec: Specification, + key: Name? = null, +): ReadWriteProperty> = object : ReadWriteProperty> { + override fun getValue(thisRef: Any?, property: KProperty<*>): List { + val name = key ?: property.name.asName() + return getIndexed(name).values.map { spec.write(it as MutableMeta) } + } + + override fun setValue(thisRef: Any?, property: KProperty<*>, value: List) { + val name = key ?: property.name.asName() + setIndexed(name, value.map { it.toMeta() }) } } diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/TypedMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/TypedMeta.kt deleted file mode 100644 index cd1c3c47..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/TypedMeta.kt +++ /dev/null @@ -1,51 +0,0 @@ -package space.kscience.dataforge.meta - -import kotlinx.serialization.json.Json -import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.NameToken -import space.kscience.dataforge.names.toName - -/** - * A meta node that ensures that all of its descendants has at least the same type - */ -public interface TypedMeta> : Meta { - override val items: Map> - - @Suppress("UNCHECKED_CAST") - override fun getItem(name: Name): TypedMetaItem? = super.getItem(name)?.let { it as TypedMetaItem } - //Typed meta guarantees that all children have M type -} - - -/** - * The same as [Meta.get], but with specific node type - */ -public operator fun > M.get(name: Name): TypedMetaItem? = getItem(name) - - -public operator fun > M.get(key: String): TypedMetaItem? = this[key.toName()] -public operator fun > M.get(key: NameToken): TypedMetaItem? = items[key] - -/** - * Equals, hashcode and to string for any meta - */ -public abstract class MetaBase : Meta { - - override fun equals(other: Any?): Boolean = if (other is Meta) { - Meta.equals(this, other) - } else { - false - } - - override fun hashCode(): Int = items.hashCode() - - override fun toString(): String = Json { - prettyPrint = true - useArrayPolymorphism = true - }.encodeToString(MetaSerializer, this) -} - -/** - * Equals and hash code implementation for meta node - */ -public abstract class AbstractTypedMeta> : TypedMeta, MetaBase() diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/Described.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/Described.kt index 73c4ad7c..b21363ab 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/Described.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/Described.kt @@ -4,21 +4,5 @@ package space.kscience.dataforge.meta.descriptors * An object which provides its descriptor */ public interface Described { - public val descriptor: ItemDescriptor? - - public companion object { - //public const val DESCRIPTOR_NODE: String = "@descriptor" - } -} - -///** -// * If meta node supplies explicit descriptor, return it, otherwise try to use descriptor node from meta itself -// */ -//val MetaRepr.descriptor: NodeDescriptor? -// get() { -// return if (this is Described) { -// descriptor -// } else { -// toMeta()[DESCRIPTOR_NODE].node?.let { NodeDescriptor.wrap(it) } -// } -// } \ No newline at end of file + public val descriptor: MetaDescriptor? +} \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/DescriptorMeta.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/DescriptorMeta.kt deleted file mode 100644 index 6d44012b..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/DescriptorMeta.kt +++ /dev/null @@ -1,47 +0,0 @@ -package space.kscience.dataforge.meta.descriptors - -import space.kscience.dataforge.meta.* -import space.kscience.dataforge.names.NameToken - -/** - * A [Meta] that is constructed from [NodeDescriptor] - */ -private class DescriptorMeta(val descriptor: NodeDescriptor) : Meta, MetaBase() { - override val items: Map - get() = buildMap { - descriptor.items.forEach { (token, descriptorItem) -> - val item = descriptorItem.defaultItem() - if (item != null) { - put(NameToken(token), item) - } - } - } -} - -/** - * Generate a laminate representing default item set generated by this descriptor - */ -public fun NodeDescriptor.defaultMeta(): Laminate = Laminate(default, DescriptorMeta(this)) - -/** - * Build a default [MetaItemNode] from this node descriptor - */ -internal fun NodeDescriptor.defaultItem(): MetaItemNode<*> = - MetaItemNode(defaultMeta()) - -/** - * Build a default [MetaItemValue] from this descriptor - */ -internal fun ValueDescriptor.defaultItem(): MetaItemValue? { - return MetaItemValue(default ?: return null) -} - -/** - * Build a default [TypedMetaItem] from descriptor. - */ -public fun ItemDescriptor.defaultItem(): MetaItem? { - return when (this) { - is ValueDescriptor -> defaultItem() - is NodeDescriptor -> defaultItem() - } -} \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/ItemDescriptor.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/ItemDescriptor.kt deleted file mode 100644 index a1a6a595..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/ItemDescriptor.kt +++ /dev/null @@ -1,121 +0,0 @@ -package space.kscience.dataforge.meta.descriptors - -import space.kscience.dataforge.meta.* -import space.kscience.dataforge.misc.DFBuilder -import space.kscience.dataforge.names.* - -/** - * A common parent for [ValueDescriptor] and [NodeDescriptor]. Describes a single [TypedMetaItem] or a group of same-name-siblings. - */ -public sealed interface ItemDescriptor: MetaRepr { - - /** - * True if same name siblings with this name are allowed - */ - public val multiple: Boolean - - /** - * The item description text - */ - public val info: String? - - /** - * True if the item is required - */ - public val required: Boolean - - - /** - * Additional attributes of an item. For example validation and widget parameters - * - * @return - */ - public val attributes: Meta? - - /** - * An index field by which this node is identified in case of same name siblings construct - */ - public val indexKey: String - - public companion object { - public const val DEFAULT_INDEX_KEY: String = "@index" - } -} - - -/** - * The builder for [ItemDescriptor] - */ -@DFBuilder -public sealed class ItemDescriptorBuilder(final override val config: Config) : Configurable, ItemDescriptor { - - /** - * True if same name siblings with this name are allowed - */ - override var multiple: Boolean by config.boolean(false) - - /** - * The item description text - */ - override var info: String? by config.string() - - /** - * True if the item is required - */ - abstract override var required: Boolean - - - /** - * Additional attributes of an item. For example validation and widget parameters - * - * @return - */ - override var attributes: Config? by config.node() - - /** - * An index field by which this node is identified in case of same name siblings construct - */ - override var indexKey: String by config.string(DEFAULT_INDEX_KEY) - - public abstract fun build(): ItemDescriptor - - override fun toMeta(): Meta = config - - public companion object { - public const val DEFAULT_INDEX_KEY: String = "@index" - } -} - -/** - * Configure attributes of the descriptor, creating an attributes node if needed. - */ -public inline fun ItemDescriptorBuilder.attributes(block: Config.() -> Unit) { - (attributes ?: Config().also { this.attributes = it }).apply(block) -} - -/** - * Check if given item suits the descriptor - */ -public fun ItemDescriptor.validateItem(item: MetaItem?): Boolean { - if (item == null) return !required - return when (this) { - is ValueDescriptor -> isAllowedValue(item.value ?: return false) - is NodeDescriptor -> items.all { (key, d) -> - d.validateItem(item.node[key]) - } - } -} - -/** - * Get a descriptor item associated with given name or null if item for given name not provided - */ -public operator fun ItemDescriptor.get(name: Name): ItemDescriptor? { - if (name.isEmpty()) return this - return when (this) { - is ValueDescriptor -> null // empty name already checked - is NodeDescriptor -> items[name.firstOrNull()!!.toString()]?.get(name.cutFirst()) - } -} - -public operator fun ItemDescriptor.get(name: String): ItemDescriptor? = get(name.toName()) - 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 new file mode 100644 index 00000000..cbce3e2b --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptor.kt @@ -0,0 +1,106 @@ +package space.kscience.dataforge.meta.descriptors + +import kotlinx.serialization.Serializable +import space.kscience.dataforge.meta.Meta +import space.kscience.dataforge.meta.get +import space.kscience.dataforge.meta.set +import space.kscience.dataforge.names.* +import space.kscience.dataforge.values.Value +import space.kscience.dataforge.values.ValueType + +/** + * Restrictions on value in the node + */ +public enum class ValueRequirement { + /** + * No restrictions + */ + NONE, + + /** + * The value is required + */ + REQUIRED, + + /** + * The value must be null + */ + ABSENT +} + +/** + * The descriptor for a meta + * @param info description text + * @param children child descriptors for this node + * @param multiple True if same name siblings with this name are allowed + * @param required The requirements for node content + * @param valueTypes list of allowed types for [Meta.value], null if all values are allowed. + * Empty list means that no value should be present in this node. + * @param indexKey An index field by which this node is identified in case of same name siblings construct + * @param defaultValue the default [Meta.value] for the node + * @param attributes additional attributes of this descriptor. For example validation and widget parameters + */ +@Serializable +public data class MetaDescriptor( + public val info: String? = null, + public val children: Map = emptyMap(), + public val multiple: Boolean = false, + public val valueRequirement: ValueRequirement = ValueRequirement.NONE, + public val valueTypes: List? = null, + public val indexKey: String = Meta.INDEX_KEY, + public val defaultValue: Value? = null, + public val attributes: Meta = Meta.EMPTY, +) { + /** + * A node constructed of default values for this descriptor and its children + */ + public val defaultNode: Meta by lazy { + Meta { + defaultValue?.let { defaultValue -> + this.value = defaultValue + } + children.forEach { (key, descriptor) -> + set(key, descriptor.defaultNode) + } + } + } + + public companion object { + internal const val ALLOWED_VALUES_KEY = "allowedValues" + } +} + +public val MetaDescriptor.required: Boolean get() = valueRequirement == ValueRequirement.REQUIRED || children.values.any { required } + +public val MetaDescriptor.allowedValues: List? get() = attributes[MetaDescriptor.ALLOWED_VALUES_KEY]?.value?.list + +public operator fun MetaDescriptor.get(name: Name): MetaDescriptor? = when (name.length) { + 0 -> this + 1 -> children[name.firstOrNull()!!.toString()] + else -> get(name.firstOrNull()!!.asName())?.get(name.cutFirst()) +} + +public operator fun MetaDescriptor.get(name: String): MetaDescriptor? = get(Name.parse(name)) + +public fun MetaDescriptor.validate(value: Value?): Boolean = if (value == null) { + valueRequirement != ValueRequirement.REQUIRED +} else { + if (valueRequirement == ValueRequirement.ABSENT) false + else { + (valueTypes == null || value.type in valueTypes) && (allowedValues?.let { value in it } ?: true) + } +} + +/** + * Check if given item suits the descriptor + */ +public fun MetaDescriptor.validate(item: Meta?): Boolean { + if (item == null) return !required + if (!validate(item.value)) return false + + children.forEach { (key, childDescriptor) -> + if (!childDescriptor.validate(item[key])) return false + } + return true +} + 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 new file mode 100644 index 00000000..d123bb54 --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt @@ -0,0 +1,174 @@ +package space.kscience.dataforge.meta.descriptors + +import space.kscience.dataforge.meta.* +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.set + +public class MetaDescriptorBuilder internal constructor() { + public var info: String? = null + public var children: MutableMap = linkedMapOf() + public var multiple: Boolean = false + public var valueRequirement: ValueRequirement = ValueRequirement.NONE + + public var type: List? = null + + public fun type(primaryType: ValueType, vararg otherTypes: ValueType) { + type = listOf(primaryType, *otherTypes) + } + + public var indexKey: String = Meta.INDEX_KEY + public var default: Value? = null + + public fun default(value: Any?) { + default = Value.of(value) + } + + public var attributes: MutableMeta = MutableMeta() + + public inline fun attributes(block: MutableMeta.() -> Unit) { + attributes.apply(block) + } + + public fun item(name: Name, block: MetaDescriptorBuilder.() -> Unit = {}): MetaDescriptorBuilder { + return when (name.length) { + 0 -> apply(block) + 1 -> { + val target = MetaDescriptorBuilder().apply(block) + children[name.first().body] = target + target + } + else -> { + children.getOrPut(name.first().body) { MetaDescriptorBuilder() }.item(name.cutFirst(), block) + } + } + } + + public fun node( + name: Name, + descriptor: MetaDescriptor, + block: MetaDescriptorBuilder.() -> Unit = {} + ): MetaDescriptorBuilder = when (name.length) { + 0 -> error("Can't set descriptor to root") + 1 -> { + val item = descriptor.toBuilder().apply { + valueRequirement = ValueRequirement.ABSENT + }.apply(block) + children[name.first().body] = item + item + } + else -> children.getOrPut(name.first().body) { + MetaDescriptorBuilder() + }.node(name.cutFirst(), descriptor, block) + } + + public var allowedValues: List + get() = attributes[MetaDescriptor.ALLOWED_VALUES_KEY]?.value?.list ?: emptyList() + set(value) { + attributes[MetaDescriptor.ALLOWED_VALUES_KEY] = value + } + + + public fun allowedValues(vararg values: Any) { + allowedValues = values.map { Value.of(it) } + } + + internal fun build(): MetaDescriptor = MetaDescriptor( + info = info, + children = children.mapValues { it.value.build() }, + multiple = multiple, + valueRequirement = valueRequirement, + valueTypes = type, + indexKey = indexKey, + defaultValue = default, + attributes = attributes + ) +} + +public fun MetaDescriptorBuilder.item(name: String, block: MetaDescriptorBuilder.() -> Unit): MetaDescriptorBuilder = + item(Name.parse(name), block) + +public fun MetaDescriptor(block: MetaDescriptorBuilder.() -> Unit): MetaDescriptor = + MetaDescriptorBuilder().apply(block).build() + +/** + * Create and configure child value descriptor + */ +public fun MetaDescriptorBuilder.value( + name: Name, + type: ValueType, + vararg additionalTypes: ValueType, + block: MetaDescriptorBuilder.() -> Unit = {} +): MetaDescriptorBuilder = item(name) { + type(type, *additionalTypes) + block() +} + +public fun MetaDescriptorBuilder.value( + name: String, + type: ValueType, + vararg additionalTypes: ValueType, + block: MetaDescriptorBuilder.() -> Unit = {} +): MetaDescriptorBuilder = value(Name.parse(name), type, additionalTypes = additionalTypes, block) + +/** + * Create and configure child value descriptor + */ +public fun MetaDescriptorBuilder.node( + name: Name, block: MetaDescriptorBuilder.() -> Unit +): MetaDescriptorBuilder = item(name) { + valueRequirement = ValueRequirement.ABSENT + block() +} + +public fun MetaDescriptorBuilder.node(name: String, block: MetaDescriptorBuilder.() -> Unit) { + node(Name.parse(name), block) +} + +public fun MetaDescriptorBuilder.node( + key: String, + described: Described, + block: MetaDescriptorBuilder.() -> Unit = {}, +) { + described.descriptor?.let { + node(Name.parse(key), it, block) + } +} + +public fun MetaDescriptorBuilder.required() { + valueRequirement = ValueRequirement.REQUIRED +} + +public inline fun > MetaDescriptorBuilder.enum( + key: Name, + default: E?, + crossinline modifier: MetaDescriptorBuilder.() -> Unit = {}, +): MetaDescriptorBuilder = value(key, ValueType.STRING) { + default?.let { + this.default = default.asValue() + } + allowedValues = enumValues().map { it.asValue() } + modifier() +} + +private fun MetaDescriptor.toBuilder(): MetaDescriptorBuilder = MetaDescriptorBuilder().apply { + info = this@toBuilder.info + children = this@toBuilder.children.mapValuesTo(LinkedHashMap()) { it.value.toBuilder() } + multiple = this@toBuilder.multiple + valueRequirement = this@toBuilder.valueRequirement + type = this@toBuilder.valueTypes + indexKey = this@toBuilder.indexKey + default = defaultValue + attributes = this@toBuilder.attributes.toMutableMeta() +} + +/** + * Make a deep copy of this descriptor applying given transformation [block] + */ +public fun MetaDescriptor.copy(block: MetaDescriptorBuilder.() -> Unit = {}): MetaDescriptor = + toBuilder().apply(block).build() \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/NodeDescriptor.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/NodeDescriptor.kt deleted file mode 100644 index e677ea32..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/NodeDescriptor.kt +++ /dev/null @@ -1,191 +0,0 @@ -package space.kscience.dataforge.meta.descriptors - -import space.kscience.dataforge.meta.* -import space.kscience.dataforge.misc.DFBuilder -import space.kscience.dataforge.names.* - - -/** - * Descriptor for meta node. Could contain additional information for viewing - * and editing. - * - * @author Alexander Nozik - */ -@DFBuilder -public sealed interface NodeDescriptor: ItemDescriptor { - /** - * True if the node is required - * - * @return - */ - override val required: Boolean - - /** - * The default for this node. Null if there is no default. - * - * @return - */ - public val default: Config? - - /** - * The map of children item descriptors (both nodes and values) - */ - public val items: Map - - /** - * The map of children node descriptors - */ - public val nodes: Map - - /** - * The list of children value descriptors - */ - public val values: Map - - public companion object { - - internal val ITEM_KEY: Name = "item".asName() - internal val IS_NODE_KEY: Name = "@isNode".asName() - - //TODO infer descriptor from spec - } -} - - -@DFBuilder -public class NodeDescriptorBuilder(config: Config = Config()) : ItemDescriptorBuilder(config), NodeDescriptor { - init { - config[IS_NODE_KEY] = true - } - - /** - * True if the node is required - * - * @return - */ - override var required: Boolean by config.boolean { default == null } - - /** - * The default for this node. Null if there is no default. - * - * @return - */ - override var default: Config? by config.node() - - /** - * The map of children item descriptors (both nodes and values) - */ - override val items: Map - get() = config.getIndexed(ITEM_KEY).entries.associate { (name, item) -> - if (name == null) error("Child item index should not be null") - val node = item.node ?: error("Node descriptor must be a node") - if (node[IS_NODE_KEY].boolean == true) { - name to NodeDescriptorBuilder(node as Config) - } else { - name to ValueDescriptorBuilder(node as Config) - } - } - - /** - * The map of children node descriptors - */ - @Suppress("UNCHECKED_CAST") - override val nodes: Map - get() = config.getIndexed(ITEM_KEY).entries.filter { - it.value.node[IS_NODE_KEY].boolean == true - }.associate { (name, item) -> - if (name == null) error("Child node index should not be null") - val node = item.node ?: error("Node descriptor must be a node") - name to NodeDescriptorBuilder(node as Config) - } - - /** - * The list of children value descriptors - */ - override val values: Map - get() = config.getIndexed(ITEM_KEY).entries.filter { - it.value.node[IS_NODE_KEY].boolean != true - }.associate { (name, item) -> - if (name == null) error("Child value index should not be null") - val node = item.node ?: error("Node descriptor must be a node") - name to ValueDescriptorBuilder(node as Config) - } - - private fun buildNode(name: Name): NodeDescriptorBuilder { - return when (name.length) { - 0 -> this - 1 -> { - val token = NameToken(ITEM_KEY.toString(), name.toString()) - val config: Config = config[token].node ?: Config().also { - it[IS_NODE_KEY] = true - config[token] = it - } - NodeDescriptorBuilder(config) - } - else -> buildNode(name.firstOrNull()?.asName()!!).buildNode(name.cutFirst()) - } - } - - /** - * Define a child item descriptor for this node - */ - private fun newItem(key: String, descriptor: ItemDescriptor) { - if (items.keys.contains(key)) error("The key $key already exists in descriptor") - val token = ITEM_KEY.withIndex(key) - config[token] = descriptor.toMeta() - } - - public fun item(name: Name, descriptor: ItemDescriptor) { - buildNode(name.cutLast()).newItem(name.lastOrNull().toString(), descriptor) - } - - public fun item(name: String, descriptor: ItemDescriptor) { - item(name.toName(), descriptor) - } - - /** - * Create and configure a child node descriptor - */ - public fun node(name: Name, block: NodeDescriptorBuilder.() -> Unit) { - item(name, NodeDescriptorBuilder().apply(block)) - } - - public fun node(name: String, block: NodeDescriptorBuilder.() -> Unit) { - node(name.toName(), block) - } - - /** - * Create and configure child value descriptor - */ - public fun value(name: Name, block: ValueDescriptorBuilder.() -> Unit) { - require(name.length >= 1) { "Name length for value descriptor must be non-empty" } - item(name, ValueDescriptorBuilder().apply(block)) - } - - public fun value(name: String, block: ValueDescriptorBuilder.() -> Unit) { - value(name.toName(), block) - } - - override fun build(): NodeDescriptor = NodeDescriptorBuilder(config.copy()) - - public companion object { - - internal val ITEM_KEY: Name = "item".asName() - internal val IS_NODE_KEY: Name = "@isNode".asName() - - //TODO infer descriptor from spec - } -} - -public inline fun NodeDescriptor(block: NodeDescriptorBuilder.() -> Unit): NodeDescriptor = - NodeDescriptorBuilder().apply(block) - -/** - * Merge two node descriptors into one using first one as primary - */ -public operator fun NodeDescriptor.plus(other: NodeDescriptor): NodeDescriptor { - return NodeDescriptorBuilder().apply { - config.update(other.toMeta()) - config.update(this@plus.toMeta()) - } -} \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/ValueDescriptor.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/ValueDescriptor.kt deleted file mode 100644 index 6642346f..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/ValueDescriptor.kt +++ /dev/null @@ -1,135 +0,0 @@ -package space.kscience.dataforge.meta.descriptors - -import space.kscience.dataforge.meta.* -import space.kscience.dataforge.misc.DFBuilder -import space.kscience.dataforge.values.* - - - -/** - * A descriptor for meta value - * - * Descriptor can have non-atomic path. It is resolved when descriptor is added to the node - * - * @author Alexander Nozik - */ -@DFBuilder -public sealed interface ValueDescriptor: ItemDescriptor{ - - /** - * True if the value is required - * - * @return - */ - override val required: Boolean - - /** - * The default for this value. Null if there is no default. - * - * @return - */ - public val default: Value? - - - /** - * A list of allowed ValueTypes. Empty if any value type allowed - * - * @return - */ - public val type: List? - /** - * Check if given value is allowed for here. The type should be allowed and - * if it is value should be within allowed values - * - * @param value - * @return - */ - public fun isAllowedValue(value: Value): Boolean = - (type?.let { it.contains(ValueType.STRING) || it.contains(value.type) } ?: true) - && (allowedValues.isEmpty() || allowedValues.contains(value)) - - /** - * A list of allowed values with descriptions. If empty than any value is - * allowed. - * - * @return - */ - public val allowedValues: List -} - -/** - * A builder fir [ValueDescriptor] - */ -@DFBuilder -public class ValueDescriptorBuilder(config: Config = Config()) : ItemDescriptorBuilder(config), ValueDescriptor { - - /** - * True if the value is required - * - * @return - */ - override var required: Boolean by config.boolean { default == null } - - /** - * The default for this value. Null if there is no default. - * - * @return - */ - override var default: Value? by config.value() - - public fun default(v: Any) { - this.default = Value.of(v) - } - - /** - * A list of allowed ValueTypes. Empty if any value type allowed - * - * @return - */ - override var type: List? by config.listValue { ValueType.valueOf(it.string) } - - public fun type(vararg t: ValueType) { - this.type = listOf(*t) - } - - /** - * Check if given value is allowed for here. The type should be allowed and - * if it is value should be within allowed values - * - * @param value - * @return - */ - override fun isAllowedValue(value: Value): Boolean { - return (type?.let { it.contains(ValueType.STRING) || it.contains(value.type) } ?: true) - && (allowedValues.isEmpty() || allowedValues.contains(value)) - } - - /** - * A list of allowed values with descriptions. If empty than any value is - * allowed. - * - * @return - */ - override var allowedValues: List by config.item().convert( - reader = { - val value = it.value - when { - value?.list != null -> value.list - type?.let { type -> type.size == 1 && type[0] === ValueType.BOOLEAN } ?: false -> listOf(True, False) - else -> emptyList() - } - }, - writer = { - MetaItemValue(it.asValue()) - } - ) - - /** - * Allow given list of value and forbid others - */ - public fun allow(vararg v: Any) { - this.allowedValues = v.map { Value.of(it) } - } - - override fun build(): ValueDescriptor = ValueDescriptorBuilder(config.copy()) -} diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/descriptorExtensions.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/descriptorExtensions.kt deleted file mode 100644 index 8149843e..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/descriptorExtensions.kt +++ /dev/null @@ -1,18 +0,0 @@ -package space.kscience.dataforge.meta.descriptors - -import space.kscience.dataforge.names.Name -import space.kscience.dataforge.values.ValueType -import space.kscience.dataforge.values.asValue - -public inline fun > NodeDescriptorBuilder.enum( - key: Name, - default: E?, - crossinline modifier: ValueDescriptor.() -> Unit = {}, -): Unit = value(key) { - type(ValueType.STRING) - default?.let { - default(default) - } - allowedValues = enumValues().map { it.asValue() } - modifier() -} \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/schemeDescriptor.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/schemeDescriptor.kt new file mode 100644 index 00000000..03104104 --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/schemeDescriptor.kt @@ -0,0 +1,46 @@ +package space.kscience.dataforge.meta.descriptors + +import space.kscience.dataforge.meta.Scheme +import space.kscience.dataforge.meta.SchemeSpec +import space.kscience.dataforge.values.ValueType +import kotlin.reflect.KProperty1 +import kotlin.reflect.typeOf + +public inline fun MetaDescriptorBuilder.value( + property: KProperty1, + noinline block: MetaDescriptorBuilder.() -> Unit = {}, +): MetaDescriptorBuilder = when (typeOf()) { + typeOf(), typeOf(), typeOf(), typeOf(), typeOf(), typeOf() -> + value(property.name, ValueType.NUMBER) { + block() + } + typeOf(), typeOf(), typeOf(), typeOf(), typeOf(), typeOf() -> + value(property.name, ValueType.NUMBER) { + block() + } + typeOf() -> value(property.name, ValueType.BOOLEAN) { + block() + } + typeOf>(), typeOf>(), typeOf>(), typeOf>(), typeOf>(), typeOf>(), + typeOf(), typeOf(), typeOf(), typeOf(), typeOf(), + -> value(property.name, ValueType.NUMBER) { + multiple = true + block() + } + typeOf() -> value(property.name, ValueType.STRING) { + block() + } + typeOf>(), typeOf>() -> value(property.name, ValueType.STRING) { + multiple = true + block() + } + else -> item(property.name, block) +} + +public inline fun MetaDescriptorBuilder.scheme( + property: KProperty1, + spec: SchemeSpec, + noinline block: MetaDescriptorBuilder.() -> Unit = {}, +) { + node(property.name, spec, block) +} \ No newline at end of file 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 c6cd2a4e..0c129932 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 @@ -1,47 +1,54 @@ package space.kscience.dataforge.meta -import space.kscience.dataforge.meta.descriptors.NodeDescriptor +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 /** * Convert meta to map of maps */ -public fun Meta.toMap(descriptor: NodeDescriptor? = null): Map { - return items.entries.associate { (token, item) -> - token.toString() to when (item) { - is MetaItemNode -> item.node.toMap() - is MetaItemValue -> item.value.value +public fun Meta.toMap(descriptor: MetaDescriptor? = null): Map = buildMap { + items.forEach { (key, child) -> + if (child.items.isEmpty()) { + //single-value meta is considered a leaf + put(key.toString(), child.value) + } else { + //if child contains both children and value, then value will be placed into `@value` key + put(key.toString(), child.toMap(descriptor?.get(key.body))) } } + if (value != null) { + put(Meta.VALUE_KEY, value) + } } + /** - * Convert map of maps to meta. This method will recognize [TypedMetaItem], [Map] and [List] of all mentioned above as value. - * All other values will be converted to values. + * 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 [Value]. */ @DFExperimental -public fun Map.toMeta(descriptor: NodeDescriptor? = null): Meta = Meta { +public fun Map.toMeta(@Suppress("UNUSED_PARAMETER") descriptor: MetaDescriptor? = null): Meta = Meta { @Suppress("UNCHECKED_CAST") - fun toItem(value: Any?): MetaItem = when (value) { - is MetaItem -> value - is Meta -> MetaItemNode(value) - is Map<*, *> -> MetaItemNode((value as Map).toMeta()) - else -> MetaItemValue(Value.of(value)) + fun toMeta(value: Any?): Meta = when (value) { + is Meta -> value + is Map<*, *> -> (value as Map).toMeta() + else -> Meta(Value.of(value)) } entries.forEach { (key, value) -> if (value is List<*>) { - val items = value.map { toItem(it) } - if (items.all { it is MetaItemValue }) { + val items = value.map { toMeta(it) } + if (items.all { it.isLeaf }) { set(key, ListValue(items.map { it.value!! })) } else { - setIndexedItems(key.toName(), value.map { toItem(it) }) + setIndexed(Name.parse(key), value.map { toMeta(it) }) } } else { - set(key, toItem(value)) + set(key, toMeta(value)) } } } \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/transformations/MetaConverter.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/transformations/MetaConverter.kt index be7f054c..52de57bc 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/transformations/MetaConverter.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/transformations/MetaConverter.kt @@ -1,124 +1,89 @@ package space.kscience.dataforge.meta.transformations import space.kscience.dataforge.meta.* -import space.kscience.dataforge.values.* +import space.kscience.dataforge.values.Value +import space.kscience.dataforge.values.asValue /** - * A converter of generic object to and from [TypedMetaItem] + * A converter of generic object to and from [Meta] */ -public interface MetaConverter { - public fun itemToObject(item: MetaItem): T - public fun objectToMetaItem(obj: T): MetaItem +public interface MetaConverter { + public fun metaToObject(meta: Meta): T? + public fun objectToMeta(obj: T): Meta public companion object { - public val item: MetaConverter = object : MetaConverter { - override fun itemToObject(item: MetaItem): MetaItem = item - override fun objectToMetaItem(obj: MetaItem): MetaItem = obj - } - public val meta: MetaConverter = object : MetaConverter { - override fun itemToObject(item: MetaItem): Meta = when (item) { - is MetaItemNode -> item.node - is MetaItemValue -> item.value.toMeta() - } - - override fun objectToMetaItem(obj: Meta): MetaItem = MetaItemNode(obj) + override fun metaToObject(meta: Meta): Meta = meta + override fun objectToMeta(obj: Meta): Meta = obj } public val value: MetaConverter = object : MetaConverter { - override fun itemToObject(item: MetaItem): Value = when (item) { - is MetaItemNode -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value") - is MetaItemValue -> item.value - } - - override fun objectToMetaItem(obj: Value): MetaItem = MetaItemValue(obj) + override fun metaToObject(meta: Meta): Value? = meta.value + override fun objectToMeta(obj: Value): Meta = Meta(obj) } public val string: MetaConverter = object : MetaConverter { - override fun itemToObject(item: MetaItem): String = when (item) { - is MetaItemNode -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value") - is MetaItemValue -> item.value - }.string - - override fun objectToMetaItem(obj: String): MetaItem = MetaItemValue(obj.asValue()) + override fun metaToObject(meta: Meta): String? = meta.string + override fun objectToMeta(obj: String): Meta = Meta(obj.asValue()) } public val boolean: MetaConverter = object : MetaConverter { - override fun itemToObject(item: MetaItem): Boolean = when (item) { - is MetaItemNode -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value") - is MetaItemValue -> item.value - }.boolean - - override fun objectToMetaItem(obj: Boolean): MetaItem = MetaItemValue(obj.asValue()) + override fun metaToObject(meta: Meta): Boolean? = meta.boolean + override fun objectToMeta(obj: Boolean): Meta = Meta(obj.asValue()) } public val number: MetaConverter = object : MetaConverter { - override fun itemToObject(item: MetaItem): Number = when (item) { - is MetaItemNode -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value") - is MetaItemValue -> item.value - }.number - - override fun objectToMetaItem(obj: Number): MetaItem = MetaItemValue(obj.asValue()) + override fun metaToObject(meta: Meta): Number? = meta.number + override fun objectToMeta(obj: Number): Meta = Meta(obj.asValue()) } public val double: MetaConverter = object : MetaConverter { - override fun itemToObject(item: MetaItem): Double = when (item) { - is MetaItemNode -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value") - is MetaItemValue -> item.value - }.double + override fun metaToObject(meta: Meta): Double? = meta.double - override fun objectToMetaItem(obj: Double): MetaItem = MetaItemValue(obj.asValue()) + override fun objectToMeta(obj: Double): Meta = Meta(obj.asValue()) } public val float: MetaConverter = object : MetaConverter { - override fun itemToObject(item: MetaItem): Float = when (item) { - is MetaItemNode -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value") - is MetaItemValue -> item.value - }.float + override fun metaToObject(meta: Meta): Float? = meta.float - override fun objectToMetaItem(obj: Float): MetaItem = MetaItemValue(obj.asValue()) + override fun objectToMeta(obj: Float): Meta = Meta(obj.asValue()) } public val int: MetaConverter = object : MetaConverter { - override fun itemToObject(item: MetaItem): Int = when (item) { - is MetaItemNode -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value") - is MetaItemValue -> item.value - }.int + override fun metaToObject(meta: Meta): Int? = meta.int - override fun objectToMetaItem(obj: Int): MetaItem = MetaItemValue(obj.asValue()) + override fun objectToMeta(obj: Int): Meta = Meta(obj.asValue()) } public val long: MetaConverter = object : MetaConverter { - override fun itemToObject(item: MetaItem): Long = when (item) { - is MetaItemNode -> item.node[Meta.VALUE_KEY].value ?: error("Can't convert node to a value") - is MetaItemValue -> item.value - }.long + override fun metaToObject(meta: Meta): Long? = meta.long - override fun objectToMetaItem(obj: Long): MetaItem = MetaItemValue(obj.asValue()) + override fun objectToMeta(obj: Long): Meta = Meta(obj.asValue()) } public inline fun > enum(): MetaConverter = object : MetaConverter { @Suppress("USELESS_CAST") - override fun itemToObject(item: MetaItem): E = item.enum() as? E ?: error("The Item is not a Enum") + override fun metaToObject(meta: Meta): E = meta.enum() as? E ?: error("The Item is not a Enum") - override fun objectToMetaItem(obj: E): MetaItem = MetaItemValue(obj.asValue()) + override fun objectToMeta(obj: E): Meta = Meta(obj.asValue()) } - public fun valueList(writer: (T) -> Value = { Value.of(it)}, reader: (Value) -> T): MetaConverter> = + public fun valueList( + writer: (T) -> Value = { Value.of(it) }, + reader: (Value) -> T + ): MetaConverter> = object : MetaConverter> { - override fun itemToObject(item: MetaItem): List = - item.value?.list?.map(reader) ?: error("The item is not a value list") + override fun metaToObject(meta: Meta): List = + meta.value?.list?.map(reader) ?: error("The item is not a value list") - override fun objectToMetaItem(obj: List): MetaItem = - MetaItemValue(obj.map(writer).asValue()) + override fun objectToMeta(obj: List): Meta = Meta(obj.map(writer).asValue()) } } } -public fun MetaConverter.nullableItemToObject(item: MetaItem?): T? = item?.let { itemToObject(it) } -public fun MetaConverter.nullableObjectToMetaItem(obj: T?): MetaItem? = obj?.let { objectToMetaItem(it) } +public fun MetaConverter.nullableMetaToObject(item: Meta?): T? = item?.let { metaToObject(it) } +public fun MetaConverter.nullableObjectToMeta(obj: T?): Meta? = obj?.let { objectToMeta(it) } -public fun MetaConverter.metaToObject(meta: Meta): T = itemToObject(MetaItemNode(meta)) -public fun MetaConverter.valueToObject(value: Value): T = itemToObject(MetaItemValue(value)) +public fun MetaConverter.valueToObject(value: Value): T? = metaToObject(Meta(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 3a35dbf8..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 @@ -13,7 +13,7 @@ public interface TransformationRule { /** * Check if this transformation should be applied to a node with given name and value */ - public fun matches(name: Name, item: MetaItem?): Boolean + public fun matches(name: Name, item: Meta?): Boolean /** * Select all items to be transformed. Item could be a value as well as node @@ -21,12 +21,12 @@ public interface TransformationRule { * @return a sequence of item paths to be transformed */ public fun selectItems(meta: Meta): Sequence = - meta.itemSequence().filter { matches(it.first, it.second) }.map { it.first } + meta.nodeSequence().filter { matches(it.first, it.second) }.map { it.first } /** * Apply transformation for a single item (Node or Value) to the target */ - public fun > transformItem(name: Name, item: MetaItem?, target: M): Unit + public fun transformItem(name: Name, item: Meta?, target: MutableMeta): Unit } /** @@ -34,15 +34,15 @@ public interface TransformationRule { */ public data class KeepTransformationRule(val selector: (Name) -> Boolean) : TransformationRule { - override fun matches(name: Name, item: MetaItem?): Boolean { + override fun matches(name: Name, item: Meta?): Boolean { return selector(name) } override fun selectItems(meta: Meta): Sequence = - meta.itemSequence().map { it.first }.filter(selector) + meta.nodeSequence().map { it.first }.filter(selector) - override fun > transformItem(name: Name, item: MetaItem?, target: M) { - if (selector(name)) target.set(name, item) + override fun transformItem(name: Name, item: Meta?, target: MutableMeta) { + if (selector(name)) target.setMeta(name, item) } } @@ -51,15 +51,15 @@ public data class KeepTransformationRule(val selector: (Name) -> Boolean) : */ public data class SingleItemTransformationRule( val from: Name, - val transform: MutableMeta<*>.(Name, MetaItem?) -> Unit, + val transform: MutableMeta.(Name, Meta?) -> Unit, ) : TransformationRule { - override fun matches(name: Name, item: MetaItem?): Boolean { + override fun matches(name: Name, item: Meta?): Boolean { return name == from } override fun selectItems(meta: Meta): Sequence = sequenceOf(from) - override fun > transformItem(name: Name, item: MetaItem?, target: M) { + override fun transformItem(name: Name, item: Meta?, target: MutableMeta) { if (name == this.from) { target.transform(name, item) } @@ -68,13 +68,13 @@ public data class SingleItemTransformationRule( public data class RegexItemTransformationRule( val from: Regex, - val transform: MutableMeta<*>.(name: Name, MatchResult, MetaItem?) -> Unit, + val transform: MutableMeta.(name: Name, MatchResult, Meta?) -> Unit, ) : TransformationRule { - override fun matches(name: Name, item: MetaItem?): Boolean { + override fun matches(name: Name, item: Meta?): Boolean { return from.matches(name.toString()) } - override fun > transformItem(name: Name, item: MetaItem?, target: M) { + override fun transformItem(name: Name, item: Meta?, target: MutableMeta) { val match = from.matchEntire(name.toString()) if (match != null) { target.transform(name, match, item) @@ -105,7 +105,7 @@ public value class MetaTransformation(private val transformations: Collection rule.selectItems(source).forEach { name -> rule.transformItem(name, source[name], this) @@ -131,8 +131,9 @@ public value class MetaTransformation(private val transformations: Collection> bind(source: Config, target: M) { - source.onChange(target) { name, _, newItem -> + public fun bind(source: ObservableMeta, target: MutableMeta) { + source.onChange(target) { name -> + val newItem = source[name] transformations.forEach { t -> if (t.matches(name, newItem)) { t.transformItem(name, newItem, target) @@ -172,18 +173,18 @@ public class MetaTransformationBuilder { */ public fun keep(regex: String) { transformations.add( - RegexItemTransformationRule(regex.toRegex()) { name, _, metaItem -> - set(name, metaItem) + RegexItemTransformationRule(regex.toRegex()) { name, _, Meta -> + setMeta(name, Meta) }) } /** * Move an item from [from] to [to], optionally applying [operation] it defined */ - public fun move(from: Name, to: Name, operation: (MetaItem?) -> Any? = { it }) { + 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/misc/cast.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/cast.kt new file mode 100644 index 00000000..e714d596 --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/misc/cast.kt @@ -0,0 +1,3 @@ +package space.kscience.dataforge.misc + +public expect inline fun Any?.unsafeCast(): T \ No newline at end of file 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 7d7a214d..7bf8d14e 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,66 @@ public class Name(public val tokens: List) { public val MATCH_ALL_TOKEN: NameToken = NameToken("**") public val EMPTY: Name = Name(emptyList()) + + /** + * Convert a list of strings to a [Name] interpreting all arguments as token bodies without indices + */ + public fun of(vararg strings: String): Name = Name(strings.map { NameToken(it) }) + + /** + * 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()) + } } } @@ -74,61 +134,11 @@ public fun Name.lastOrNull(): NameToken? = tokens.lastOrNull() */ public fun Name.firstOrNull(): NameToken? = tokens.firstOrNull() - /** - * 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. + * First token or throw exception */ -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 +public fun Name.first(): NameToken = tokens.first() - 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. @@ -140,7 +150,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) @@ -169,8 +179,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 */ @@ -185,7 +195,7 @@ public fun Name.endsWith(name: Name): Boolean = this.length >= name.length && (this == name || tokens.subList(length - name.length, length) == name.tokens) /** - * if [this] starts with given [head] name, returns the reminder of the name (could be empty). Otherwise returns null + * if [this] starts with given [head] name, returns the reminder of the name (could be empty). Otherwise, returns null */ public fun Name.removeHeadOrNull(head: Name): Name? = if (startsWith(head)) { Name(tokens.subList(head.length, length)) 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/commonMain/kotlin/space/kscience/dataforge/values/Value.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/values/Value.kt index 3c708a2d..e2a83b9c 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/values/Value.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/values/Value.kt @@ -1,6 +1,7 @@ package space.kscience.dataforge.values import kotlinx.serialization.Serializable +import kotlin.jvm.JvmInline /** @@ -153,16 +154,10 @@ public class NumberValue(public val number: Number) : Value { override fun hashCode(): Int = numberOrNull.hashCode() } -public class StringValue(public val string: String) : Value { +@JvmInline +public value class StringValue(public val string: String) : Value { override val value: Any get() = string override val type: ValueType get() = ValueType.STRING - - override fun equals(other: Any?): Boolean { - return this.string == (other as? Value)?.string - } - - override fun hashCode(): Int = string.hashCode() - override fun toString(): String = string } @@ -199,11 +194,14 @@ public class ListValue(override val list: List) : Value, Iterable return list.hashCode() } - public companion object{ + public companion object { public val EMPTY: ListValue = ListValue(emptyList()) } } +public fun ListValue(vararg numbers: Number): ListValue = ListValue(numbers.map { it.asValue() }) +public fun ListValue(vararg strings: String): ListValue = ListValue(strings.map { it.asValue() }) + public fun Number.asValue(): Value = NumberValue(this) public fun Boolean.asValue(): Value = if (this) True else False diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/values/ValueProvider.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/values/ValueProvider.kt new file mode 100644 index 00000000..300c3b6a --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/values/ValueProvider.kt @@ -0,0 +1,23 @@ +package space.kscience.dataforge.values + +import space.kscience.dataforge.names.Name + +/** + * An object that could provide values + */ +public fun interface ValueProvider { + public fun getValue(name: Name): Value? +} + +public fun ValueProvider.getValue(key: String): Value? = getValue(Name.parse(key)) + +/** + * An object that could consume values + */ +public interface MutableValueProvider : ValueProvider { + public fun setValue(name: Name, value: Value?) +} + +public fun MutableValueProvider.setValue(key: String, value: Value?) { + setValue(Name.parse(key), value) +} \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/values/valueExtensions.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/values/valueExtensions.kt index 785730d9..68755825 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/values/valueExtensions.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/values/valueExtensions.kt @@ -1,7 +1,6 @@ package space.kscience.dataforge.values import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MetaBuilder /** * Check if value is null @@ -25,6 +24,13 @@ public val Value.float: Float get() = number.toFloat() public val Value.short: Short get() = number.toShort() public val Value.long: Long get() = number.toLong() +public inline fun > Value.enum(): E = if (this is EnumValue<*>) { + value as E +} else { + enumValueOf(string) +} + + public val Value.stringList: List get() = list.map { it.string } public val Value.doubleArray: DoubleArray @@ -35,4 +41,4 @@ public val Value.doubleArray: DoubleArray } -public fun Value.toMeta(): MetaBuilder = Meta { Meta.VALUE_KEY put this } \ No newline at end of file +public fun Value.toMeta(): Meta = Meta(this) \ No newline at end of file diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/ConfigTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/ConfigTest.kt index 3ea8d7d3..a2117abf 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/ConfigTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/ConfigTest.kt @@ -6,7 +6,7 @@ import kotlin.test.assertEquals class ConfigTest { @Test fun testIndexedWrite(){ - val config = Config() + val config = MutableMeta() config["a[1].b"] = 1 assertEquals(null, config["a.b"].int) assertEquals(1, config["a[1].b"].int) diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/JsonMetaTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/JsonMetaTest.kt index 6863a1a0..fba9b596 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/JsonMetaTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/JsonMetaTest.kt @@ -1,7 +1,8 @@ package space.kscience.dataforge.meta import kotlinx.serialization.json.* -import space.kscience.dataforge.meta.descriptors.NodeDescriptor +import space.kscience.dataforge.meta.descriptors.MetaDescriptor +import space.kscience.dataforge.meta.descriptors.item import kotlin.test.Test import kotlin.test.assertEquals @@ -30,8 +31,8 @@ class JsonMetaTest { }) } - val descriptor = NodeDescriptor{ - node("nodeArray"){ + val descriptor = MetaDescriptor { + item("nodeArray") { indexKey = "index" } } @@ -43,8 +44,17 @@ class JsonMetaTest { //println(meta) val reconstructed = meta.toJson(descriptor) println(reconstructed) - assertEquals(2, - reconstructed["nodeArray"]?.jsonArray?.get(1)?.jsonObject?.get("index")?.jsonPrimitive?.int) - assertEquals(json,reconstructed) + assertEquals( + 2, + reconstructed + .jsonObject["nodeArray"] + ?.jsonArray + ?.get(1) + ?.jsonObject + ?.get("index") + ?.jsonPrimitive + ?.int + ) + assertEquals(json, reconstructed) } } \ No newline at end of file diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MetaBuilderTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MetaBuilderTest.kt index 50914147..3667110f 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MetaBuilderTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MetaBuilderTest.kt @@ -1,5 +1,6 @@ package space.kscience.dataforge.meta +import space.kscience.dataforge.values.Value import space.kscience.dataforge.values.asValue import kotlin.test.Test import kotlin.test.assertEquals @@ -10,7 +11,7 @@ class MetaBuilderTest { fun testBuilder() { val meta = Meta { "a" put 22 - "b" put listOf(1, 2, 3) + "b" put Value.of(listOf(1, 2, 3)) this["c"] = "myValue".asValue() "node" put { "e" put 12.2 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 ce5ad197..7a2dbc22 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 @@ -1,6 +1,5 @@ package space.kscience.dataforge.meta -import space.kscience.dataforge.values.asValue import kotlin.test.Test import kotlin.test.assertEquals @@ -11,17 +10,17 @@ class MetaDelegateTest { NO } - class InnerSpec : Scheme() { + class InnerScheme : Scheme() { var innerValue by string() - companion object : SchemeSpec(::InnerSpec) + companion object : SchemeSpec(::InnerScheme) } class TestScheme : Scheme() { var myValue by string() var safeValue by double(2.2) var enumValue by enum(TestEnum.YES) - var inner by spec(InnerSpec) + var inner by spec(InnerScheme) companion object : SchemeSpec(::TestScheme) } @@ -30,10 +29,10 @@ class MetaDelegateTest { fun delegateTest() { val testObject = TestScheme.empty() - testObject.set("myValue","theString".asValue()) + testObject.meta["myValue"] = "theString" testObject.enumValue = TestEnum.NO - testObject.inner = InnerSpec { innerValue = "ddd" } + testObject.inner = InnerScheme { innerValue = "ddd" } assertEquals("theString", testObject.myValue) assertEquals(TestEnum.NO, testObject.enumValue) diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MetaTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MetaTest.kt index f3971b66..f88bc307 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MetaTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MetaTest.kt @@ -40,7 +40,7 @@ class MetaTest { "b" put { "c" put "ddd" } - "list" put (0..4).map { + "list" putIndexed (0..4).map { Meta { "value" put it } diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MutableMetaTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MutableMetaTest.kt index 55a0a6de..534d907e 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MutableMetaTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/MutableMetaTest.kt @@ -6,7 +6,7 @@ import kotlin.test.assertEquals class MutableMetaTest{ @Test fun testRemove(){ - val meta = Meta { + val meta = MutableMeta { "aNode" put { "innerNode" put { "innerValue" put true @@ -14,7 +14,7 @@ class MutableMetaTest{ "b" put 22 "c" put "StringValue" } - }.asConfig() + } meta.remove("aNode.c") assertEquals(meta["aNode.c"], null) diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SchemeTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SchemeTest.kt index 2b55658e..87948ec9 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SchemeTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SchemeTest.kt @@ -7,27 +7,27 @@ import kotlin.test.assertEquals @DFExperimental class SchemeTest { @Test - fun testSchemeWrappingBeforeEdit(){ - val config = Config() - val scheme = TestScheme.wrap(config) + fun testSchemeWrappingBeforeEdit() { + val config = MutableMeta() + val scheme = TestScheme.write(config) scheme.a = 29 assertEquals(29, config["a"].int) } @Test - fun testSchemeWrappingAfterEdit(){ + fun testSchemeWrappingAfterEdit() { val scheme = TestScheme.empty() scheme.a = 29 - val config = Config() + val config = MutableMeta() scheme.retarget(config) assertEquals(29, scheme.a) } @Test - fun testSchemeSubscription(){ + fun testSchemeSubscription() { val scheme = TestScheme.empty() var flag: Int? = null - scheme.useProperty(TestScheme::a){a-> + scheme.useProperty(TestScheme::a) { a -> flag = a } scheme.a = 2 diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SpecificationTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SpecificationTest.kt index 66e749be..3a61363c 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SpecificationTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SpecificationTest.kt @@ -9,16 +9,7 @@ internal class TestScheme : Scheme() { var a by int() var b by string() - companion object : Specification { - override fun empty(): TestScheme = TestScheme() - - override fun read(items: ItemProvider): TestScheme = - wrap(Config(), items) - - override fun write(target: MutableItemProvider, defaultProvider: ItemProvider): TestScheme = - wrap(target, defaultProvider) - - } + companion object : SchemeSpec(::TestScheme) } class SpecificationTest { @@ -58,8 +49,8 @@ class SpecificationTest { @Test fun testChildModification() { - val config = Config() - val child = config.getChild("child") + val config = MutableMeta() + val child = config.getOrCreate("child") val scheme = TestScheme.write(child) scheme.a = 22 scheme.b = "test" @@ -69,9 +60,9 @@ class SpecificationTest { @Test fun testChildUpdate() { - val config = Config() - val child = config.getChild("child") - child.update(TestScheme) { + val config = MutableMeta() + val child = config.getOrCreate("child") + child.updateWith(TestScheme) { a = 22 b = "test" } 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 7263ead6..b05d6e4e 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 @@ -9,16 +9,14 @@ import kotlin.test.assertNotNull class DescriptorTest { - val descriptor = NodeDescriptor { + val descriptor = MetaDescriptor { node("aNode") { info = "A root demo node" - value("b") { + value("b", ValueType.NUMBER) { info = "b number value" - type(ValueType.NUMBER) } node("otherNode") { - value("otherValue") { - type(ValueType.BOOLEAN) + value("otherValue", ValueType.BOOLEAN) { default(false) info = "default value" } @@ -30,13 +28,13 @@ class DescriptorTest { fun testAllowedValues() { val child = descriptor["aNode.b"] assertNotNull(child) - val allowed = descriptor.nodes["aNode"]?.values?.get("b")?.allowedValues - assertEquals(emptyList(), allowed) + val allowed = descriptor["aNode"]?.get("b")?.allowedValues + assertEquals(null, allowed) } @Test - fun testDefaultMetaNode(){ - val meta = descriptor.defaultMeta() + fun testDefaultMetaNode() { + val meta = descriptor.defaultNode assertEquals(false, meta["aNode.otherNode.otherValue"].boolean) } } \ No newline at end of file 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 6568d9cb..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,13 +1,12 @@ package space.kscience.dataforge.meta import space.kscience.dataforge.names.NameToken -import space.kscience.dataforge.values.Null import space.kscience.dataforge.values.Value +import space.kscience.dataforge.values.asValue import space.kscience.dataforge.values.isList //TODO add Meta wrapper for dynamic - public fun Value.toDynamic(): dynamic { return if (isList()) { list.map { it.toDynamic() }.toTypedArray().asDynamic() @@ -21,14 +20,10 @@ public fun Value.toDynamic(): dynamic { */ public fun Meta.toDynamic(): dynamic { if (this is DynamicMeta) return this.obj - - fun MetaItem.toDynamic(): dynamic = when (this) { - is MetaItemValue -> this.value.toDynamic() - is MetaItemNode -> this.node.toDynamic() - } + if(items.isEmpty()) return value?.toDynamic() val res = js("{}") - this.items.entries.groupBy { it.key.body }.forEach { (key, value) -> + items.entries.groupBy { it.key.body }.forEach { (key, value) -> val list = value.map { it.value } res[key] = when (list.size) { 1 -> list.first().toDynamic() @@ -38,46 +33,60 @@ public fun Meta.toDynamic(): dynamic { return res } -public class DynamicMeta(internal val obj: dynamic) : MetaBase() { - private fun keys(): Array = js("Object").keys(obj) +public class DynamicMeta(internal val obj: dynamic) : TypedMeta { + private fun keys(): Array = js("Object").keys(obj) as Array private fun isArray(@Suppress("UNUSED_PARAMETER") obj: dynamic): Boolean = - js("Array.isArray(obj)") as Boolean + js("Array").isArray(obj) as Boolean private fun isPrimitive(obj: dynamic): Boolean = (jsTypeOf(obj) != "object") - @Suppress("UNCHECKED_CAST", "USELESS_CAST") - private fun asItem(obj: dynamic): TypedMetaItem? { - return when { - obj == null -> MetaItemValue(Null) - isArray(obj) && (obj as Array).all { isPrimitive(it) } -> MetaItemValue(Value.of(obj as Array)) - else -> when (jsTypeOf(obj)) { - "boolean" -> MetaItemValue(Value.of(obj as Boolean)) - "number" -> MetaItemValue(Value.of(obj as Number)) - "string" -> MetaItemValue(Value.of(obj as String)) - "object" -> MetaItemNode(DynamicMeta(obj)) - else -> null - } + @Suppress("USELESS_CAST") + override val value: Value? + get() = if (isArray(obj) && (obj as Array).all { isPrimitive(it) }) Value.of(obj as Array) + else when (jsTypeOf(obj)) { + "boolean" -> (obj as Boolean).asValue() + "number" -> (obj as Number).asValue() + "string" -> (obj as String).asValue() + else -> null } - } - override val items: Map> - get() = keys().flatMap>> { key -> + override val items: Map + get() = if (isPrimitive(obj)) { + emptyMap() + } else if (isArray(obj)) { + if((obj as Array).all { isPrimitive(it) }){ + emptyMap() + } else{ + (obj as Array).mapIndexed{ index: Int, b: dynamic -> + val indexString = b[Meta.INDEX_KEY]?.toString() ?: index.toString() + NameToken(Meta.JSON_ARRAY_KEY, indexString) to DynamicMeta(b) + }.toMap() + } + } else keys().flatMap { key -> val value = obj[key] ?: return@flatMap emptyList() - if (isArray(value)) { - val array = value as Array - return@flatMap if (array.all { isPrimitive(it) }) { - listOf(NameToken(key) to MetaItemValue(Value.of(array))) - } else { - array.mapIndexedNotNull { index, it -> - val item = asItem(it) ?: return@mapIndexedNotNull null - NameToken(key, index.toString()) to item + when { + isArray(value) -> { + val array = value as Array + if (array.all { isPrimitive(it) }) { + //primitive value + listOf(NameToken(key) to DynamicMeta(value)) + } else { + array.mapIndexedNotNull { index, it -> + val item = DynamicMeta(it) + NameToken(key, index.toString()) to item + } } } - } else { - val item = asItem(value) ?: return@flatMap emptyList() - listOf(NameToken(key) to item) + else -> { + val item = DynamicMeta(value) + listOf(NameToken(key) to item) + } } - }.associate { it } + }.toMap() + + 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) } \ No newline at end of file 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 new file mode 100644 index 00000000..b404ebb4 --- /dev/null +++ b/dataforge-meta/src/jsMain/kotlin/space/kscience/dataforge/misc/castJs.kt @@ -0,0 +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 diff --git a/dataforge-meta/src/jsTest/kotlin/space/kscience/dataforge/meta/DynamicMetaTest.kt b/dataforge-meta/src/jsTest/kotlin/space/kscience/dataforge/meta/DynamicMetaTest.kt index 2c9c3e23..a03865a8 100644 --- a/dataforge-meta/src/jsTest/kotlin/space/kscience/dataforge/meta/DynamicMetaTest.kt +++ b/dataforge-meta/src/jsTest/kotlin/space/kscience/dataforge/meta/DynamicMetaTest.kt @@ -1,5 +1,6 @@ package space.kscience.dataforge.meta +import space.kscience.dataforge.values.ListValue import space.kscience.dataforge.values.int import kotlin.test.Test import kotlin.test.assertEquals @@ -21,7 +22,7 @@ class DynamicMetaTest { val meta = DynamicMeta(d) println(meta) assertEquals(true, meta["ob.booleanNode"].boolean) - assertEquals(2, meta["array"].value?.list?.get(1)?.int) + assertEquals(2, meta["array"]?.value?.list?.get(1)?.int) assertEquals(4, meta.items.size) } @@ -29,7 +30,7 @@ class DynamicMetaTest { fun testMetaToDynamic(){ val meta = Meta { "a" put 22 - "array" put listOf(1, 2, 3) + "array" put ListValue(1, 2, 3) "b" put "myString" "ob" put { "childNode" put 18 @@ -38,6 +39,7 @@ class DynamicMetaTest { } val dynamic = meta.toDynamic() + println(JSON.stringify(dynamic)) assertEquals(2,dynamic.array[1]) assertEquals(22, dynamic.a) val keys = js("Object.keys(dynamic)") as Array diff --git a/dataforge-meta/src/jvmMain/kotlin/space/kscience/dataforge/misc/castJvm.kt b/dataforge-meta/src/jvmMain/kotlin/space/kscience/dataforge/misc/castJvm.kt new file mode 100644 index 00000000..27d399fe --- /dev/null +++ b/dataforge-meta/src/jvmMain/kotlin/space/kscience/dataforge/misc/castJvm.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-meta/src/nativeMain/kotlin/space/kscience/dataforge/misc/castNative.kt b/dataforge-meta/src/nativeMain/kotlin/space/kscience/dataforge/misc/castNative.kt new file mode 100644 index 00000000..27d399fe --- /dev/null +++ b/dataforge-meta/src/nativeMain/kotlin/space/kscience/dataforge/misc/castNative.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/src/jvmMain/kotlin/space/kscience/dataforge/scripting/Builders.kt b/dataforge-scripting/src/jvmMain/kotlin/space/kscience/dataforge/scripting/Builders.kt index 28f05216..19c6e640 100644 --- a/dataforge-scripting/src/jvmMain/kotlin/space/kscience/dataforge/scripting/Builders.kt +++ b/dataforge-scripting/src/jvmMain/kotlin/space/kscience/dataforge/scripting/Builders.kt @@ -51,7 +51,7 @@ public object Builders { return builder.build() } - public fun buildWorkspace(file: File): Workspace = buildWorkspace(file.toScriptSource()) + public fun buildWorkspace(scriptFile: File): Workspace = buildWorkspace(scriptFile.toScriptSource()) - public fun buildWorkspace(string: String): Workspace = buildWorkspace(string.toScriptSource()) + public fun buildWorkspace(scriptString: String): Workspace = buildWorkspace(scriptString.toScriptSource()) } \ No newline at end of file diff --git a/dataforge-scripting/src/jvmTest/kotlin/space/kscience/dataforge/scripting/BuildersKtTest.kt b/dataforge-scripting/src/jvmTest/kotlin/space/kscience/dataforge/scripting/BuildersKtTest.kt index c0f557e4..36ad16fb 100644 --- a/dataforge-scripting/src/jvmTest/kotlin/space/kscience/dataforge/scripting/BuildersKtTest.kt +++ b/dataforge-scripting/src/jvmTest/kotlin/space/kscience/dataforge/scripting/BuildersKtTest.kt @@ -3,7 +3,7 @@ package space.kscience.dataforge.scripting import space.kscience.dataforge.context.Global import space.kscience.dataforge.meta.get import space.kscience.dataforge.meta.int -import space.kscience.dataforge.workspace.WorkspaceBuilder +import space.kscience.dataforge.workspace.Workspace import space.kscience.dataforge.workspace.target import kotlin.test.Test import kotlin.test.assertEquals @@ -12,7 +12,7 @@ import kotlin.test.assertEquals class BuildersKtTest { @Test fun checkBuilder() { - val workspace = WorkspaceBuilder(Global).apply { + Workspace(Global){ println("I am working") context { name("test") } diff --git a/dataforge-tables/build.gradle.kts b/dataforge-tables/build.gradle.kts deleted file mode 100644 index 507b1f71..00000000 --- a/dataforge-tables/build.gradle.kts +++ /dev/null @@ -1,21 +0,0 @@ -plugins { - id("ru.mipt.npm.gradle.mpp") - id("ru.mipt.npm.gradle.native") -} - -kotlin { - sourceSets { - commonMain{ - dependencies { - api(project(":dataforge-context")) - api(project(":dataforge-io")) - - api(kotlin("reflect")) - } - } - } -} - -readme{ - maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE -} \ No newline at end of file diff --git a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/ColumnDef.kt b/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/ColumnDef.kt deleted file mode 100644 index 68723922..00000000 --- a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/ColumnDef.kt +++ /dev/null @@ -1,10 +0,0 @@ -package space.kscience.dataforge.tables - -import space.kscience.dataforge.meta.Meta -import kotlin.reflect.KType - -public data class ColumnDef( - override val name: String, - override val type: KType, - override val meta: Meta -): ColumnHeader \ No newline at end of file diff --git a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/ColumnHeader.kt b/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/ColumnHeader.kt deleted file mode 100644 index e0a3e30e..00000000 --- a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/ColumnHeader.kt +++ /dev/null @@ -1,37 +0,0 @@ -package space.kscience.dataforge.tables - -import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.get -import space.kscience.dataforge.meta.int -import space.kscience.dataforge.meta.string -import space.kscience.dataforge.values.Value -import space.kscience.dataforge.values.ValueType -import kotlin.reflect.KType - -public typealias TableHeader = List> - -public typealias ValueTableHeader = List> - -public interface ColumnHeader { - public val name: String - public val type: KType - public val meta: Meta -} - -public data class SimpleColumnHeader( - override val name: String, - override val type: KType, - override val meta: Meta -) : ColumnHeader - -public val ColumnHeader.valueType: ValueType? get() = meta["valueType"].string?.let { ValueType.valueOf(it) } - -public val ColumnHeader.textWidth: Int - get() = meta["columnWidth"].int ?: when (valueType) { - ValueType.NUMBER -> 8 - ValueType.STRING -> 16 - ValueType.BOOLEAN -> 5 - ValueType.NULL -> 5 - ValueType.LIST -> 32 - null -> 16 - } diff --git a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/ColumnScheme.kt b/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/ColumnScheme.kt deleted file mode 100644 index fc2e4196..00000000 --- a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/ColumnScheme.kt +++ /dev/null @@ -1,17 +0,0 @@ -package space.kscience.dataforge.tables - -import space.kscience.dataforge.meta.Scheme -import space.kscience.dataforge.meta.SchemeSpec -import space.kscience.dataforge.meta.enum -import space.kscience.dataforge.meta.string -import space.kscience.dataforge.values.ValueType - -public open class ColumnScheme : Scheme() { - public var title: String? by string() - - public companion object : SchemeSpec(::ColumnScheme) -} - -public class ValueColumnScheme : ColumnScheme() { - public var valueType: ValueType by enum(ValueType.STRING) -} \ No newline at end of file diff --git a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/ColumnTable.kt b/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/ColumnTable.kt deleted file mode 100644 index 38a9d58e..00000000 --- a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/ColumnTable.kt +++ /dev/null @@ -1,26 +0,0 @@ -package space.kscience.dataforge.tables - -/** - * @param T bottom type for all columns in the table - */ -public class ColumnTable(override val columns: Collection>) : Table { - private val rowsNum = columns.first().size - - init { - require(columns.all { it.size == rowsNum }) { "All columns must be of the same size" } - } - - override val rows: List> - get() = (0 until rowsNum).map { VirtualRow(this, it) } - - override fun get(row: Int, column: String): T? = columns[column]?.get(row) -} - -internal class VirtualRow(val table: Table, val index: Int) : Row { - override fun get(column: String): T? = table.get(index, column) - -// override fun get(columnHeader: ColumnHeader): T? { -// return table.co[columnHeader][index] -// } -} - diff --git a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/ListColumn.kt b/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/ListColumn.kt deleted file mode 100644 index b720fe1f..00000000 --- a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/ListColumn.kt +++ /dev/null @@ -1,36 +0,0 @@ -package space.kscience.dataforge.tables - -import space.kscience.dataforge.meta.Meta -import kotlin.reflect.KType -import kotlin.reflect.typeOf - -public class ListColumn( - override val name: String, - private val data: List, - override val type: KType, - override val meta: Meta -) : Column { - override val size: Int get() = data.size - - override fun get(index: Int): T? = data[index] - - public companion object { - public inline operator fun invoke( - name: String, - def: ColumnScheme, - data: List - ): ListColumn = ListColumn(name, data, typeOf(), def.toMeta()) - - public inline operator fun invoke( - name: String, - def: ColumnScheme, - size: Int, - dataBuilder: (Int) -> T? - ): ListColumn = invoke(name, def, List(size, dataBuilder)) - } -} - -public inline fun Column.map(meta: Meta = this.meta, noinline block: (T?) -> R): Column { - val data = List(size) { block(get(it)) } - return ListColumn(name, data, typeOf(), meta) -} \ No newline at end of file diff --git a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/MutableColumnTable.kt b/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/MutableColumnTable.kt deleted file mode 100644 index 50632709..00000000 --- a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/MutableColumnTable.kt +++ /dev/null @@ -1,31 +0,0 @@ -package space.kscience.dataforge.tables - -/** - * Mutable table with a fixed size, but dynamic columns - */ -public class MutableColumnTable(public val size: Int) : Table { - private val _columns = ArrayList>() - - override val columns: List> get() = _columns - override val rows: List> get() = (0 until size).map { - VirtualRow(this, it) - } - - override fun get(row: Int, column: String): C? = columns[column]?.get(row) - - /** - * Add a fixed column to the end of the table - */ - public fun add(column: Column) { - require(column.size == this.size) { "Required column size $size, but found ${column.size}" } - _columns.add(column) - } - - /** - * Insert a column at [index] - */ - public fun insert(index: Int, column: Column) { - require(column.size == this.size) { "Required column size $size, but found ${column.size}" } - _columns.add(index, column) - } -} diff --git a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/MutableTable.kt b/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/MutableTable.kt deleted file mode 100644 index 494bf4f2..00000000 --- a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/MutableTable.kt +++ /dev/null @@ -1,50 +0,0 @@ -package space.kscience.dataforge.tables - -import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.values.Value -import kotlin.properties.PropertyDelegateProvider -import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KType -import kotlin.reflect.typeOf - -public class MutableTable( - override val rows: MutableList>, - override val headers: MutableList>, -) : RowTable(rows, headers) { - - @PublishedApi - internal fun addColumn(name: String, type: KType, meta: Meta): ColumnHeader { - val column = SimpleColumnHeader(name, type, meta) - headers.add(column) - return column - } - - public inline fun addColumn( - name: String, - noinline columnMetaBuilder: ColumnScheme.() -> Unit = {}, - ): ColumnHeader = addColumn(name, typeOf(), ColumnScheme(columnMetaBuilder).toMeta()) - - public inline fun column( - noinline columnMetaBuilder: ColumnScheme.() -> Unit = {} - ): PropertyDelegateProvider>> = - PropertyDelegateProvider { _, property -> - val res = addColumn(property.name, columnMetaBuilder) - ReadOnlyProperty { _, _ -> res } - } - - public fun row(map: Map): Row { - val row = MapRow(map) - rows.add(row) - return row - } - - public fun row(vararg pairs: Pair, T>): Row = - row(pairs.associate { it.first.name to it.second }) -} - -public fun MutableTable.row(vararg pairs: Pair, Any?>): Row = - row(pairs.associate { it.first.name to Value.of(it.second) }) - -public fun Table.edit(block: MutableTable.() -> Unit): Table { - return MutableTable(rows.toMutableList(), headers.toMutableList()).apply(block) -} \ No newline at end of file diff --git a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/RowTable.kt b/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/RowTable.kt deleted file mode 100644 index 4c5bae5e..00000000 --- a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/RowTable.kt +++ /dev/null @@ -1,34 +0,0 @@ -package space.kscience.dataforge.tables - -import kotlinx.coroutines.flow.toList -import space.kscience.dataforge.meta.Meta -import kotlin.jvm.JvmInline -import kotlin.reflect.KType - -@JvmInline -public value class MapRow(private val values: Map) : Row { - override fun get(column: String): C? = values[column] -} - -internal class RowTableColumn(val table: Table, val header: ColumnHeader) : Column { - init { - require(header in table.headers){"Header $header does not belong to $table"} - } - - override val name: String get() = header.name - override val type: KType get() = header.type - override val meta: Meta get() = header.meta - override val size: Int get() = table.rows.size - - @Suppress("UNCHECKED_CAST") - override fun get(index: Int): R? = table[index, name]?.let { it as R} -} - -public open class RowTable(override val rows: List>, override val headers: List>) : - Table { - override fun get(row: Int, column: String): C? = rows[row].get(column) - - override val columns: List> get() = headers.map { RowTableColumn(this, it) } -} - -public suspend fun Rows.collect(): Table = this as? Table ?: RowTable(rowFlow().toList(), headers) \ No newline at end of file diff --git a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/Table.kt b/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/Table.kt deleted file mode 100644 index 2fa199ec..00000000 --- a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/Table.kt +++ /dev/null @@ -1,57 +0,0 @@ -package space.kscience.dataforge.tables - -import kotlinx.coroutines.flow.Flow -import kotlinx.coroutines.flow.asFlow - -/** - * Finite or infinite row set. Rows are produced in a lazy suspendable [Flow]. - * Each row must contain at least all the fields mentioned in [headers]. - */ -public interface Rows { - public val headers: TableHeader - public fun rowFlow(): Flow> -} - -public interface Table : Rows { - public operator fun get(row: Int, column: String): T? - public val columns: Collection> - override val headers: TableHeader get() = columns.toList() - public val rows: List> - override fun rowFlow(): Flow> = rows.asFlow() - - /** - * Apply typed query to this table and return lazy [Flow] of resulting rows. The flow could be empty. - */ - //fun select(query: Any): Flow = error("Query of type ${query::class} is not supported by this table") - public companion object { - public inline operator fun invoke(block: MutableTable.() -> Unit): Table = - MutableTable(arrayListOf(), arrayListOf()).apply(block) - } -} - -public operator fun Collection>.get(name: String): Column? = find { it.name == name } - - -public inline operator fun Table.get(row: Int, column: ColumnHeader): R? { - require(headers.contains(column)) { "Column $column is not in table headers" } - return get(row, column.name) as? R -} - -public interface Column : ColumnHeader { - public val size: Int - public operator fun get(index: Int): T? -} - -public val Column<*>.indices: IntRange get() = (0 until size) - -public operator fun Column.iterator(): Iterator = iterator { - for (i in indices) { - yield(get(i)) - } -} - -public interface Row { - public operator fun get(column: String): T? -} - -public inline operator fun Row.get(column: ColumnHeader): R? = get(column.name) as? R \ No newline at end of file diff --git a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/TransformationColumn.kt b/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/TransformationColumn.kt deleted file mode 100644 index 5a1e83be..00000000 --- a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/TransformationColumn.kt +++ /dev/null @@ -1,65 +0,0 @@ -package space.kscience.dataforge.tables - -import space.kscience.dataforge.meta.Meta -import kotlin.reflect.KType -import kotlin.reflect.typeOf - -/** - * A virtual column obtained by transforming Given row to a single value - */ -public class TransformationColumn( - public val table: Table, - override val type: KType, - override val name: String, - override val meta: Meta, - public val mapper: (Row) -> R?, -) : Column { - override val size: Int get() = table.rows.size - - override fun get(index: Int): R? = mapper(table.rows[index]) -} - -/** - * A virtual column obtained via transformation of single column with caching results on call (evaluation is lazy). - * - * Calls are not thread safe - */ -public class CachedTransformationColumn( - public val table: Table, - override val type: KType, - override val name: String, - override val meta: Meta, - public val mapper: (Row) -> R?, -) : Column { - override val size: Int get() = table.rows.size - private val values: HashMap = HashMap() - override fun get(index: Int): R? = values.getOrPut(index) { mapper(table.rows[index]) } -} - -/** - * Create a virtual column from a given column - */ -public inline fun Table.mapRows( - name: String, - meta: Meta = Meta.EMPTY, - cache: Boolean = false, - noinline mapper: (Row) -> R?, -): Column = if (cache) { - CachedTransformationColumn(this, typeOf(), name, meta, mapper) -} else { - TransformationColumn(this, typeOf(), name, meta, mapper) -} - -public fun Table.mapRowsToDouble( - name: String, - meta: Meta = Meta.EMPTY, - block: (Row) -> Double, -): RealColumn { - val data = DoubleArray(rows.size) { block(rows[it]) } - return RealColumn(name, data, meta) -} - -public fun Table.mapRowsToInt(name: String, meta: Meta = Meta.EMPTY, block: (Row) -> Int): IntColumn { - val data = IntArray(rows.size) { block(rows[it]) } - return IntColumn(name, data, meta) -} \ No newline at end of file diff --git a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/io/TextRows.kt b/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/io/TextRows.kt deleted file mode 100644 index 90732c89..00000000 --- a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/io/TextRows.kt +++ /dev/null @@ -1,151 +0,0 @@ -package space.kscience.dataforge.tables.io - -import io.ktor.utils.io.core.Output -import io.ktor.utils.io.core.readBytes -import kotlinx.coroutines.flow.* -import space.kscience.dataforge.io.Binary -import space.kscience.dataforge.io.readSafeUtf8Line -import space.kscience.dataforge.io.writeUtf8String -import space.kscience.dataforge.tables.* -import space.kscience.dataforge.values.* - -/** - * Read a lin as a fixed width [Row] - */ -private fun readRow(header: ValueTableHeader, line: String): Row { - val values = line.trim().split("\\s+".toRegex()).map { it.lazyParseValue() } - - if (values.size == header.size) { - val map = header.map { it.name }.zip(values).toMap() - return MapRow(map) - } else { - error("Can't read line \"$line\". Expected ${header.size} values in a line, but found ${values.size}") - } -} - -/** - * Finite or infinite [Rows] created from a fixed width text binary - */ -public class TextRows(override val headers: ValueTableHeader, private val binary: Binary) : Rows { - - /** - * A flow of indexes of string start offsets ignoring empty strings - */ - public fun indexFlow(): Flow = binary.read { - //TODO replace by line reader - val text = readBytes().decodeToString() - text.lineSequence() - .map { it.trim() } - .filter { it.isNotEmpty() } - .scan(0) { acc, str -> acc + str.length }.asFlow() -// var counter: Int = 0 -// flow { -// do { -// val line = readUTF8Line() -// counter += line?.length ?: 0 -// if (!line.isNullOrBlank()) { -// emit(counter) -// } -// } while (!endOfInput) -// } - } - - override fun rowFlow(): Flow> = binary.read { - val text = readBytes().decodeToString() - text.lineSequence() - .map { it.trim() } - .filter { it.isNotEmpty() } - .map { readRow(headers, it) }.asFlow() -// flow { -// do { -// val line = readUTF8Line() -// if (!line.isNullOrBlank()) { -// val row = readRow(headers, line) -// emit(row) -// } -// } while (!endOfInput) -// } - } - - public companion object -} - -/** - * Create a row offset index for [TextRows] - */ -public suspend fun TextRows.buildRowIndex(): List = indexFlow().toList() - -/** - * Finite table created from [RandomAccessBinary] with fixed width text table - */ -public class TextTable( - override val headers: ValueTableHeader, - private val binary: Binary, - public val index: List, -) : Table { - - override val columns: Collection> get() = headers.map { RowTableColumn(this, it) } - - override val rows: List> get() = index.map { readAt(it) } - - override fun rowFlow(): Flow> = TextRows(headers, binary).rowFlow() - - private fun readAt(offset: Int): Row { - return binary.read(offset) { - val line = readSafeUtf8Line() - return@read readRow(headers, line) - } - } - - override fun get(row: Int, column: String): Value? { - val offset = index[row] - return readAt(offset)[column] - } - - public companion object { - public suspend operator fun invoke(header: ValueTableHeader, binary: Binary): TextTable { - val index = TextRows(header, binary).buildRowIndex() - return TextTable(header, binary, index) - } - } -} - - -/** - * Write a fixed width value to the output - */ -private fun Output.writeValue(value: Value, width: Int, left: Boolean = true) { - require(width > 5) { "Width could not be less than 5" } - val str: String = when (value.type) { - ValueType.NUMBER -> value.numberOrNull.toString() //TODO apply decimal format - ValueType.STRING, ValueType.LIST -> value.string.take(width) - ValueType.BOOLEAN -> if (value.boolean) { - "true" - } else { - "false" - } - ValueType.NULL -> "@null" - } - val padded = if (left) { - str.padEnd(width) - } else { - str.padStart(width) - } - writeUtf8String(padded) -} - -/** - * Write rows without header to the output - */ -public suspend fun Output.writeRows(rows: Rows) { - val widths: List = rows.headers.map { - it.textWidth - } - rows.rowFlow().collect { row -> - rows.headers.forEachIndexed { index, columnHeader -> - writeValue(row[columnHeader] ?: Null, widths[index]) - } -// appendLine() - writeUtf8String("\r\n") - } -} \ No newline at end of file diff --git a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/io/textTableEnvelope.kt b/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/io/textTableEnvelope.kt deleted file mode 100644 index d8bb8f8d..00000000 --- a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/io/textTableEnvelope.kt +++ /dev/null @@ -1,43 +0,0 @@ -package space.kscience.dataforge.tables.io - -import space.kscience.dataforge.io.Binary -import space.kscience.dataforge.io.Envelope -import space.kscience.dataforge.io.asBinary -import space.kscience.dataforge.io.buildByteArray -import space.kscience.dataforge.meta.* -import space.kscience.dataforge.misc.DFExperimental -import space.kscience.dataforge.tables.SimpleColumnHeader -import space.kscience.dataforge.tables.Table -import space.kscience.dataforge.values.Value -import kotlin.reflect.typeOf - - -public suspend fun Table.toEnvelope(): Envelope = Envelope { - meta { - headers.forEachIndexed { index, columnHeader -> - set("column", index.toString(), Meta { - "name" put columnHeader.name - if (!columnHeader.meta.isEmpty()) { - "meta" put columnHeader.meta - } - }) - } - } - - type = "table.value" - dataID = "valueTable[${this@toEnvelope.hashCode()}]" - - data = buildByteArray { - writeRows(this@toEnvelope) - }.asBinary() -} - -@DFExperimental -public fun TextRows.Companion.readEnvelope(envelope: Envelope): TextRows { - val header = envelope.meta.getIndexed("column") - .entries.sortedBy { it.key?.toInt() } - .map { (_, item) -> - SimpleColumnHeader(item.node["name"].string!!, typeOf(), item.node["meta"].node ?: Meta.EMPTY) - } - return TextRows(header, envelope.data ?: Binary.EMPTY) -} \ No newline at end of file diff --git a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/numericColumns.kt b/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/numericColumns.kt deleted file mode 100644 index c46fdcc6..00000000 --- a/dataforge-tables/src/commonMain/kotlin/space/kscience/dataforge/tables/numericColumns.kt +++ /dev/null @@ -1,84 +0,0 @@ -package space.kscience.dataforge.tables - -import space.kscience.dataforge.meta.Meta -import kotlin.reflect.KType -import kotlin.reflect.typeOf - - -public class RealColumn( - override val name: String, - public val data: DoubleArray, - override val meta: Meta = Meta.EMPTY -) : Column { - override val type: KType get() = typeOf() - - override val size: Int get() = data.size - - @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") - override inline fun get(index: Int): Double = data[index] - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is RealColumn) return false - - if (name != other.name) return false - if (!data.contentEquals(other.data)) return false - if (meta != other.meta) return false - - return true - } - - override fun hashCode(): Int { - var result = name.hashCode() - result = 31 * result + data.contentHashCode() - result = 31 * result + meta.hashCode() - return result - } - - public companion object { - public inline operator fun invoke( - name: String, - data: DoubleArray, - noinline metaBuilder: ColumnScheme.() -> Unit - ): RealColumn = RealColumn(name, data, ColumnScheme(metaBuilder).toMeta()) - } -} - -public class IntColumn( - override val name: String, - public val data: IntArray, - override val meta: Meta = Meta.EMPTY -) : Column { - override val type: KType get() = typeOf() - - override val size: Int get() = data.size - - @Suppress("OVERRIDE_BY_INLINE", "NOTHING_TO_INLINE") - override inline fun get(index: Int): Int = data[index] - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other !is IntColumn) return false - - if (name != other.name) return false - if (!data.contentEquals(other.data)) return false - if (meta != other.meta) return false - - return true - } - - override fun hashCode(): Int { - var result = name.hashCode() - result = 31 * result + data.contentHashCode() - result = 31 * result + meta.hashCode() - return result - } - - public companion object { - public inline operator fun invoke( - name: String, - data: IntArray, - noinline metaBuilder: ColumnScheme.() -> Unit - ): IntColumn = IntColumn(name, data, ColumnScheme(metaBuilder).toMeta()) - } -} \ No newline at end of file diff --git a/dataforge-tables/src/jvmMain/kotlin/space/kscience/dataforge/tables/CastColumn.kt b/dataforge-tables/src/jvmMain/kotlin/space/kscience/dataforge/tables/CastColumn.kt deleted file mode 100644 index b533b46f..00000000 --- a/dataforge-tables/src/jvmMain/kotlin/space/kscience/dataforge/tables/CastColumn.kt +++ /dev/null @@ -1,37 +0,0 @@ -package space.kscience.dataforge.tables - -import space.kscience.dataforge.meta.Meta -import kotlin.properties.ReadOnlyProperty -import kotlin.reflect.KProperty -import kotlin.reflect.KType -import kotlin.reflect.full.isSubtypeOf - -@Suppress("UNCHECKED_CAST") -public fun Column<*>.cast(type: KType): Column { - return if (type.isSubtypeOf(this.type)) { - this as Column - } else { - CastColumn(this, type) - } -} - -private class CastColumn(private val origin: Column<*>, override val type: KType) : Column { - override val name: String get() = origin.name - override val meta: Meta get() = origin.meta - override val size: Int get() = origin.size - - @Suppress("UNCHECKED_CAST") - override fun get(index: Int): T? = origin[index]?.let { - it as T - } -} - -public class ColumnProperty(public val table: Table, public val type: KType) : ReadOnlyProperty> { - override fun getValue(thisRef: Any?, property: KProperty<*>): Column { - val name = property.name - return (table.columns[name] ?: error("Column with name $name not found in the table")).cast(type) - } -} - -public operator fun Collection>.get(header: ColumnHeader): Column? = - find { it.name == header.name }?.cast(header.type) diff --git a/dataforge-tables/src/jvmTest/kotlin/space/kscience/dataforge/tables/io/TextRowsTest.kt b/dataforge-tables/src/jvmTest/kotlin/space/kscience/dataforge/tables/io/TextRowsTest.kt deleted file mode 100644 index 55b55cdf..00000000 --- a/dataforge-tables/src/jvmTest/kotlin/space/kscience/dataforge/tables/io/TextRowsTest.kt +++ /dev/null @@ -1,35 +0,0 @@ -package space.kscience.dataforge.tables.io - -import kotlinx.coroutines.flow.toList -import kotlinx.coroutines.runBlocking -import space.kscience.dataforge.io.toByteArray -import space.kscience.dataforge.misc.DFExperimental -import space.kscience.dataforge.tables.Table -import space.kscience.dataforge.tables.row -import space.kscience.dataforge.values.Value -import space.kscience.dataforge.values.int -import space.kscience.dataforge.values.string -import kotlin.test.Test -import kotlin.test.assertEquals - - -@DFExperimental -class TextRowsTest { - val table = Table { - val a by column() - val b by column() - row(a to 1, b to "b1") - row(a to 2, b to "b2") - } - - @Test - fun testTableWriteRead() = runBlocking { - val envelope = table.toEnvelope() - val string = envelope.data!!.toByteArray().decodeToString() - println(string) - val table = TextRows.readEnvelope(envelope) - val rows = table.rowFlow().toList() - assertEquals(1, rows[0]["a"]?.int) - assertEquals("b2", rows[1]["b"]?.string) - } -} \ 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 ac14c473..965f859e 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 @@ -6,7 +6,7 @@ import space.kscience.dataforge.data.DataTree import space.kscience.dataforge.data.GoalExecutionRestriction import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.descriptors.Described -import space.kscience.dataforge.meta.descriptors.ItemDescriptor +import space.kscience.dataforge.meta.descriptors.MetaDescriptor import space.kscience.dataforge.misc.DFInternal import space.kscience.dataforge.misc.Type import space.kscience.dataforge.names.Name @@ -47,11 +47,11 @@ public class TaskResultBuilder( @DFInternal public fun Task( resultType: KType, - descriptor: ItemDescriptor? = null, + descriptor: MetaDescriptor? = null, builder: suspend TaskResultBuilder.() -> Unit, ): Task = object : Task { - override val descriptor: ItemDescriptor? = descriptor + override val descriptor: MetaDescriptor? = descriptor override suspend fun execute( workspace: Workspace, @@ -69,6 +69,6 @@ public fun Task( @OptIn(DFInternal::class) @Suppress("FunctionName") public inline fun Task( - descriptor: ItemDescriptor? = null, + descriptor: MetaDescriptor? = null, noinline builder: suspend TaskResultBuilder.() -> Unit, ): Task = Task(typeOf(), descriptor, builder) \ No newline at end of file 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 16af8969..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 @@ -2,10 +2,9 @@ package space.kscience.dataforge.workspace import space.kscience.dataforge.context.ContextAware import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MetaBuilder +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: MetaBuilder.() -> Unit = {}): TaskResult<*> = +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 68598714..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 @@ -8,12 +8,12 @@ import space.kscience.dataforge.data.DataSet import space.kscience.dataforge.data.DataSetBuilder import space.kscience.dataforge.data.DataTree import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MetaBuilder -import space.kscience.dataforge.meta.descriptors.NodeDescriptor +import space.kscience.dataforge.meta.MutableMeta +import space.kscience.dataforge.meta.descriptors.MetaDescriptor +import space.kscience.dataforge.meta.descriptors.MetaDescriptorBuilder import space.kscience.dataforge.misc.DFBuilder import space.kscience.dataforge.misc.DFExperimental import space.kscience.dataforge.names.Name -import space.kscience.dataforge.names.toName import kotlin.properties.PropertyDelegateProvider import kotlin.properties.ReadOnlyProperty @@ -26,16 +26,16 @@ public interface TaskContainer { public inline fun TaskContainer.registerTask( name: String, - noinline descriptorBuilder: NodeDescriptor.() -> Unit = {}, + noinline descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {}, noinline builder: suspend TaskResultBuilder.() -> Unit, -): Unit = registerTask(name.toName(), Task(NodeDescriptor(descriptorBuilder), builder)) +): Unit = registerTask(Name.parse(name), Task(MetaDescriptor(descriptorBuilder), builder)) public inline fun TaskContainer.task( - noinline descriptorBuilder: NodeDescriptor.() -> Unit = {}, + noinline descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {}, noinline builder: suspend TaskResultBuilder.() -> Unit, ): PropertyDelegateProvider>> = PropertyDelegateProvider { _, property -> - val taskName = property.name.toName() - val task = Task(NodeDescriptor(descriptorBuilder), builder) + val taskName = Name.parse(property.name) + val task = Task(MetaDescriptor(descriptorBuilder), builder) registerTask(taskName, task) ReadOnlyProperty { _, _ -> TaskReference(taskName, task) } } @@ -87,10 +87,9 @@ public class WorkspaceBuilder(private val parentContext: Context = Global) : Tas /** * Define a new target with a builder */ -public inline fun WorkspaceBuilder.target(name: String, metaBuilder: MetaBuilder.() -> Unit): Unit = - target(name, Meta(metaBuilder)) +public inline fun WorkspaceBuilder.target(name: String, mutableMeta: MutableMeta.() -> Unit): Unit = + target(name, Meta(mutableMeta)) @DFBuilder -public fun Workspace(parentContext: Context = Global, builder: WorkspaceBuilder.() -> Unit): Workspace { - return WorkspaceBuilder(parentContext).apply(builder).build() -} \ No newline at end of file +public fun Workspace(parentContext: Context = Global, builder: WorkspaceBuilder.() -> Unit): Workspace = + WorkspaceBuilder(parentContext).apply(builder).build() \ No newline at end of file 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 210d56ef..90a69976 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 @@ -86,7 +86,7 @@ public suspend fun DataSetBuilder.file( //otherwise, read as directory plugin.run { val data = readDataDirectory(path, formatResolver) - val name = data.getMeta()[Envelope.ENVELOPE_NAME_KEY].string + val name = data.getMeta()?.get(Envelope.ENVELOPE_NAME_KEY).string ?: path.fileName.toString().replace(".df", "") emit(name, data) } 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) } } diff --git a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/SimpleWorkspaceTest.kt b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/SimpleWorkspaceTest.kt index 16ae6da6..e5657444 100644 --- a/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/SimpleWorkspaceTest.kt +++ b/dataforge-workspace/src/jvmTest/kotlin/space/kscience/dataforge/workspace/SimpleWorkspaceTest.kt @@ -28,7 +28,7 @@ public inline fun P.toFactory(): PluginFactory

= object override val type: KClass = P::class } -public fun Workspace.runBlocking(task: String, block: MetaBuilder.() -> Unit = {}): DataSet = runBlocking { +public fun Workspace.runBlocking(task: String, block: MutableMeta.() -> Unit = {}): DataSet = runBlocking { produce(task, block) } diff --git a/gradle.properties b/gradle.properties index db27b7de..2bae1b5e 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,4 @@ -org.gradle.jvmargs=-XX:MaxMetaspaceSize=512m +org.gradle.jvmargs=-XX:MaxMetaspaceSize=2G org.gradle.parallel=true kotlin.code.style=official @@ -6,4 +6,4 @@ kotlin.parallel.tasks.in.project=true kotlin.mpp.enableGranularSourceSetsMetadata=true kotlin.native.enableDependencyPropagation=false -kotlin.mpp.stability.nowarn=true \ No newline at end of file +kotlin.mpp.stability.nowarn=true diff --git a/settings.gradle.kts b/settings.gradle.kts index a5bf754f..6d8e56a0 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -5,16 +5,13 @@ pluginManagement { gradlePluginPortal() } - val toolsVersion = "0.9.5" - val kotlinVersion = "1.5.0" + val toolsVersion = "0.10.2" plugins { id("ru.mipt.npm.gradle.project") version toolsVersion id("ru.mipt.npm.gradle.mpp") version toolsVersion id("ru.mipt.npm.gradle.jvm") version toolsVersion id("ru.mipt.npm.gradle.js") version toolsVersion - kotlin("jvm") version kotlinVersion - kotlin("js") version kotlinVersion } } @@ -24,8 +21,6 @@ include( ":dataforge-io:dataforge-io-yaml", ":dataforge-context", ":dataforge-data", -// ":dataforge-output", - ":dataforge-tables", ":dataforge-workspace", ":dataforge-scripting" ) \ No newline at end of file