tweak MetaDescriptor.kt

This commit is contained in:
Alexander Nozik 2021-08-07 10:31:32 +03:00
parent e432b07201
commit 5632487dca
4 changed files with 37 additions and 36 deletions

View File

@ -149,7 +149,6 @@ public operator fun MutableMeta.set(name: Name, value: Value?): Unit = setValue(
public fun MutableMeta.getOrCreate(key: String): MutableMeta = getOrCreate(Name.parse(key)) public fun MutableMeta.getOrCreate(key: String): MutableMeta = getOrCreate(Name.parse(key))
@Serializable(MutableMetaSerializer::class)
public interface MutableTypedMeta<M : MutableTypedMeta<M>> : TypedMeta<M>, MutableMeta { public interface MutableTypedMeta<M : MutableTypedMeta<M>> : TypedMeta<M>, MutableMeta {
/** /**
* Zero-copy attach or replace existing node. Node is used with any additional state, listeners, etc. * Zero-copy attach or replace existing node. Node is used with any additional state, listeners, etc.

View File

@ -71,7 +71,7 @@ private class ObservableMetaWrapper(
origin.setMeta(name, node) origin.setMeta(name, node)
// //
// if meta is observable propagate changes from it // if meta is observable propagate changes from it
if(node is ObservableMeta){ if (node is ObservableMeta) {
node.onChange(this) { changeName -> node.onChange(this) { changeName ->
setMeta(name + changeName, node[changeName]) setMeta(name + changeName, node[changeName])

View File

@ -9,23 +9,23 @@ import space.kscience.dataforge.values.Value
import space.kscience.dataforge.values.ValueType import space.kscience.dataforge.values.ValueType
/** /**
* The restriction on Meta node content * Restrictions on value in the node
*/ */
public enum class MetaNodeRequirements { public enum class ValueRequirement {
/** /**
* no restrictions * No restrictions
*/ */
NONE, NONE,
/** /**
* The node itself must exist * The value is required
*/ */
EXIST, REQUIRED,
/** /**
* Value must be present * The value must be null
*/ */
HAS_VALUE ABSENT
} }
/** /**
@ -45,7 +45,7 @@ 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: MetaNodeRequirements = MetaNodeRequirements.NONE, public val valueRequirement: ValueRequirement = ValueRequirement.NONE,
public val valueTypes: 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,
@ -56,6 +56,8 @@ public data class MetaDescriptor(
} }
} }
public val MetaDescriptor.required: Boolean get() = valueRequirement == ValueRequirement.REQUIRED || children.values.any { required }
public val MetaDescriptor.allowedValues: List<Value>? get() = attributes[MetaDescriptor.ALLOWED_VALUES_KEY]?.value?.list public val MetaDescriptor.allowedValues: List<Value>? get() = attributes[MetaDescriptor.ALLOWED_VALUES_KEY]?.value?.list
public operator fun MetaDescriptor.get(name: Name): MetaDescriptor? = when (name.length) { public operator fun MetaDescriptor.get(name: Name): MetaDescriptor? = when (name.length) {
@ -80,16 +82,19 @@ public val MetaDescriptor.defaultNode: Meta
} }
public fun MetaDescriptor.validate(value: Value?): Boolean = if (value == null) { public fun MetaDescriptor.validate(value: Value?): Boolean = if (value == null) {
required != MetaNodeRequirements.HAS_VALUE valueRequirement != ValueRequirement.REQUIRED
} else { } else {
(valueTypes == null || value.type in valueTypes) && (allowedValues?.let { value in it } ?: true) 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 * Check if given item suits the descriptor
*/ */
public fun MetaDescriptor.validate(item: Meta?): Boolean { public fun MetaDescriptor.validate(item: Meta?): Boolean {
if (item == null) return required == MetaNodeRequirements.NONE if (item == null) return !required
if (!validate(item.value)) return false if (!validate(item.value)) return false
children.forEach { (key, childDescriptor) -> children.forEach { (key, childDescriptor) ->

View File

@ -14,7 +14,7 @@ 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: MetaNodeRequirements = MetaNodeRequirements.NONE public var valueRequirement: ValueRequirement = ValueRequirement.NONE
public var type: List<ValueType>? = null public var type: List<ValueType>? = null
@ -35,15 +35,14 @@ public class MetaDescriptorBuilder internal constructor() {
attributes.apply(block) attributes.apply(block)
} }
public fun item(name: Name, descriptor: MetaDescriptor) { public fun item(name: Name, descriptor: MetaDescriptor, block: MetaDescriptorBuilder.() -> Unit) {
when (name.length) { when (name.length) {
0 -> {} 0 -> {
1 -> {
children[name.first().body] = descriptor.toBuilder()
}
else -> {
children.getOrPut(name.first().body) { MetaDescriptorBuilder() }.item(name.cutFirst(), descriptor)
} }
1 -> children[name.first().body] = descriptor.toBuilder().apply(block)
else -> children.getOrPut(name.first().body) {
MetaDescriptorBuilder()
}.item(name.cutFirst(), descriptor, block)
} }
} }
@ -75,7 +74,7 @@ public class MetaDescriptorBuilder internal constructor() {
info = info, info = info,
children = children.mapValues { it.value.build() }, children = children.mapValues { it.value.build() },
multiple = multiple, multiple = multiple,
required = required, valueRequirement = valueRequirement,
valueTypes = type, valueTypes = type,
indexKey = indexKey, indexKey = indexKey,
defaultValue = default, defaultValue = default,
@ -98,11 +97,9 @@ public fun MetaDescriptorBuilder.value(
type: ValueType, type: ValueType,
vararg additionalTypes: ValueType, vararg additionalTypes: ValueType,
block: MetaDescriptorBuilder.() -> Unit block: MetaDescriptorBuilder.() -> Unit
) { ): Unit = item(name) {
item(name) { type(type, *additionalTypes)
type(type, *additionalTypes) block()
block()
}
} }
public fun MetaDescriptorBuilder.value( public fun MetaDescriptorBuilder.value(
@ -110,24 +107,24 @@ public fun MetaDescriptorBuilder.value(
type: ValueType, type: ValueType,
vararg additionalTypes: ValueType, vararg additionalTypes: ValueType,
block: MetaDescriptorBuilder.() -> Unit block: MetaDescriptorBuilder.() -> Unit
) { ): Unit = value(Name.parse(name), type, additionalTypes = additionalTypes, block)
value(Name.parse(name), type, additionalTypes = additionalTypes, block)
}
/** /**
* Create and configure child value descriptor * Create and configure child value descriptor
*/ */
public fun MetaDescriptorBuilder.node(name: Name, block: MetaDescriptorBuilder.() -> Unit) { public fun MetaDescriptorBuilder.node(name: Name, block: MetaDescriptorBuilder.() -> Unit): Unit = item(name) {
item(name) { valueRequirement = ValueRequirement.ABSENT
type(ValueType.NULL) block()
block()
}
} }
public fun MetaDescriptorBuilder.node(name: String, block: MetaDescriptorBuilder.() -> Unit) { public fun MetaDescriptorBuilder.node(name: String, block: MetaDescriptorBuilder.() -> Unit) {
node(Name.parse(name), block) node(Name.parse(name), block)
} }
public fun MetaDescriptorBuilder.required() {
valueRequirement = ValueRequirement.REQUIRED
}
public inline fun <reified E : Enum<E>> MetaDescriptorBuilder.enum( public inline fun <reified E : Enum<E>> MetaDescriptorBuilder.enum(
key: Name, key: Name,
default: E?, default: E?,
@ -144,7 +141,7 @@ private fun MetaDescriptor.toBuilder(): MetaDescriptorBuilder = MetaDescriptorBu
info = this@toBuilder.info info = this@toBuilder.info
children = this@toBuilder.children.mapValuesTo(LinkedHashMap()) { it.value.toBuilder() } children = this@toBuilder.children.mapValuesTo(LinkedHashMap()) { it.value.toBuilder() }
multiple = this@toBuilder.multiple multiple = this@toBuilder.multiple
required = this@toBuilder.required valueRequirement = this@toBuilder.valueRequirement
type = this@toBuilder.valueTypes type = this@toBuilder.valueTypes
indexKey = this@toBuilder.indexKey indexKey = this@toBuilder.indexKey
default = defaultValue default = defaultValue