Fixed descriptors

This commit is contained in:
Alexander Nozik 2019-03-19 14:29:02 +03:00
parent ce0e5d4f24
commit 2283aaffad
10 changed files with 137 additions and 124 deletions

View File

@ -22,6 +22,7 @@
package hep.dataforge.descriptors
import hep.dataforge.meta.*
import hep.dataforge.names.NameToken
import hep.dataforge.names.toName
/**
@ -39,6 +40,14 @@ class NodeDescriptor(override val config: Config) : Specification {
*/
var name: String by string { error("Anonymous descriptors are not allowed") }
/**
* The default for this node. Null if there is no default.
*
* @return
*/
var default: Meta? by node()
/**
* True if multiple children with this nodes name are allowed. Anonymous
* nodes are always single
@ -52,7 +61,7 @@ class NodeDescriptor(override val config: Config) : Specification {
*
* @return
*/
var required: Boolean by boolean(false)
var required: Boolean by boolean { default == null }
/**
* The node description
@ -78,6 +87,18 @@ class NodeDescriptor(override val config: Config) : Specification {
name to ValueDescriptor.wrap(node.node ?: error("Value descriptor must be a node"))
}
fun value(name: String, descriptor: ValueDescriptor) {
val token = NameToken("value", name)
config[token] = descriptor.config
}
/**
* Add a value descriptor using block for
*/
fun value(name: String, block: ValueDescriptor.() -> Unit) {
value(name, ValueDescriptor.build { this.name = name }.apply(block))
}
/**
* The map of children node descriptors
*/
@ -87,43 +108,15 @@ class NodeDescriptor(override val config: Config) : Specification {
}
/**
* Check if this node has default
*
* @return
*/
fun hasDefault(): Boolean {
return meta.hasMeta("default")
fun node(name: String, descriptor: NodeDescriptor) {
val token = NameToken("node", name)
config[token] = descriptor.config
}
/**
* The default meta for this node (could be multiple). Null if not defined
*
* @return
*/
val default: List<Meta> by nodeList(def = emptyList())
/**
* Identify if this descriptor has child value descriptor with default
*
* @param name
* @return
*/
fun hasDefaultForValue(name: String): Boolean {
return getValueDescriptor(name)?.hasDefault() ?: false
fun node(name: String, block: NodeDescriptor.() -> Unit) {
node(name, NodeDescriptor.build { this.name = name }.apply(block))
}
/**
* The key of the value which is used to display this node in case it is
* multiple. By default, the key is empty which means that node index is
* used.
*
* @return
*/
val key: String by stringValue(def = "")
fun builder(): DescriptorBuilder = DescriptorBuilder(this.name, Configuration(this.meta))
//override val descriptor: NodeDescriptor = empty("descriptor")
@ -131,8 +124,5 @@ class NodeDescriptor(override val config: Config) : Specification {
override fun wrap(config: Config): NodeDescriptor = NodeDescriptor(config)
fun empty(nodeName: String): NodeDescriptor {
return NodeDescriptor(Meta.buildEmpty(nodeName))
}
}
}

View File

@ -17,7 +17,10 @@
package hep.dataforge.descriptors
import hep.dataforge.meta.*
import hep.dataforge.values.*
import hep.dataforge.values.False
import hep.dataforge.values.True
import hep.dataforge.values.Value
import hep.dataforge.values.ValueType
/**
* A descriptor for meta value
@ -35,6 +38,10 @@ class ValueDescriptor(override val config: Config) : Specification {
*/
var default: Value? by value()
fun default(v: Any) {
this.default = Value.of(v)
}
/**
* True if multiple values with this name are allowed.
*
@ -72,6 +79,10 @@ class ValueDescriptor(override val config: Config) : Specification {
it?.list?.map { v -> ValueType.valueOf(v.string) } ?: emptyList()
}
fun type(vararg t: ValueType) {
this.type = listOf(*t)
}
var tags: List<String> by value().map { value ->
value?.list?.map { it.string } ?: emptyList()
}
@ -103,10 +114,24 @@ class ValueDescriptor(override val config: Config) : Specification {
}
}
/**
* Allow given list of value and forbid others
*/
fun allow(vararg v: Any) {
this.allowedValues = v.map { Value.of(it) }
}
companion object : SpecificationCompanion<ValueDescriptor> {
override fun wrap(config: Config): ValueDescriptor = ValueDescriptor(config)
inline fun <reified E : Enum<E>> enum(name: String) =
ValueDescriptor.build {
this.name = name
type(ValueType.STRING)
this.allowedValues = enumValues<E>().map { Value.of(it.name) }
}
// /**
// * Build a value descriptor from annotation
// */

View File

@ -23,14 +23,14 @@ import kotlin.reflect.KClass
@MustBeDocumented
annotation class ValueDef(
val key: String,
val type: Array<ValueType> = [ValueType.STRING],
val type: Array<ValueType> = arrayOf(ValueType.STRING),
val multiple: Boolean = false,
val def: String = "",
val info: String = "",
val required: Boolean = true,
val allowed: Array<String> = [],
val allowed: Array<String> = emptyArray(),
val enumeration: KClass<*> = Any::class,
val tags: Array<String> = []
val tags: Array<String> = emptyArray()
)
@MustBeDocumented
@ -39,11 +39,11 @@ annotation class NodeDef(
val info: String = "",
val multiple: Boolean = false,
val required: Boolean = false,
val tags: Array<String> = [],
val tags: Array<String> = emptyArray(),
/**
* A list of child value descriptors
*/
val values: Array<ValueDef> = [],
val values: Array<ValueDef> = emptyArray(),
/**
* A target class for this node to describe
* @return
@ -135,11 +135,11 @@ annotation class DescriptorValue(val def: ValueDef)
@MustBeDocumented
annotation class ValueProperty(
val name: String = "",
val type: Array<ValueType> = [ValueType.STRING],
val type: Array<ValueType> = arrayOf(ValueType.STRING),
val multiple: Boolean = false,
val def: String = "",
val enumeration: KClass<*> = Any::class,
val tags: Array<String> = []
val tags: Array<String> = emptyArray()
)

View File

@ -11,45 +11,45 @@ import kotlin.jvm.JvmName
* A property delegate that uses custom key
*/
fun Configurable.value(default: Any = Null, key: String? = null) =
ValueConfigDelegate(config, key, Value.of(default))
MutableValueDelegate(config, key, Value.of(default))
fun Configurable.string(default: String? = null, key: String? = null) =
StringConfigDelegate(config, key, default)
MutableStringDelegate(config, key, default)
fun Configurable.boolean(default: Boolean? = null, key: String? = null) =
BooleanConfigDelegate(config, key, default)
MutableBooleanDelegate(config, key, default)
fun Configurable.number(default: Number? = null, key: String? = null) =
NumberConfigDelegate(config, key, default)
MutableNumberDelegate(config, key, default)
fun Configurable.child(key: String? = null) = MetaNodeDelegate(config, key)
fun Configurable.node(key: String? = null) = MutableNodeDelegate(config, key)
//fun <T : Configurable> Configurable.spec(spec: Specification<T>, key: String? = null) = ChildConfigDelegate<T>(key) { spec.wrap(this) }
@JvmName("safeString")
fun Configurable.string(default: String, key: String? = null) =
SafeStringConfigDelegate(config, key) { default }
MutableSafeStringDelegate(config, key) { default }
@JvmName("safeBoolean")
fun Configurable.boolean(default: Boolean, key: String? = null) =
SafeBooleanConfigDelegate(config, key) { default }
MutableSafeBooleanDelegate(config, key) { default }
@JvmName("safeNumber")
fun Configurable.number(default: Number, key: String? = null) =
SafeNumberConfigDelegate(config, key) { default }
MutableSafeNumberDelegate(config, key) { default }
@JvmName("safeString")
fun Configurable.string(key: String? = null, default: () -> String) =
SafeStringConfigDelegate(config, key, default)
MutableSafeStringDelegate(config, key, default)
@JvmName("safeBoolean")
fun Configurable.boolean(key: String? = null, default: () -> Boolean) =
SafeBooleanConfigDelegate(config, key, default)
MutableSafeBooleanDelegate(config, key, default)
@JvmName("safeNumber")
fun Configurable.number(key: String? = null, default: () -> Number) =
SafeNumberConfigDelegate(config, key, default)
MutableSafeNumberDelegate(config, key, default)
inline fun <reified E : Enum<E>> Configurable.enum(default: E, key: String? = null) =
SafeEnumvConfigDelegate(config, key, default) { enumValueOf(it) }
MutableSafeEnumvDelegate(config, key, default) { enumValueOf(it) }

View File

@ -164,23 +164,23 @@ inline fun <reified E : Enum<E>> Meta.enum(default: E, key: String? = null) =
SafeEnumDelegate(this, key, default) { enumValueOf(it) }
/* Config delegates */
/* Read-write delegates */
class ValueConfigDelegate<M : MutableMeta<M>>(
val config: M,
class MutableValueDelegate<M : MutableMeta<M>>(
val meta: M,
private val key: String? = null,
private val default: Value? = null
) : ReadWriteProperty<Any?, Value?> {
override fun getValue(thisRef: Any?, property: KProperty<*>): Value? {
return config[key ?: property.name]?.value ?: default
return meta[key ?: property.name]?.value ?: default
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: Value?) {
val name = key ?: property.name
if (value == null) {
config.remove(name)
meta.remove(name)
} else {
config.setValue(name, value)
meta.setValue(name, value)
}
}
@ -188,59 +188,59 @@ class ValueConfigDelegate<M : MutableMeta<M>>(
ReadWriteDelegateWrapper(this, reader, writer)
}
class StringConfigDelegate<M : MutableMeta<M>>(
val config: M,
class MutableStringDelegate<M : MutableMeta<M>>(
val meta: M,
private val key: String? = null,
private val default: String? = null
) : ReadWriteProperty<Any?, String?> {
override fun getValue(thisRef: Any?, property: KProperty<*>): String? {
return config[key ?: property.name]?.string ?: default
return meta[key ?: property.name]?.string ?: default
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: String?) {
val name = key ?: property.name
if (value == null) {
config.remove(name)
meta.remove(name)
} else {
config.setValue(name, value.asValue())
meta.setValue(name, value.asValue())
}
}
}
class BooleanConfigDelegate<M : MutableMeta<M>>(
val config: M,
class MutableBooleanDelegate<M : MutableMeta<M>>(
val meta: M,
private val key: String? = null,
private val default: Boolean? = null
) : ReadWriteProperty<Any?, Boolean?> {
override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean? {
return config[key ?: property.name]?.boolean ?: default
return meta[key ?: property.name]?.boolean ?: default
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean?) {
val name = key ?: property.name
if (value == null) {
config.remove(name)
meta.remove(name)
} else {
config.setValue(name, value.asValue())
meta.setValue(name, value.asValue())
}
}
}
class NumberConfigDelegate<M : MutableMeta<M>>(
val config: M,
class MutableNumberDelegate<M : MutableMeta<M>>(
val meta: M,
private val key: String? = null,
private val default: Number? = null
) : ReadWriteProperty<Any?, Number?> {
override fun getValue(thisRef: Any?, property: KProperty<*>): Number? {
return config[key ?: property.name]?.number ?: default
return meta[key ?: property.name]?.number ?: default
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: Number?) {
val name = key ?: property.name
if (value == null) {
config.remove(name)
meta.remove(name)
} else {
config.setValue(name, value.asValue())
meta.setValue(name, value.asValue())
}
}
@ -252,8 +252,8 @@ class NumberConfigDelegate<M : MutableMeta<M>>(
//Delegates with non-null values
class SafeStringConfigDelegate<M : MutableMeta<M>>(
val config: M,
class MutableSafeStringDelegate<M : MutableMeta<M>>(
val meta: M,
private val key: String? = null,
default: () -> String
) : ReadWriteProperty<Any?, String> {
@ -261,16 +261,16 @@ class SafeStringConfigDelegate<M : MutableMeta<M>>(
private val default: String by lazy(default)
override fun getValue(thisRef: Any?, property: KProperty<*>): String {
return config[key ?: property.name]?.string ?: default
return meta[key ?: property.name]?.string ?: default
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
config.setValue(key ?: property.name, value.asValue())
meta.setValue(key ?: property.name, value.asValue())
}
}
class SafeBooleanConfigDelegate<M : MutableMeta<M>>(
val config: M,
class MutableSafeBooleanDelegate<M : MutableMeta<M>>(
val meta: M,
private val key: String? = null,
default: () -> Boolean
) : ReadWriteProperty<Any?, Boolean> {
@ -278,16 +278,16 @@ class SafeBooleanConfigDelegate<M : MutableMeta<M>>(
private val default: Boolean by lazy(default)
override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean {
return config[key ?: property.name]?.boolean ?: default
return meta[key ?: property.name]?.boolean ?: default
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: Boolean) {
config.setValue(key ?: property.name, value.asValue())
meta.setValue(key ?: property.name, value.asValue())
}
}
class SafeNumberConfigDelegate<M : MutableMeta<M>>(
val config: M,
class MutableSafeNumberDelegate<M : MutableMeta<M>>(
val meta: M,
private val key: String? = null,
default: () -> Number
) : ReadWriteProperty<Any?, Number> {
@ -295,11 +295,11 @@ class SafeNumberConfigDelegate<M : MutableMeta<M>>(
private val default: Number by lazy(default)
override fun getValue(thisRef: Any?, property: KProperty<*>): Number {
return config[key ?: property.name]?.number ?: default
return meta[key ?: property.name]?.number ?: default
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: Number) {
config.setValue(key ?: property.name, value.asValue())
meta.setValue(key ?: property.name, value.asValue())
}
val double get() = ReadWriteDelegateWrapper(this, reader = { it.toDouble() }, writer = { it })
@ -308,48 +308,48 @@ class SafeNumberConfigDelegate<M : MutableMeta<M>>(
val long get() = ReadWriteDelegateWrapper(this, reader = { it.toLong() }, writer = { it })
}
class SafeEnumvConfigDelegate<M : MutableMeta<M>, E : Enum<E>>(
val config: M,
class MutableSafeEnumvDelegate<M : MutableMeta<M>, E : Enum<E>>(
val meta: M,
private val key: String? = null,
private val default: E,
private val resolver: (String) -> E
) : ReadWriteProperty<Any?, E> {
override fun getValue(thisRef: Any?, property: KProperty<*>): E {
return (config[key ?: property.name]?.string)?.let { resolver(it) } ?: default
return (meta[key ?: property.name]?.string)?.let { resolver(it) } ?: default
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: E) {
config.setValue(key ?: property.name, value.name.asValue())
meta.setValue(key ?: property.name, value.name.asValue())
}
}
//Child node delegate
class MetaNodeDelegate<M : MutableMetaNode<M>>(
val config: M,
class MutableNodeDelegate<M : MutableMetaNode<M>>(
val meta: M,
private val key: String? = null
) : ReadWriteProperty<Any?, Meta> {
override fun getValue(thisRef: Any?, property: KProperty<*>): Meta {
return config[key ?: property.name]?.node ?: EmptyMeta
) : ReadWriteProperty<Any?, Meta?> {
override fun getValue(thisRef: Any?, property: KProperty<*>): Meta? {
return meta[key ?: property.name]?.node
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: Meta) {
config[key ?: property.name] = value
override fun setValue(thisRef: Any?, property: KProperty<*>, value: Meta?) {
meta[key ?: property.name] = value
}
}
class ChildConfigDelegate<M : MutableMetaNode<M>, T : Configurable>(
val config: M,
class MutableMorphDelegate<M : MutableMetaNode<M>, T : Configurable>(
val meta: M,
private val key: String? = null,
private val converter: (Meta) -> T
) :
ReadWriteProperty<Any?, T> {
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
return converter(config[key ?: property.name]?.node ?: EmptyMeta)
return converter(meta[key ?: property.name]?.node ?: EmptyMeta)
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
config[key ?: property.name] = value.config
meta[key ?: property.name] = value.config
}
}
@ -374,45 +374,43 @@ class ReadWriteDelegateWrapper<T, R>(
* A property delegate that uses custom key
*/
fun <M : MutableMeta<M>> M.value(default: Value = Null, key: String? = null) =
ValueConfigDelegate(this, key, default)
MutableValueDelegate(this, key, default)
fun <M : MutableMeta<M>> M.string(default: String? = null, key: String? = null) =
StringConfigDelegate(this, key, default)
MutableStringDelegate(this, key, default)
fun <M : MutableMeta<M>> M.boolean(default: Boolean? = null, key: String? = null) =
BooleanConfigDelegate(this, key, default)
MutableBooleanDelegate(this, key, default)
fun <M : MutableMeta<M>> M.number(default: Number? = null, key: String? = null) =
NumberConfigDelegate(this, key, default)
MutableNumberDelegate(this, key, default)
fun <M : MutableMetaNode<M>> M.child(key: String? = null) = MetaNodeDelegate(this, key)
//fun <T : Configurable> Configurable.spec(spec: Specification<T>, key: String? = null) = ChildConfigDelegate<T>(key) { spec.wrap(this) }
fun <M : MutableMetaNode<M>> M.node(key: String? = null) = MutableNodeDelegate(this, key)
@JvmName("safeString")
fun <M : MutableMeta<M>> M.string(default: String, key: String? = null) =
SafeStringConfigDelegate(this, key) { default }
MutableSafeStringDelegate(this, key) { default }
@JvmName("safeBoolean")
fun <M : MutableMeta<M>> M.boolean(default: Boolean, key: String? = null) =
SafeBooleanConfigDelegate(this, key) { default }
MutableSafeBooleanDelegate(this, key) { default }
@JvmName("safeNumber")
fun <M : MutableMeta<M>> M.number(default: Number, key: String? = null) =
SafeNumberConfigDelegate(this, key) { default }
MutableSafeNumberDelegate(this, key) { default }
@JvmName("safeString")
fun <M : MutableMeta<M>> M.string(key: String? = null, default: () -> String) =
SafeStringConfigDelegate(this, key, default)
MutableSafeStringDelegate(this, key, default)
@JvmName("safeBoolean")
fun <M : MutableMeta<M>> M.boolean(key: String? = null, default: () -> Boolean) =
SafeBooleanConfigDelegate(this, key, default)
MutableSafeBooleanDelegate(this, key, default)
@JvmName("safeNumber")
fun <M : MutableMeta<M>> M.number(key: String? = null, default: () -> Number) =
SafeNumberConfigDelegate(this, key, default)
MutableSafeNumberDelegate(this, key, default)
inline fun <M : MutableMeta<M>, reified E : Enum<E>> M.enum(default: E, key: String? = null) =
SafeEnumvConfigDelegate(this, key, default) { enumValueOf(it) }
MutableSafeEnumvDelegate(this, key, default) { enumValueOf(it) }

View File

@ -33,4 +33,4 @@ fun Configurable.stringList(vararg default: String = emptyArray(), key: String?
fun <T : Metoid> Metoid.child(key: String? = null, converter: (Meta) -> T) = ChildDelegate(meta, key, converter)
fun <T : Configurable> Configurable.child(key: String? = null, converter: (Meta) -> T) =
ChildConfigDelegate(config, key, converter)
MutableMorphDelegate(config, key, converter)

View File

@ -125,6 +125,8 @@ operator fun <M : MutableMetaNode<M>> M.set(name: Name, value: Any?) {
}
}
operator fun <M : MutableMetaNode<M>> M.set(name: NameToken, value: Any?) = set(Name(key), value)
operator fun <M : MutableMetaNode<M>> M.set(key: String, value: Any?) = set(key.toName(), value)
/**

View File

@ -59,4 +59,4 @@ fun <M : MutableMetaNode<M>, C : Specification> Specification.spec(
spec: SpecificationCompanion<C>,
key: String? = null
) =
ChildConfigDelegate(config, key) { spec.wrap(config) }
MutableMorphDelegate(config, key) { spec.wrap(config) }

View File

@ -48,7 +48,7 @@ class Styled(val base: Meta, val style: Config = Config().empty()) : MutableMeta
}
}
fun Styled.configure(meta: Meta) = apply { style.update(style) }
fun Styled.configure(meta: Meta) = apply { style.update(meta) }
fun Meta.withStyle(style: Meta = EmptyMeta) = if (this is Styled) {
this.apply { this.configure(style) }

View File

@ -1,8 +1,6 @@
package hep.dataforge.meta
fun Meta.toDynamic(): dynamic {
fun MetaItem<*>.toDynamic(): dynamic = when (this) {
is MetaItem.ValueItem -> this.value.value.asDynamic()