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))
@Serializable(MutableMetaSerializer::class)
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.

View File

@ -9,23 +9,23 @@ import space.kscience.dataforge.values.Value
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,
/**
* 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 children: Map<String, MetaDescriptor> = emptyMap(),
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 indexKey: String = Meta.INDEX_KEY,
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 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) {
required != MetaNodeRequirements.HAS_VALUE
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 == MetaNodeRequirements.NONE
if (item == null) return !required
if (!validate(item.value)) return false
children.forEach { (key, childDescriptor) ->

View File

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