Descriptors
This commit is contained in:
parent
47e39ae0ac
commit
9fd89a5b60
@ -22,7 +22,6 @@
|
||||
package hep.dataforge.descriptors
|
||||
|
||||
import hep.dataforge.Named
|
||||
import hep.dataforge.description.ValueDescriptor
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.Name
|
||||
import java.util.*
|
||||
|
@ -14,19 +14,10 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 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
|
||||
package hep.dataforge.descriptors
|
||||
|
||||
import hep.dataforge.Named
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.AnonymousNotAlowed
|
||||
import hep.dataforge.values.BooleanValue
|
||||
import hep.dataforge.values.Value
|
||||
import hep.dataforge.values.ValueType
|
||||
import hep.dataforge.values.*
|
||||
|
||||
/**
|
||||
* A descriptor for meta value
|
||||
@ -35,54 +26,54 @@ import hep.dataforge.values.ValueType
|
||||
*
|
||||
* @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.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
val default by meta.value()
|
||||
var default: Value? by value()
|
||||
|
||||
/**
|
||||
* True if multiple values with this name are allowed.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
val multiple: Boolean by meta.boolean(false)
|
||||
var multiple: Boolean by boolean(false)
|
||||
|
||||
/**
|
||||
* True if the value is required
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
val required: Boolean by meta.boolean(default == null)
|
||||
var required: Boolean by boolean { default == null }
|
||||
|
||||
/**
|
||||
* Value name
|
||||
*
|
||||
* @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
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
val info: String by stringValue(def = "")
|
||||
var info: String? by string()
|
||||
|
||||
/**
|
||||
* A list of allowed ValueTypes. Empty if any value type allowed
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
val type: List<ValueType> by customValue(def = emptyList()) {
|
||||
it.list.map { v -> ValueType.valueOf(v.string) }
|
||||
var type: List<ValueType> by value().map {
|
||||
it?.list?.map { v -> ValueType.valueOf(v.string) } ?: emptyList()
|
||||
}
|
||||
|
||||
val tags: List<String> by customValue(def = emptyList()) {
|
||||
meta.getStringArray("tags").toList()
|
||||
var tags: List<String> by value().map { value ->
|
||||
value?.list?.map { it.string } ?: emptyList()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -92,7 +83,7 @@ class ValueDescriptor(val meta: Meta) : MetaRepr {
|
||||
* @param value
|
||||
* @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(
|
||||
value
|
||||
))
|
||||
@ -104,96 +95,74 @@ class ValueDescriptor(val meta: Meta) : MetaRepr {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
val allowedValues: List<Value> by customValue(
|
||||
def = if (type.size == 1 && type[0] === ValueType.BOOLEAN) {
|
||||
listOf(BooleanValue.TRUE, BooleanValue.FALSE)
|
||||
var allowedValues: List<Value> by value().map {
|
||||
it?.list ?: if (type.size == 1 && type[0] === ValueType.BOOLEAN) {
|
||||
listOf(True, False)
|
||||
} else {
|
||||
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) {
|
||||
builder.setValue("multiple", def.multiple)
|
||||
}
|
||||
companion object : SpecificationCompanion<ValueDescriptor> {
|
||||
|
||||
if (!def.info.isEmpty()) {
|
||||
builder.setValue("info", def.info)
|
||||
}
|
||||
override fun wrap(config: Config): ValueDescriptor = ValueDescriptor(config)
|
||||
|
||||
if (def.allowed.isNotEmpty()) {
|
||||
builder.setValue("allowedValues", def.allowed)
|
||||
} else if (def.enumeration != Any::class) {
|
||||
if (def.enumeration.java.isEnum) {
|
||||
val values = def.enumeration.java.enumConstants
|
||||
builder.setValue("allowedValues", values.map { it.toString() })
|
||||
} else {
|
||||
throw RuntimeException("Only enumeration classes are allowed in 'enumeration' annotation property")
|
||||
}
|
||||
}
|
||||
|
||||
if (def.def.isNotEmpty()) {
|
||||
builder.setValue("default", def.def)
|
||||
} else if (!def.required) {
|
||||
builder.setValue("required", def.required)
|
||||
}
|
||||
|
||||
if (def.tags.isNotEmpty()) {
|
||||
builder.setValue("tags", def.tags)
|
||||
}
|
||||
return ValueDescriptor(builder)
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a value descriptor from its fields
|
||||
*/
|
||||
fun build(
|
||||
name: String,
|
||||
info: String = "",
|
||||
defaultValue: Any? = null,
|
||||
required: Boolean = false,
|
||||
multiple: Boolean = false,
|
||||
types: List<ValueType> = emptyList(),
|
||||
allowedValues: List<Any> = emptyList()
|
||||
): ValueDescriptor {
|
||||
val valueBuilder = buildMeta("value") {
|
||||
"name" to name
|
||||
if (!types.isEmpty()) "type" to types
|
||||
if (required) "required" to required
|
||||
if (multiple) "multiple" to multiple
|
||||
if (!info.isEmpty()) "info" to info
|
||||
if (defaultValue != null) "default" to defaultValue
|
||||
if (!allowedValues.isEmpty()) "allowedValues" to allowedValues
|
||||
}.build()
|
||||
return ValueDescriptor(valueBuilder)
|
||||
}
|
||||
|
||||
/**
|
||||
* Build empty value descriptor
|
||||
*/
|
||||
fun empty(valueName: String): ValueDescriptor {
|
||||
val builder = MetaBuilder("value")
|
||||
.setValue("name", valueName)
|
||||
return ValueDescriptor(builder)
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge two separate value descriptors
|
||||
*/
|
||||
fun merge(primary: ValueDescriptor, secondary: ValueDescriptor): ValueDescriptor {
|
||||
return ValueDescriptor(Laminate(primary.meta, secondary.meta))
|
||||
}
|
||||
// /**
|
||||
// * 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) {
|
||||
// builder.setValue("multiple", def.multiple)
|
||||
// }
|
||||
//
|
||||
// if (!def.info.isEmpty()) {
|
||||
// builder.setValue("info", def.info)
|
||||
// }
|
||||
//
|
||||
// if (def.allowed.isNotEmpty()) {
|
||||
// builder.setValue("allowedValues", def.allowed)
|
||||
// } else if (def.enumeration != Any::class) {
|
||||
// if (def.enumeration.java.isEnum) {
|
||||
// val values = def.enumeration.java.enumConstants
|
||||
// builder.setValue("allowedValues", values.map { it.toString() })
|
||||
// } else {
|
||||
// throw RuntimeException("Only enumeration classes are allowed in 'enumeration' annotation property")
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (def.def.isNotEmpty()) {
|
||||
// builder.setValue("default", def.def)
|
||||
// } else if (!def.required) {
|
||||
// builder.setValue("required", def.required)
|
||||
// }
|
||||
//
|
||||
// if (def.tags.isNotEmpty()) {
|
||||
// builder.setValue("tags", def.tags)
|
||||
// }
|
||||
// return ValueDescriptor(builder)
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * Build empty value descriptor
|
||||
// */
|
||||
// fun empty(valueName: String): ValueDescriptor {
|
||||
// val builder = MetaBuilder("value")
|
||||
// .setValue("name", valueName)
|
||||
// return ValueDescriptor(builder)
|
||||
// }
|
||||
//
|
||||
// /**
|
||||
// * 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
|
||||
*/
|
||||
fun Configurable.value(default: Value = Null, key: String? = null) =
|
||||
ValueConfigDelegate(config, key, default)
|
||||
fun Configurable.value(default: Any = Null, key: String? = null) =
|
||||
ValueConfigDelegate(config, key, Value.of(default))
|
||||
|
||||
fun Configurable.string(default: String? = null, key: String? = null) =
|
||||
StringConfigDelegate(config, key, default)
|
||||
@ -28,15 +28,28 @@ fun Configurable.child(key: String? = null) = MetaNodeDelegate(config, key)
|
||||
|
||||
@JvmName("safeString")
|
||||
fun Configurable.string(default: String, key: String? = null) =
|
||||
SafeStringConfigDelegate(config, key, default)
|
||||
SafeStringConfigDelegate(config, key) { default }
|
||||
|
||||
@JvmName("safeBoolean")
|
||||
fun Configurable.boolean(default: Boolean, key: String? = null) =
|
||||
SafeBooleanConfigDelegate(config, key, default)
|
||||
SafeBooleanConfigDelegate(config, key) { default }
|
||||
|
||||
@JvmName("safeNumber")
|
||||
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)
|
||||
|
||||
|
||||
inline fun <reified E : Enum<E>> Configurable.enum(default: E, key: String? = null) =
|
||||
SafeEnumvConfigDelegate(config, key, default) { enumValueOf(it) }
|
@ -183,6 +183,9 @@ class ValueConfigDelegate<M : MutableMeta<M>>(
|
||||
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>>(
|
||||
|
Loading…
Reference in New Issue
Block a user