Descriptor updates and utilities

This commit is contained in:
Alexander Nozik 2021-08-06 12:29:48 +03:00
parent 28a6914747
commit e432b07201
15 changed files with 132 additions and 569 deletions

View File

@ -1,6 +1,9 @@
name: Gradle build name: Gradle build
on: [ push ] on:
push:
branches: [ dev, master ]
pull_request:
jobs: jobs:
build: build:
@ -8,23 +11,22 @@ jobs:
matrix: matrix:
os: [ macOS-latest, windows-latest ] os: [ macOS-latest, windows-latest ]
runs-on: ${{matrix.os}} runs-on: ${{matrix.os}}
timeout-minutes: 30 timeout-minutes: 40
steps: steps:
- name: Checkout the repo - name: Checkout the repo
uses: actions/checkout@v2 uses: actions/checkout@v2
- name: Set up JDK 11 - name: Set up JDK 11
uses: DeLaGuardo/setup-graalvm@4.0 uses: DeLaGuardo/setup-graalvm@4.0
with: with:
graalvm: 21.1.0 graalvm: 21.2.0
java: java11 java: java11
arch: amd64 arch: amd64
- name: Add msys to path
if: matrix.os == 'windows-latest'
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
- name: Cache gradle - name: Cache gradle
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: ~/.gradle/caches path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: | restore-keys: |
${{ runner.os }}-gradle- ${{ runner.os }}-gradle-
@ -36,4 +38,4 @@ jobs:
restore-keys: | restore-keys: |
${{ runner.os }}-gradle- ${{ runner.os }}-gradle-
- name: Build - name: Build
run: ./gradlew build --no-daemon --stacktrace run: ./gradlew build --build-cache --no-daemon --stacktrace

View File

@ -2,39 +2,27 @@ name: Dokka publication
on: on:
push: push:
branches: branches: [ master ]
- master
jobs: jobs:
build: build:
runs-on: ubuntu-20.04 runs-on: ubuntu-20.04
timeout-minutes: 40
steps: steps:
- name: Checkout the repo - uses: actions/checkout@v2
uses: actions/checkout@v2 - uses: DeLaGuardo/setup-graalvm@4.0
- name: Set up JDK 11
uses: DeLaGuardo/setup-graalvm@4.0
with: with:
graalvm: 21.1.0 graalvm: 21.2.0
java: java11 java: java11
arch: amd64 arch: amd64
- name: Cache gradle - uses: actions/cache@v2
uses: actions/cache@v2
with: with:
path: ~/.gradle/caches 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') }} key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: | restore-keys: |
${{ runner.os }}-gradle- ${{ runner.os }}-gradle-
- name: Build - run: ./gradlew dokkaHtmlMultiModule --build-cache --no-daemon --no-parallel --stacktrace
run: ./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace - uses: JamesIves/github-pages-deploy-action@4.1.0
- name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@4.1.0
with: with:
branch: gh-pages branch: gh-pages
folder: build/dokka/htmlMultiModule folder: build/dokka/htmlMultiModule

View File

@ -3,8 +3,7 @@ name: Gradle publish
on: on:
workflow_dispatch: workflow_dispatch:
release: release:
types: types: [ created ]
- created
jobs: jobs:
publish: publish:
@ -20,16 +19,15 @@ jobs:
- name: Set up JDK 11 - name: Set up JDK 11
uses: DeLaGuardo/setup-graalvm@4.0 uses: DeLaGuardo/setup-graalvm@4.0
with: with:
graalvm: 21.1.0 graalvm: 21.2.0
java: java11 java: java11
arch: amd64 arch: amd64
- name: Add msys to path
if: matrix.os == 'windows-latest'
run: SETX PATH "%PATH%;C:\msys64\mingw64\bin"
- name: Cache gradle - name: Cache gradle
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: ~/.gradle/caches path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }} key: ${{ runner.os }}-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: | restore-keys: |
${{ runner.os }}-gradle- ${{ runner.os }}-gradle-
@ -42,20 +40,14 @@ jobs:
${{ runner.os }}-gradle- ${{ runner.os }}-gradle-
- name: Publish Windows Artifacts - name: Publish Windows Artifacts
if: matrix.os == 'windows-latest' if: matrix.os == 'windows-latest'
shell: cmd
run: > run: >
./gradlew release --no-daemon ./gradlew release --no-daemon --build-cache -Ppublishing.enabled=true
-Ppublishing.enabled=true -Ppublishing.space.user=${{ secrets.SPACE_APP_ID }}
-Ppublishing.github.user=${{ secrets.PUBLISHING_GITHUB_USER }} -Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }}
-Ppublishing.github.token=${{ secrets.PUBLISHING_GITHUB_TOKEN }}
-Ppublishing.space.user=${{ secrets.PUBLISHING_SPACE_USER }}
-Ppublishing.space.token=${{ secrets.PUBLISHING_SPACE_TOKEN }}
- name: Publish Mac Artifacts - name: Publish Mac Artifacts
if: matrix.os == 'macOS-latest' if: matrix.os == 'macOS-latest'
run: > run: >
./gradlew release --no-daemon ./gradlew release --no-daemon --build-cache -Ppublishing.enabled=true -Ppublishing.platform=macosX64
-Ppublishing.enabled=true -Ppublishing.space.user=${{ secrets.SPACE_APP_ID }}
-Ppublishing.platform=macosX64 -Ppublishing.space.token=${{ secrets.SPACE_APP_SECRET }}
-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 }}

View File

@ -14,10 +14,8 @@
- **API breaking** `String.toName()` is replaced by `Name.parse()` - **API breaking** `String.toName()` is replaced by `Name.parse()`
- **API breaking** Configurable`config` changed to `meta` - **API breaking** Configurable`config` changed to `meta`
### Deprecated
- Direct use of `Config`
### Removed ### Removed
- `Config`
- Public PluginManager mutability - Public PluginManager mutability
- Tables and tables-exposed moved to the separate project `tables.kt` - Tables and tables-exposed moved to the separate project `tables.kt`
- BinaryMetaFormat. Use CBOR encoding instead - BinaryMetaFormat. Use CBOR encoding instead

View File

@ -4,7 +4,7 @@ plugins {
allprojects { allprojects {
group = "space.kscience" group = "space.kscience"
version = "0.5.0-dev-7" version = "0.5.0-dev-9"
} }
subprojects { subprojects {

View File

@ -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 JsonPrimitive -> toValue(descriptor)
is JsonObject -> get(Meta.VALUE_KEY)?.toValueOrNull(descriptor) is JsonObject -> get(Meta.VALUE_KEY)?.toValueOrNull(descriptor)
is JsonArray -> { is JsonArray -> {

View File

@ -3,6 +3,7 @@ package space.kscience.dataforge.meta
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import space.kscience.dataforge.names.NameToken import space.kscience.dataforge.names.NameToken
import space.kscience.dataforge.values.Value import space.kscience.dataforge.values.Value
import space.kscience.dataforge.values.asValue
/** /**
* The meta implementation which is guaranteed to be immutable. * The meta implementation which is guaranteed to be immutable.
@ -32,6 +33,15 @@ public fun Meta.seal(): SealedMeta = this as? SealedMeta ?: SealedMeta(
@Suppress("FunctionName") @Suppress("FunctionName")
public fun Meta(value: Value): SealedMeta = SealedMeta(value, emptyMap()) 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") @Suppress("FunctionName")
public inline fun Meta(builder: MutableMeta.() -> Unit): SealedMeta = public inline fun Meta(builder: MutableMeta.() -> Unit): SealedMeta =
MutableMeta(builder).seal() MutableMeta(builder).seal()

View File

@ -41,7 +41,7 @@ public interface Specification<out T : Any> : ReadOnlySpecification<T> {
/** /**
* Update a [MutableMeta] using given specification * Update a [MutableMeta] using given specification
*/ */
public fun <T : Any> MutableMeta.update( public fun <T : Any> MutableMeta.updateWith(
spec: Specification<T>, spec: Specification<T>,
action: T.() -> Unit action: T.() -> Unit
): T = spec.write(this).apply(action) ): T = spec.write(this).apply(action)
@ -50,7 +50,7 @@ public fun <T : Any> MutableMeta.update(
/** /**
* Update configuration using given specification * Update configuration using given specification
*/ */
public fun <T : Any> Configurable.update( public fun <T : Any> Configurable.updateWith(
spec: Specification<T>, spec: Specification<T>,
action: T.() -> Unit, action: T.() -> Unit,
): T = spec.write(meta).apply(action) ): T = spec.write(meta).apply(action)

View File

@ -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())
//

View File

@ -8,13 +8,34 @@ import space.kscience.dataforge.names.*
import space.kscience.dataforge.values.Value import space.kscience.dataforge.values.Value
import space.kscience.dataforge.values.ValueType 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 * The descriptor for a meta
* @param info description text * @param info description text
* @param children child descriptors for this node * @param children child descriptors for this node
* @param multiple True if same name siblings with this name are allowed * @param multiple True if same name siblings with this name are allowed
* @param required True if the item is required * @param required The requirements for node content
* @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 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 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 defaultValue the default [Meta.value] for the node
* @param attributes additional attributes of this descriptor. For example validation and widget parameters * @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 info: String? = null,
public val children: Map<String, MetaDescriptor> = emptyMap(), public val children: Map<String, MetaDescriptor> = emptyMap(),
public val multiple: Boolean = false, public val multiple: Boolean = false,
public val required: Boolean = false, public val required: MetaNodeRequirements = MetaNodeRequirements.NONE,
public val type: List<ValueType>? = null, public val valueTypes: List<ValueType>? = null,
public val indexKey: String = Meta.INDEX_KEY, public val indexKey: String = Meta.INDEX_KEY,
public val defaultValue: Value? = null, public val defaultValue: Value? = null,
public val attributes: Meta = Meta.EMPTY, 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 * Check if given item suits the descriptor
*/ */
public fun MetaDescriptor.validate(item: Meta?): Boolean = (item != null || !required) && public fun MetaDescriptor.validate(item: Meta?): Boolean {
allowedValues?.let { item?.value in it } ?: true && if (item == null) return required == MetaNodeRequirements.NONE
children.all { (key, childDescriptor) -> childDescriptor.validate(item?.get(key)) } if (!validate(item.value)) return false
children.forEach { (key, childDescriptor) ->
if (!childDescriptor.validate(item[key])) return false
}
return true
}

View File

@ -1,9 +1,6 @@
package space.kscience.dataforge.meta.descriptors package space.kscience.dataforge.meta.descriptors
import space.kscience.dataforge.meta.Meta import space.kscience.dataforge.meta.*
import space.kscience.dataforge.meta.MutableMeta
import space.kscience.dataforge.meta.get
import space.kscience.dataforge.meta.set
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.cutFirst import space.kscience.dataforge.names.cutFirst
import space.kscience.dataforge.names.first 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.Value
import space.kscience.dataforge.values.ValueType import space.kscience.dataforge.values.ValueType
import space.kscience.dataforge.values.asValue 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 import kotlin.collections.set
public class MetaDescriptorBuilder { public class MetaDescriptorBuilder internal constructor() {
public var info: String? = null public var info: String? = null
public var children: MutableMap<String, MetaDescriptorBuilder> = hashMapOf() public var children: MutableMap<String, MetaDescriptorBuilder> = hashMapOf()
public var multiple: Boolean = false public var multiple: Boolean = false
public var required: Boolean = false public var required: MetaNodeRequirements = MetaNodeRequirements.NONE
public var type: List<ValueType>? = null public var type: List<ValueType>? = null
@ -42,6 +31,22 @@ public class MetaDescriptorBuilder {
public var attributes: MutableMeta = MutableMeta() 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) { public fun item(name: Name, block: MetaDescriptorBuilder.() -> Unit) {
when (name.length) { when (name.length) {
0 -> apply(block) 0 -> apply(block)
@ -71,7 +76,7 @@ public class MetaDescriptorBuilder {
children = children.mapValues { it.value.build() }, children = children.mapValues { it.value.build() },
multiple = multiple, multiple = multiple,
required = required, required = required,
type = type, valueTypes = type,
indexKey = indexKey, indexKey = indexKey,
defaultValue = default, defaultValue = default,
attributes = attributes attributes = attributes
@ -127,10 +132,27 @@ public inline fun <reified E : Enum<E>> MetaDescriptorBuilder.enum(
key: Name, key: Name,
default: E?, default: E?,
crossinline modifier: MetaDescriptorBuilder.() -> Unit = {}, crossinline modifier: MetaDescriptorBuilder.() -> Unit = {},
): Unit = value(key,ValueType.STRING) { ): Unit = value(key, ValueType.STRING) {
default?.let { default?.let {
this.default = default.asValue() this.default = default.asValue()
} }
allowedValues = enumValues<E>().map { it.asValue() } allowedValues = enumValues<E>().map { it.asValue() }
modifier() 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
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()

View File

@ -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<NameToken, MetaItem>
// 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<String, ItemDescriptor>
//
// /**
// * The map of children node descriptors
// */
// public val nodes: Map<String, NodeDescriptor>
//
// /**
// * The list of children value descriptors
// */
// public val values: Map<String, ValueDescriptor>
//
// /**
// * 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<String, ItemDescriptor>
// 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<String, NodeDescriptor>
// 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<String, ValueDescriptor>
// 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())
// }
//}

View File

@ -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<ValueType>?
//
// /**
// * 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<Value>
//}
//
///**
// * 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<ValueType>? 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<Value> 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())
//}

View File

@ -48,6 +48,11 @@ public class Name(public val tokens: List<NameToken>) {
public val EMPTY: Name = Name(emptyList()) 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. * 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. * This operation is rather heavy so it should be used with care in high performance code.

View File

@ -62,7 +62,7 @@ class SpecificationTest {
fun testChildUpdate() { fun testChildUpdate() {
val config = MutableMeta() val config = MutableMeta()
val child = config.getOrCreate("child") val child = config.getOrCreate("child")
child.update(TestScheme) { child.updateWith(TestScheme) {
a = 22 a = 22
b = "test" b = "test"
} }