Descriptors
This commit is contained in:
parent
47e39ae0ac
commit
9fd89a5b60
@ -22,7 +22,6 @@
|
|||||||
package hep.dataforge.descriptors
|
package hep.dataforge.descriptors
|
||||||
|
|
||||||
import hep.dataforge.Named
|
import hep.dataforge.Named
|
||||||
import hep.dataforge.description.ValueDescriptor
|
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.*
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
@ -14,19 +14,10 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
package hep.dataforge.descriptors
|
||||||
* To change this license header, choose License Headers in Project Properties.
|
|
||||||
* To change this template file, choose Tools | Templates
|
|
||||||
* and open the template in the editor.
|
|
||||||
*/
|
|
||||||
package hep.dataforge.description
|
|
||||||
|
|
||||||
import hep.dataforge.Named
|
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.*
|
||||||
import hep.dataforge.names.AnonymousNotAlowed
|
import hep.dataforge.values.*
|
||||||
import hep.dataforge.values.BooleanValue
|
|
||||||
import hep.dataforge.values.Value
|
|
||||||
import hep.dataforge.values.ValueType
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A descriptor for meta value
|
* A descriptor for meta value
|
||||||
@ -35,54 +26,54 @@ import hep.dataforge.values.ValueType
|
|||||||
*
|
*
|
||||||
* @author Alexander Nozik
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
class ValueDescriptor(val meta: Meta) : MetaRepr {
|
class ValueDescriptor(override val config: Config) : Specification {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default for this value. Null if there is no default.
|
* The default for this value. Null if there is no default.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
val default by meta.value()
|
var default: Value? by value()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if multiple values with this name are allowed.
|
* True if multiple values with this name are allowed.
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
val multiple: Boolean by meta.boolean(false)
|
var multiple: Boolean by boolean(false)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if the value is required
|
* True if the value is required
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
val required: Boolean by meta.boolean(default == null)
|
var required: Boolean by boolean { default == null }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Value name
|
* Value name
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
val name: String by meta.string{ error("Anonimous descriptors are not allowed")}
|
var name: String by string { error("Anonymous descriptors are not allowed") }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The value info
|
* The value info
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
val info: String by stringValue(def = "")
|
var info: String? by string()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A list of allowed ValueTypes. Empty if any value type allowed
|
* A list of allowed ValueTypes. Empty if any value type allowed
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
val type: List<ValueType> by customValue(def = emptyList()) {
|
var type: List<ValueType> by value().map {
|
||||||
it.list.map { v -> ValueType.valueOf(v.string) }
|
it?.list?.map { v -> ValueType.valueOf(v.string) } ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
val tags: List<String> by customValue(def = emptyList()) {
|
var tags: List<String> by value().map { value ->
|
||||||
meta.getStringArray("tags").toList()
|
value?.list?.map { it.string } ?: emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -92,7 +83,7 @@ class ValueDescriptor(val meta: Meta) : MetaRepr {
|
|||||||
* @param value
|
* @param value
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fun isValueAllowed(value: Value): Boolean {
|
fun isAllowedValue(value: Value): Boolean {
|
||||||
return (type.isEmpty() || type.contains(ValueType.STRING) || type.contains(value.type)) && (allowedValues.isEmpty() || allowedValues.contains(
|
return (type.isEmpty() || type.contains(ValueType.STRING) || type.contains(value.type)) && (allowedValues.isEmpty() || allowedValues.contains(
|
||||||
value
|
value
|
||||||
))
|
))
|
||||||
@ -104,96 +95,74 @@ class ValueDescriptor(val meta: Meta) : MetaRepr {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
val allowedValues: List<Value> by customValue(
|
var allowedValues: List<Value> by value().map {
|
||||||
def = if (type.size == 1 && type[0] === ValueType.BOOLEAN) {
|
it?.list ?: if (type.size == 1 && type[0] === ValueType.BOOLEAN) {
|
||||||
listOf(BooleanValue.TRUE, BooleanValue.FALSE)
|
listOf(True, False)
|
||||||
} else {
|
} else {
|
||||||
emptyList()
|
emptyList()
|
||||||
}
|
}
|
||||||
) { it.list }
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a value descriptor from annotation
|
|
||||||
*/
|
|
||||||
fun build(def: ValueDef): ValueDescriptor {
|
|
||||||
val builder = MetaBuilder("value")
|
|
||||||
.setValue("name", def.key)
|
|
||||||
|
|
||||||
if (def.type.isNotEmpty()) {
|
|
||||||
builder.setValue("type", def.type)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (def.multiple) {
|
companion object : SpecificationCompanion<ValueDescriptor> {
|
||||||
builder.setValue("multiple", def.multiple)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!def.info.isEmpty()) {
|
override fun wrap(config: Config): ValueDescriptor = ValueDescriptor(config)
|
||||||
builder.setValue("info", def.info)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (def.allowed.isNotEmpty()) {
|
// /**
|
||||||
builder.setValue("allowedValues", def.allowed)
|
// * Build a value descriptor from annotation
|
||||||
} else if (def.enumeration != Any::class) {
|
// */
|
||||||
if (def.enumeration.java.isEnum) {
|
// fun build(def: ValueDef): ValueDescriptor {
|
||||||
val values = def.enumeration.java.enumConstants
|
// val builder = MetaBuilder("value")
|
||||||
builder.setValue("allowedValues", values.map { it.toString() })
|
// .setValue("name", def.key)
|
||||||
} else {
|
//
|
||||||
throw RuntimeException("Only enumeration classes are allowed in 'enumeration' annotation property")
|
// if (def.type.isNotEmpty()) {
|
||||||
}
|
// builder.setValue("type", def.type)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if (def.def.isNotEmpty()) {
|
// if (def.multiple) {
|
||||||
builder.setValue("default", def.def)
|
// builder.setValue("multiple", def.multiple)
|
||||||
} else if (!def.required) {
|
// }
|
||||||
builder.setValue("required", def.required)
|
//
|
||||||
}
|
// if (!def.info.isEmpty()) {
|
||||||
|
// builder.setValue("info", def.info)
|
||||||
if (def.tags.isNotEmpty()) {
|
// }
|
||||||
builder.setValue("tags", def.tags)
|
//
|
||||||
}
|
// if (def.allowed.isNotEmpty()) {
|
||||||
return ValueDescriptor(builder)
|
// builder.setValue("allowedValues", def.allowed)
|
||||||
}
|
// } else if (def.enumeration != Any::class) {
|
||||||
|
// if (def.enumeration.java.isEnum) {
|
||||||
/**
|
// val values = def.enumeration.java.enumConstants
|
||||||
* Build a value descriptor from its fields
|
// builder.setValue("allowedValues", values.map { it.toString() })
|
||||||
*/
|
// } else {
|
||||||
fun build(
|
// throw RuntimeException("Only enumeration classes are allowed in 'enumeration' annotation property")
|
||||||
name: String,
|
// }
|
||||||
info: String = "",
|
// }
|
||||||
defaultValue: Any? = null,
|
//
|
||||||
required: Boolean = false,
|
// if (def.def.isNotEmpty()) {
|
||||||
multiple: Boolean = false,
|
// builder.setValue("default", def.def)
|
||||||
types: List<ValueType> = emptyList(),
|
// } else if (!def.required) {
|
||||||
allowedValues: List<Any> = emptyList()
|
// builder.setValue("required", def.required)
|
||||||
): ValueDescriptor {
|
// }
|
||||||
val valueBuilder = buildMeta("value") {
|
//
|
||||||
"name" to name
|
// if (def.tags.isNotEmpty()) {
|
||||||
if (!types.isEmpty()) "type" to types
|
// builder.setValue("tags", def.tags)
|
||||||
if (required) "required" to required
|
// }
|
||||||
if (multiple) "multiple" to multiple
|
// return ValueDescriptor(builder)
|
||||||
if (!info.isEmpty()) "info" to info
|
// }
|
||||||
if (defaultValue != null) "default" to defaultValue
|
//
|
||||||
if (!allowedValues.isEmpty()) "allowedValues" to allowedValues
|
// /**
|
||||||
}.build()
|
// * Build empty value descriptor
|
||||||
return ValueDescriptor(valueBuilder)
|
// */
|
||||||
}
|
// fun empty(valueName: String): ValueDescriptor {
|
||||||
|
// val builder = MetaBuilder("value")
|
||||||
/**
|
// .setValue("name", valueName)
|
||||||
* Build empty value descriptor
|
// return ValueDescriptor(builder)
|
||||||
*/
|
// }
|
||||||
fun empty(valueName: String): ValueDescriptor {
|
//
|
||||||
val builder = MetaBuilder("value")
|
// /**
|
||||||
.setValue("name", valueName)
|
// * Merge two separate value descriptors
|
||||||
return ValueDescriptor(builder)
|
// */
|
||||||
}
|
// fun merge(primary: ValueDescriptor, secondary: ValueDescriptor): ValueDescriptor {
|
||||||
|
// return ValueDescriptor(Laminate(primary.meta, secondary.meta))
|
||||||
/**
|
// }
|
||||||
* Merge two separate value descriptors
|
|
||||||
*/
|
|
||||||
fun merge(primary: ValueDescriptor, secondary: ValueDescriptor): ValueDescriptor {
|
|
||||||
return ValueDescriptor(Laminate(primary.meta, secondary.meta))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 Alexander Nozik.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package hep.dataforge.descriptors
|
||||||
|
|
||||||
|
import hep.dataforge.values.ValueType
|
||||||
|
import kotlin.reflect.KClass
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.PROPERTY)
|
||||||
|
@MustBeDocumented
|
||||||
|
annotation class ValueDef(
|
||||||
|
val key: String,
|
||||||
|
val type: Array<ValueType> = [ValueType.STRING],
|
||||||
|
val multiple: Boolean = false,
|
||||||
|
val def: String = "",
|
||||||
|
val info: String = "",
|
||||||
|
val required: Boolean = true,
|
||||||
|
val allowed: Array<String> = [],
|
||||||
|
val enumeration: KClass<*> = Any::class,
|
||||||
|
val tags: Array<String> = []
|
||||||
|
)
|
||||||
|
|
||||||
|
@MustBeDocumented
|
||||||
|
annotation class NodeDef(
|
||||||
|
val key: String,
|
||||||
|
val info: String = "",
|
||||||
|
val multiple: Boolean = false,
|
||||||
|
val required: Boolean = false,
|
||||||
|
val tags: Array<String> = [],
|
||||||
|
/**
|
||||||
|
* A list of child value descriptors
|
||||||
|
*/
|
||||||
|
val values: Array<ValueDef> = [],
|
||||||
|
/**
|
||||||
|
* A target class for this node to describe
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
val type: KClass<*> = Any::class,
|
||||||
|
/**
|
||||||
|
* The DataForge path to the resource containing the description. Following targets are supported:
|
||||||
|
*
|
||||||
|
* 1. resource
|
||||||
|
* 1. file
|
||||||
|
* 1. class
|
||||||
|
* 1. method
|
||||||
|
* 1. property
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Does not work if [type] is provided
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
val descriptor: String = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description text for meta property, node or whole object
|
||||||
|
*/
|
||||||
|
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@MustBeDocumented
|
||||||
|
annotation class Description(val value: String)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation for value property which states that lists are expected
|
||||||
|
*/
|
||||||
|
@Target(AnnotationTarget.PROPERTY)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@MustBeDocumented
|
||||||
|
annotation class Multiple
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Descriptor target
|
||||||
|
* The DataForge path to the resource containing the description. Following targets are supported:
|
||||||
|
* 1. resource
|
||||||
|
* 1. file
|
||||||
|
* 1. class
|
||||||
|
* 1. method
|
||||||
|
* 1. property
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Does not work if [type] is provided
|
||||||
|
*/
|
||||||
|
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@MustBeDocumented
|
||||||
|
annotation class Descriptor(val value: String)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aggregator class for descriptor nodes
|
||||||
|
*/
|
||||||
|
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.VALUE_PARAMETER)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@MustBeDocumented
|
||||||
|
annotation class DescriptorNodes(vararg val nodes: NodeDef)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Aggregator class for descriptor values
|
||||||
|
*/
|
||||||
|
@Target(AnnotationTarget.CLASS, AnnotationTarget.PROPERTY, AnnotationTarget.FUNCTION, AnnotationTarget.VALUE_PARAMETER)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@MustBeDocumented
|
||||||
|
annotation class DescriptorValues(vararg val nodes: ValueDef)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alternative name for property descriptor declaration
|
||||||
|
*/
|
||||||
|
@Target(AnnotationTarget.PROPERTY, AnnotationTarget.VALUE_PARAMETER)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@MustBeDocumented
|
||||||
|
annotation class DescriptorName(val name: String)
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.PROPERTY)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@MustBeDocumented
|
||||||
|
annotation class DescriptorValue(val def: ValueDef)
|
||||||
|
//TODO enter fields directly?
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.PROPERTY)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@MustBeDocumented
|
||||||
|
annotation class ValueProperty(
|
||||||
|
val name: String = "",
|
||||||
|
val type: Array<ValueType> = [ValueType.STRING],
|
||||||
|
val multiple: Boolean = false,
|
||||||
|
val def: String = "",
|
||||||
|
val enumeration: KClass<*> = Any::class,
|
||||||
|
val tags: Array<String> = []
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.PROPERTY)
|
||||||
|
@Retention(AnnotationRetention.RUNTIME)
|
||||||
|
@MustBeDocumented
|
||||||
|
annotation class NodeProperty(val name: String = "")
|
@ -10,8 +10,8 @@ import kotlin.jvm.JvmName
|
|||||||
/**
|
/**
|
||||||
* A property delegate that uses custom key
|
* A property delegate that uses custom key
|
||||||
*/
|
*/
|
||||||
fun Configurable.value(default: Value = Null, key: String? = null) =
|
fun Configurable.value(default: Any = Null, key: String? = null) =
|
||||||
ValueConfigDelegate(config, key, default)
|
ValueConfigDelegate(config, key, Value.of(default))
|
||||||
|
|
||||||
fun Configurable.string(default: String? = null, key: String? = null) =
|
fun Configurable.string(default: String? = null, key: String? = null) =
|
||||||
StringConfigDelegate(config, key, default)
|
StringConfigDelegate(config, key, default)
|
||||||
@ -28,15 +28,28 @@ fun Configurable.child(key: String? = null) = MetaNodeDelegate(config, key)
|
|||||||
|
|
||||||
@JvmName("safeString")
|
@JvmName("safeString")
|
||||||
fun Configurable.string(default: String, key: String? = null) =
|
fun Configurable.string(default: String, key: String? = null) =
|
||||||
SafeStringConfigDelegate(config, key, default)
|
SafeStringConfigDelegate(config, key) { default }
|
||||||
|
|
||||||
@JvmName("safeBoolean")
|
@JvmName("safeBoolean")
|
||||||
fun Configurable.boolean(default: Boolean, key: String? = null) =
|
fun Configurable.boolean(default: Boolean, key: String? = null) =
|
||||||
SafeBooleanConfigDelegate(config, key, default)
|
SafeBooleanConfigDelegate(config, key) { default }
|
||||||
|
|
||||||
@JvmName("safeNumber")
|
@JvmName("safeNumber")
|
||||||
fun Configurable.number(default: Number, key: String? = null) =
|
fun Configurable.number(default: Number, key: String? = null) =
|
||||||
|
SafeNumberConfigDelegate(config, key) { default }
|
||||||
|
|
||||||
|
@JvmName("safeString")
|
||||||
|
fun Configurable.string(key: String? = null, default: () -> String) =
|
||||||
|
SafeStringConfigDelegate(config, key, default)
|
||||||
|
|
||||||
|
@JvmName("safeBoolean")
|
||||||
|
fun Configurable.boolean(key: String? = null, default: () -> Boolean) =
|
||||||
|
SafeBooleanConfigDelegate(config, key, default)
|
||||||
|
|
||||||
|
@JvmName("safeNumber")
|
||||||
|
fun Configurable.number(key: String? = null, default: () -> Number) =
|
||||||
SafeNumberConfigDelegate(config, key, default)
|
SafeNumberConfigDelegate(config, key, default)
|
||||||
|
|
||||||
|
|
||||||
inline fun <reified E : Enum<E>> Configurable.enum(default: E, key: String? = null) =
|
inline fun <reified E : Enum<E>> Configurable.enum(default: E, key: String? = null) =
|
||||||
SafeEnumvConfigDelegate(config, key, default) { enumValueOf(it) }
|
SafeEnumvConfigDelegate(config, key, default) { enumValueOf(it) }
|
@ -183,6 +183,9 @@ class ValueConfigDelegate<M : MutableMeta<M>>(
|
|||||||
config.setValue(name, value)
|
config.setValue(name, value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> map(writer: (T) -> Value? = { Value.of(it) }, reader: (Value?) -> T) =
|
||||||
|
ReadWriteDelegateWrapper(this, reader, writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
class StringConfigDelegate<M : MutableMeta<M>>(
|
class StringConfigDelegate<M : MutableMeta<M>>(
|
||||||
|
Loading…
Reference in New Issue
Block a user