diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9a9f0462..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,23 +11,22 @@ jobs: matrix: os: [ macOS-latest, windows-latest ] runs-on: ${{matrix.os}} - timeout-minutes: 30 + timeout-minutes: 40 steps: - name: Checkout the repo uses: actions/checkout@v2 - name: Set up JDK 11 uses: DeLaGuardo/setup-graalvm@4.0 with: - graalvm: 21.1.0 + graalvm: 21.2.0 java: java11 arch: amd64 - - name: Add msys to path - if: matrix.os == 'windows-latest' - run: SETX PATH "%PATH%;C:\msys64\mingw64\bin" - 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- @@ -36,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 5892b3c4..23ed5435 100644 --- a/.github/workflows/pages.yml +++ b/.github/workflows/pages.yml @@ -2,39 +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: DeLaGuardo/setup-graalvm@4.0 + - uses: actions/checkout@v2 + - uses: DeLaGuardo/setup-graalvm@4.0 with: - graalvm: 21.1.0 + graalvm: 21.2.0 java: java11 arch: amd64 - - name: Cache gradle - uses: actions/cache@v2 + - uses: actions/cache@v2 with: path: ~/.gradle/caches - key: ubuntu-20.04-gradle-${{ hashFiles('*.gradle.kts') }} - restore-keys: | - ubuntu-20.04-gradle- - - name: Cache konan - uses: actions/cache@v2 - with: - path: ~/.konan key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} restore-keys: | ${{ runner.os }}-gradle- - - name: Build - run: ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace - - name: Deploy to GitHub Pages - uses: JamesIves/github-pages-deploy-action@4.1.0 + - 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 c5c110e8..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: @@ -20,16 +19,15 @@ jobs: - name: Set up JDK 11 uses: DeLaGuardo/setup-graalvm@4.0 with: - graalvm: 21.1.0 + graalvm: 21.2.0 java: java11 arch: amd64 - - name: Add msys to path - if: matrix.os == 'windows-latest' - run: SETX PATH "%PATH%;C:\msys64\mingw64\bin" - 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- @@ -42,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 a4bb6751..1af0a884 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,10 +14,8 @@ - **API breaking** `String.toName()` is replaced by `Name.parse()` - **API breaking** Configurable`config` changed to `meta` -### Deprecated -- Direct use of `Config` - ### Removed +- `Config` - Public PluginManager mutability - Tables and tables-exposed moved to the separate project `tables.kt` - BinaryMetaFormat. Use CBOR encoding instead diff --git a/build.gradle.kts b/build.gradle.kts index 65ad141f..c86da3cc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ plugins { allprojects { group = "space.kscience" - version = "0.5.0-dev-7" + version = "0.5.0-dev-9" } subprojects { 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 7913e80f..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 @@ -91,9 +91,9 @@ public fun JsonPrimitive.toValue(descriptor: MetaDescriptor?): Value { } /** - * Turn this [JsonArray] into a [ListValue] with recursion or return null if it contains objects + * Turn this [JsonElement] into a [ListValue] with recursion or return null if it contains objects */ -public fun JsonElement.toValueOrNull(descriptor: MetaDescriptor?): Value? = when (this) { +private fun JsonElement.toValueOrNull(descriptor: MetaDescriptor?): Value? = when (this) { is JsonPrimitive -> toValue(descriptor) is JsonObject -> get(Meta.VALUE_KEY)?.toValueOrNull(descriptor) is JsonArray -> { 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 597d331f..8cda90e9 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 @@ -3,6 +3,7 @@ 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. @@ -32,6 +33,15 @@ public fun Meta.seal(): SealedMeta = this as? SealedMeta ?: SealedMeta( @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() 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 afd2b668..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 @@ -41,7 +41,7 @@ public interface Specification : ReadOnlySpecification { /** * Update a [MutableMeta] using given specification */ -public fun MutableMeta.update( +public fun MutableMeta.updateWith( spec: Specification, action: T.() -> Unit ): T = spec.write(this).apply(action) @@ -50,7 +50,7 @@ public fun MutableMeta.update( /** * Update configuration using given specification */ -public fun Configurable.update( +public fun Configurable.updateWith( spec: Specification, action: T.() -> Unit, ): T = spec.write(meta).apply(action) 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 03b4fdde..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/ItemDescriptor.kt +++ /dev/null @@ -1,127 +0,0 @@ -//package space.kscience.dataforge.meta.descriptors -// -//import space.kscience.dataforge.meta.* -//import space.kscience.dataforge.misc.DFBuilder -//import space.kscience.dataforge.names.* -//import space.kscience.dataforge.values.Value -// -///** -// * 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 -// -// /** -// * Compute and cache the default [Meta] value described by this descriptor -// */ -// public val defaultValue: Meta? -// -// public companion object { -// public const val DEFAULT_INDEX_KEY: String = "@index" -// } -//} -// -// -///** -// * The builder for [ItemDescriptor] -// */ -//@DFBuilder -//public sealed class ItemDescriptorBuilder(final override val config: MutableMeta) : 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: MutableMeta? 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: MutableMeta.() -> Unit) { -// (attributes ?: MutableMeta().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 index 2a519173..495b2cca 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptor.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptor.kt @@ -8,13 +8,34 @@ import space.kscience.dataforge.names.* import space.kscience.dataforge.values.Value import space.kscience.dataforge.values.ValueType +/** + * The restriction on Meta node content + */ +public enum class MetaNodeRequirements { + /** + * no restrictions + */ + NONE, + + /** + * The node itself must exist + */ + EXIST, + + /** + * Value must be present + */ + HAS_VALUE +} + /** * 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 True if the item is required - * @param type list of allowed types for [Meta.value], null if all values are allowed. If the type is [ValueType.NULL], no value is allowed for this node. + * @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 @@ -24,8 +45,8 @@ public data class MetaDescriptor( public val info: String? = null, public val children: Map = emptyMap(), public val multiple: Boolean = false, - public val required: Boolean = false, - public val type: List? = null, + public val required: MetaNodeRequirements = MetaNodeRequirements.NONE, + public val valueTypes: List? = null, public val indexKey: String = Meta.INDEX_KEY, public val defaultValue: Value? = null, public val attributes: Meta = Meta.EMPTY, @@ -58,9 +79,22 @@ public val MetaDescriptor.defaultNode: Meta } } +public fun MetaDescriptor.validate(value: Value?): Boolean = if (value == null) { + required != MetaNodeRequirements.HAS_VALUE +} 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 = (item != null || !required) && - allowedValues?.let { item?.value in it } ?: true && - children.all { (key, childDescriptor) -> childDescriptor.validate(item?.get(key)) } \ No newline at end of file +public fun MetaDescriptor.validate(item: Meta?): Boolean { + if (item == null) return required == MetaNodeRequirements.NONE + 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 index 38c256e0..7418c58c 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/MetaDescriptorBuilder.kt @@ -1,9 +1,6 @@ package space.kscience.dataforge.meta.descriptors -import space.kscience.dataforge.meta.Meta -import space.kscience.dataforge.meta.MutableMeta -import space.kscience.dataforge.meta.get -import space.kscience.dataforge.meta.set +import space.kscience.dataforge.meta.* import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.cutFirst import space.kscience.dataforge.names.first @@ -11,21 +8,13 @@ import space.kscience.dataforge.names.length import space.kscience.dataforge.values.Value import space.kscience.dataforge.values.ValueType import space.kscience.dataforge.values.asValue -import kotlin.collections.List -import kotlin.collections.MutableMap -import kotlin.collections.emptyList -import kotlin.collections.getOrPut -import kotlin.collections.hashMapOf -import kotlin.collections.listOf -import kotlin.collections.map -import kotlin.collections.mapValues import kotlin.collections.set -public class MetaDescriptorBuilder { +public class MetaDescriptorBuilder internal constructor() { public var info: String? = null public var children: MutableMap = hashMapOf() public var multiple: Boolean = false - public var required: Boolean = false + public var required: MetaNodeRequirements = MetaNodeRequirements.NONE public var type: List? = null @@ -42,6 +31,22 @@ public class MetaDescriptorBuilder { public var attributes: MutableMeta = MutableMeta() + public inline fun attributes(block: MutableMeta.() -> Unit) { + attributes.apply(block) + } + + public fun item(name: Name, descriptor: MetaDescriptor) { + when (name.length) { + 0 -> {} + 1 -> { + children[name.first().body] = descriptor.toBuilder() + } + else -> { + children.getOrPut(name.first().body) { MetaDescriptorBuilder() }.item(name.cutFirst(), descriptor) + } + } + } + public fun item(name: Name, block: MetaDescriptorBuilder.() -> Unit) { when (name.length) { 0 -> apply(block) @@ -71,7 +76,7 @@ public class MetaDescriptorBuilder { children = children.mapValues { it.value.build() }, multiple = multiple, required = required, - type = type, + valueTypes = type, indexKey = indexKey, defaultValue = default, attributes = attributes @@ -127,10 +132,27 @@ public inline fun > MetaDescriptorBuilder.enum( key: Name, default: E?, crossinline modifier: MetaDescriptorBuilder.() -> Unit = {}, -): Unit = value(key,ValueType.STRING) { +): Unit = value(key, ValueType.STRING) { default?.let { this.default = default.asValue() } allowedValues = enumValues().map { it.asValue() } modifier() -} \ No newline at end of file +} + +private fun MetaDescriptor.toBuilder(): MetaDescriptorBuilder = MetaDescriptorBuilder().apply { + info = this@toBuilder.info + children = this@toBuilder.children.mapValuesTo(LinkedHashMap()) { it.value.toBuilder() } + multiple = this@toBuilder.multiple + required = this@toBuilder.required + 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 88a9cc9e..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/NodeDescriptor.kt +++ /dev/null @@ -1,222 +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 [Meta] that is constructed from [NodeDescriptor] -// */ -//private class DescriptorMeta(val descriptor: NodeDescriptor) : AbstractMeta() { -// override val items: Map -// get() = buildMap { -// descriptor.items.forEach { (token, descriptorItem) -> -// val item = descriptorItem.defaultValue -// if (item != null) { -// put(NameToken(token), item) -// } -// } -// } -//} -// -// -///** -// * 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: Meta? -// -// /** -// * 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 -// -// /** -// * Generate a laminate representing default item set generated by this descriptor -// */ -// public val defaultMeta: Laminate -// -// 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: MutableMeta = MutableMeta()) : 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: MutableMeta? 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 MutableMeta) -// } else { -// name to ValueDescriptorBuilder(node as MutableMeta) -// } -// } -// -// /** -// * 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 MutableMeta) -// } -// -// /** -// * 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 MutableMeta) -// } -// -// private fun buildNode(name: Name): NodeDescriptorBuilder { -// return when (name.length) { -// 0 -> this -// 1 -> { -// val token = NameToken(ITEM_KEY.toString(), name.toString()) -// val config: MutableMeta = config[token].node ?: MutableMeta().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) -// } -// -// /** -// * Generate a laminate representing default item set generated by this descriptor -// */ -// override val defaultMeta: Laminate by lazy { Laminate(default, DescriptorMeta(this)) } -// -// /** -// * Build a default [MetaItemNode] from this node descriptor -// */ -// override val defaultValue: MetaItem get() = MetaItemNode(defaultMeta) -// -// 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 abcd5ebd..00000000 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/descriptors/ValueDescriptor.kt +++ /dev/null @@ -1,139 +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: MutableMeta = MutableMeta() -//) : 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 val defaultValue: MetaItem? get() = default?.asMetaItem() -// -// override fun build(): ValueDescriptor = ValueDescriptorBuilder(config.copy()) -//} 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 ca0a7ce6..4ff779a0 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 @@ -48,6 +48,11 @@ public class Name(public val tokens: List) { 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. 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 a8033cd3..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 @@ -62,7 +62,7 @@ class SpecificationTest { fun testChildUpdate() { val config = MutableMeta() val child = config.getOrCreate("child") - child.update(TestScheme) { + child.updateWith(TestScheme) { a = 22 b = "test" }