Lazy safe delegates for meta values
This commit is contained in:
parent
5eb2bcfce6
commit
a02a5fbc3f
@ -20,9 +20,10 @@ interface Action<in T : Any, out R : Any> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Action composition. The result is terminal if one of parts is terminal
|
* Action composition. The result is terminal if one of its parts is terminal
|
||||||
*/
|
*/
|
||||||
infix fun <T : Any, I : Any, R : Any> Action<T, I>.then(action: Action<I, R>): Action<T, R> {
|
infix fun <T : Any, I : Any, R : Any> Action<T, I>.then(action: Action<I, R>): Action<T, R> {
|
||||||
|
// TODO introduce composite action and add optimize by adding action to the list
|
||||||
return object : Action<T, R> {
|
return object : Action<T, R> {
|
||||||
override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> {
|
override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> {
|
||||||
return action(this@then.invoke(node, meta), meta)
|
return action(this@then.invoke(node, meta), meta)
|
||||||
|
@ -28,7 +28,9 @@ interface Goal<out T> : Deferred<T>, CoroutineScope {
|
|||||||
/**
|
/**
|
||||||
* A monitor of goal state that could be accessed only form inside the goal
|
* A monitor of goal state that could be accessed only form inside the goal
|
||||||
*/
|
*/
|
||||||
class GoalMonitor {
|
class GoalMonitor : CoroutineContext.Element {
|
||||||
|
override val key: CoroutineContext.Key<*> get() = GoalMonitor
|
||||||
|
|
||||||
var totalWork: Double = 1.0
|
var totalWork: Double = 1.0
|
||||||
var workDone: Double = 0.0
|
var workDone: Double = 0.0
|
||||||
var status: String = ""
|
var status: String = ""
|
||||||
@ -46,6 +48,8 @@ class GoalMonitor {
|
|||||||
fun finish() {
|
fun finish() {
|
||||||
workDone = totalWork
|
workDone = totalWork
|
||||||
}
|
}
|
||||||
|
|
||||||
|
companion object : CoroutineContext.Key<GoalMonitor>
|
||||||
}
|
}
|
||||||
|
|
||||||
private class GoalImpl<T>(
|
private class GoalImpl<T>(
|
||||||
|
@ -0,0 +1,191 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.descriptors
|
||||||
|
|
||||||
|
import hep.dataforge.Named
|
||||||
|
import hep.dataforge.description.ValueDescriptor
|
||||||
|
import hep.dataforge.meta.*
|
||||||
|
import hep.dataforge.names.Name
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Descriptor for meta node. Could contain additional information for viewing
|
||||||
|
* and editing.
|
||||||
|
*
|
||||||
|
* @author Alexander Nozik
|
||||||
|
*/
|
||||||
|
open class NodeDescriptor(val meta: Meta) : MetaRepr {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if multiple children with this nodes name are allowed. Anonymous
|
||||||
|
* nodes are always single
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
val multiple: Boolean by meta.boolean(false)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the node is required
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
val required: Boolean by meta.boolean(false)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The node description
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
open val info: String by meta.string("")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of tags for this node. Tags used to customize node usage
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
val tags: List<String> by customValue(def = emptyList()) { it.list.map { it.string } }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of this node
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
override val name: String by stringValue(def = meta.name)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of value descriptors
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
fun valueDescriptors(): Map<String, ValueDescriptor> {
|
||||||
|
val map = HashMap<String, ValueDescriptor>()
|
||||||
|
if (meta.hasMeta("value")) {
|
||||||
|
for (valueNode in meta.getMetaList("value")) {
|
||||||
|
val vd = ValueDescriptor(valueNode)
|
||||||
|
map[vd.name] = vd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The child node descriptor for given name. Name syntax is supported.
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
fun getNodeDescriptor(name: String): NodeDescriptor? {
|
||||||
|
return getNodeDescriptor(Name.of(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getNodeDescriptor(name: Name): NodeDescriptor? {
|
||||||
|
return if (name.length == 1) {
|
||||||
|
childrenDescriptors()[name.unescaped]
|
||||||
|
} else {
|
||||||
|
getNodeDescriptor(name.cutLast())?.getNodeDescriptor(name.last)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value descriptor for given value name. Name syntax is supported.
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
fun getValueDescriptor(name: String): ValueDescriptor? {
|
||||||
|
return getValueDescriptor(Name.of(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getValueDescriptor(name: Name): ValueDescriptor? {
|
||||||
|
return if (name.length == 1) {
|
||||||
|
valueDescriptors()[name.unescaped]
|
||||||
|
} else {
|
||||||
|
getNodeDescriptor(name.cutLast())?.getValueDescriptor(name.last)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The map of children node descriptors
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
fun childrenDescriptors(): Map<String, NodeDescriptor> {
|
||||||
|
val map = HashMap<String, NodeDescriptor>()
|
||||||
|
if (meta.hasMeta("node")) {
|
||||||
|
for (node in meta.getMetaList("node")) {
|
||||||
|
val nd = NodeDescriptor(node)
|
||||||
|
map[nd.name] = nd
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return map
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this node has default
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
fun hasDefault(): Boolean {
|
||||||
|
return meta.hasMeta("default")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 = "")
|
||||||
|
|
||||||
|
override fun toMeta(): Meta {
|
||||||
|
return meta
|
||||||
|
}
|
||||||
|
|
||||||
|
fun builder(): DescriptorBuilder = DescriptorBuilder(this.name, Configuration(this.meta))
|
||||||
|
|
||||||
|
//override val descriptor: NodeDescriptor = empty("descriptor")
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
|
||||||
|
fun empty(nodeName: String): NodeDescriptor {
|
||||||
|
return NodeDescriptor(Meta.buildEmpty(nodeName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,199 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.names.AnonymousNotAlowed
|
||||||
|
import hep.dataforge.values.BooleanValue
|
||||||
|
import hep.dataforge.values.Value
|
||||||
|
import hep.dataforge.values.ValueType
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A descriptor for meta value
|
||||||
|
*
|
||||||
|
* Descriptor can have non-atomic path. It is resolved when descriptor is added to the node
|
||||||
|
*
|
||||||
|
* @author Alexander Nozik
|
||||||
|
*/
|
||||||
|
class ValueDescriptor(val meta: Meta) : MetaRepr {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default for this value. Null if there is no default.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
val default by meta.value()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if multiple values with this name are allowed.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
val multiple: Boolean by meta.boolean(false)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True if the value is required
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
val required: Boolean by meta.boolean(default == null)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Value name
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
val name: String by meta.string{ error("Anonimous descriptors are not allowed")}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The value info
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
val info: String by stringValue(def = "")
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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) }
|
||||||
|
}
|
||||||
|
|
||||||
|
val tags: List<String> by customValue(def = emptyList()) {
|
||||||
|
meta.getStringArray("tags").toList()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if given value is allowed for here. The type should be allowed and
|
||||||
|
* if it is value should be within allowed values
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
fun isValueAllowed(value: Value): Boolean {
|
||||||
|
return (type.isEmpty() || type.contains(ValueType.STRING) || type.contains(value.type)) && (allowedValues.isEmpty() || allowedValues.contains(
|
||||||
|
value
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A list of allowed values with descriptions. If empty than any value is
|
||||||
|
* allowed.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
val allowedValues: List<Value> by customValue(
|
||||||
|
def = if (type.size == 1 && type[0] === ValueType.BOOLEAN) {
|
||||||
|
listOf(BooleanValue.TRUE, BooleanValue.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)
|
||||||
|
}
|
||||||
|
|
||||||
|
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 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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -56,22 +56,40 @@ class DelegateWrapper<T, R>(val delegate: ReadOnlyProperty<Any?, T>, val reader:
|
|||||||
|
|
||||||
//Delegates with non-null values
|
//Delegates with non-null values
|
||||||
|
|
||||||
class SafeStringDelegate(val meta: Meta, private val key: String? = null, private val default: String) :
|
class SafeStringDelegate(
|
||||||
ReadOnlyProperty<Any?, String> {
|
val meta: Meta,
|
||||||
|
private val key: String? = null,
|
||||||
|
default: () -> String
|
||||||
|
) : ReadOnlyProperty<Any?, String> {
|
||||||
|
|
||||||
|
private val default: String by lazy(default)
|
||||||
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): String {
|
override fun getValue(thisRef: Any?, property: KProperty<*>): String {
|
||||||
return meta[key ?: property.name]?.string ?: default
|
return meta[key ?: property.name]?.string ?: default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SafeBooleanDelegate(val meta: Meta, private val key: String? = null, private val default: Boolean) :
|
class SafeBooleanDelegate(
|
||||||
ReadOnlyProperty<Any?, Boolean> {
|
val meta: Meta,
|
||||||
|
private val key: String? = null,
|
||||||
|
default: () -> Boolean
|
||||||
|
) : ReadOnlyProperty<Any?, Boolean> {
|
||||||
|
|
||||||
|
private val default: Boolean by lazy(default)
|
||||||
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean {
|
override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean {
|
||||||
return meta[key ?: property.name]?.boolean ?: default
|
return meta[key ?: property.name]?.boolean ?: default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class SafeNumberDelegate(val meta: Meta, private val key: String? = null, private val default: Number) :
|
class SafeNumberDelegate(
|
||||||
ReadOnlyProperty<Any?, Number> {
|
val meta: Meta,
|
||||||
|
private val key: String? = null,
|
||||||
|
default: () -> Number
|
||||||
|
) : ReadOnlyProperty<Any?, Number> {
|
||||||
|
|
||||||
|
private val default: Number by lazy(default)
|
||||||
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): Number {
|
override fun getValue(thisRef: Any?, property: KProperty<*>): Number {
|
||||||
return meta[key ?: property.name]?.number ?: default
|
return meta[key ?: property.name]?.number ?: default
|
||||||
}
|
}
|
||||||
@ -118,13 +136,29 @@ fun Meta.number(default: Number? = null, key: String? = null) = NumberDelegate(t
|
|||||||
fun Meta.child(key: String? = null) = ChildDelegate(this, key) { it }
|
fun Meta.child(key: String? = null) = ChildDelegate(this, key) { it }
|
||||||
|
|
||||||
@JvmName("safeString")
|
@JvmName("safeString")
|
||||||
fun Meta.string(default: String, key: String? = null) = SafeStringDelegate(this, key, default)
|
fun Meta.string(default: String, key: String? = null) =
|
||||||
|
SafeStringDelegate(this, key) { default }
|
||||||
|
|
||||||
@JvmName("safeBoolean")
|
@JvmName("safeBoolean")
|
||||||
fun Meta.boolean(default: Boolean, key: String? = null) = SafeBooleanDelegate(this, key, default)
|
fun Meta.boolean(default: Boolean, key: String? = null) =
|
||||||
|
SafeBooleanDelegate(this, key) { default }
|
||||||
|
|
||||||
@JvmName("safeNumber")
|
@JvmName("safeNumber")
|
||||||
fun Meta.number(default: Number, key: String? = null) = SafeNumberDelegate(this, key, default)
|
fun Meta.number(default: Number, key: String? = null) =
|
||||||
|
SafeNumberDelegate(this, key) { default }
|
||||||
|
|
||||||
|
@JvmName("safeString")
|
||||||
|
fun Meta.string(key: String? = null, default: () -> String) =
|
||||||
|
SafeStringDelegate(this, key, default)
|
||||||
|
|
||||||
|
@JvmName("safeBoolean")
|
||||||
|
fun Meta.boolean(key: String? = null, default: () -> Boolean) =
|
||||||
|
SafeBooleanDelegate(this, key, default)
|
||||||
|
|
||||||
|
@JvmName("safeNumber")
|
||||||
|
fun Meta.number(key: String? = null, default: () -> Number) =
|
||||||
|
SafeNumberDelegate(this, key, default)
|
||||||
|
|
||||||
|
|
||||||
inline fun <reified E : Enum<E>> Meta.enum(default: E, key: String? = null) =
|
inline fun <reified E : Enum<E>> Meta.enum(default: E, key: String? = null) =
|
||||||
SafeEnumDelegate(this, key, default) { enumValueOf(it) }
|
SafeEnumDelegate(this, key, default) { enumValueOf(it) }
|
||||||
@ -218,8 +252,11 @@ class NumberConfigDelegate<M : MutableMeta<M>>(
|
|||||||
class SafeStringConfigDelegate<M : MutableMeta<M>>(
|
class SafeStringConfigDelegate<M : MutableMeta<M>>(
|
||||||
val config: M,
|
val config: M,
|
||||||
private val key: String? = null,
|
private val key: String? = null,
|
||||||
private val default: String
|
default: () -> String
|
||||||
) : ReadWriteProperty<Any?, String> {
|
) : ReadWriteProperty<Any?, String> {
|
||||||
|
|
||||||
|
private val default: String by lazy(default)
|
||||||
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): String {
|
override fun getValue(thisRef: Any?, property: KProperty<*>): String {
|
||||||
return config[key ?: property.name]?.string ?: default
|
return config[key ?: property.name]?.string ?: default
|
||||||
}
|
}
|
||||||
@ -232,8 +269,11 @@ class SafeStringConfigDelegate<M : MutableMeta<M>>(
|
|||||||
class SafeBooleanConfigDelegate<M : MutableMeta<M>>(
|
class SafeBooleanConfigDelegate<M : MutableMeta<M>>(
|
||||||
val config: M,
|
val config: M,
|
||||||
private val key: String? = null,
|
private val key: String? = null,
|
||||||
private val default: Boolean
|
default: () -> Boolean
|
||||||
) : ReadWriteProperty<Any?, Boolean> {
|
) : ReadWriteProperty<Any?, Boolean> {
|
||||||
|
|
||||||
|
private val default: Boolean by lazy(default)
|
||||||
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean {
|
override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean {
|
||||||
return config[key ?: property.name]?.boolean ?: default
|
return config[key ?: property.name]?.boolean ?: default
|
||||||
}
|
}
|
||||||
@ -246,8 +286,11 @@ class SafeBooleanConfigDelegate<M : MutableMeta<M>>(
|
|||||||
class SafeNumberConfigDelegate<M : MutableMeta<M>>(
|
class SafeNumberConfigDelegate<M : MutableMeta<M>>(
|
||||||
val config: M,
|
val config: M,
|
||||||
private val key: String? = null,
|
private val key: String? = null,
|
||||||
private val default: Number
|
default: () -> Number
|
||||||
) : ReadWriteProperty<Any?, Number> {
|
) : ReadWriteProperty<Any?, Number> {
|
||||||
|
|
||||||
|
private val default: Number by lazy(default)
|
||||||
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): Number {
|
override fun getValue(thisRef: Any?, property: KProperty<*>): Number {
|
||||||
return config[key ?: property.name]?.number ?: default
|
return config[key ?: property.name]?.number ?: default
|
||||||
}
|
}
|
||||||
@ -345,15 +388,28 @@ fun <M : MutableMetaNode<M>> M.child(key: String? = null) = MetaNodeDelegate(thi
|
|||||||
|
|
||||||
@JvmName("safeString")
|
@JvmName("safeString")
|
||||||
fun <M : MutableMeta<M>> M.string(default: String, key: String? = null) =
|
fun <M : MutableMeta<M>> M.string(default: String, key: String? = null) =
|
||||||
SafeStringConfigDelegate(this, key, default)
|
SafeStringConfigDelegate(this, key) { default }
|
||||||
|
|
||||||
@JvmName("safeBoolean")
|
@JvmName("safeBoolean")
|
||||||
fun <M : MutableMeta<M>> M.boolean(default: Boolean, key: String? = null) =
|
fun <M : MutableMeta<M>> M.boolean(default: Boolean, key: String? = null) =
|
||||||
SafeBooleanConfigDelegate(this, key, default)
|
SafeBooleanConfigDelegate(this, key) { default }
|
||||||
|
|
||||||
@JvmName("safeNumber")
|
@JvmName("safeNumber")
|
||||||
fun <M : MutableMeta<M>> M.number(default: Number, key: String? = null) =
|
fun <M : MutableMeta<M>> M.number(default: Number, key: String? = null) =
|
||||||
|
SafeNumberConfigDelegate(this, key) { default }
|
||||||
|
|
||||||
|
@JvmName("safeString")
|
||||||
|
fun <M : MutableMeta<M>> M.string(key: String? = null, default: () -> String) =
|
||||||
|
SafeStringConfigDelegate(this, key, default)
|
||||||
|
|
||||||
|
@JvmName("safeBoolean")
|
||||||
|
fun <M : MutableMeta<M>> M.boolean(key: String? = null, default: () -> Boolean) =
|
||||||
|
SafeBooleanConfigDelegate(this, key, default)
|
||||||
|
|
||||||
|
@JvmName("safeNumber")
|
||||||
|
fun <M : MutableMeta<M>> M.number(key: String? = null, default: () -> Number) =
|
||||||
SafeNumberConfigDelegate(this, key, default)
|
SafeNumberConfigDelegate(this, key, default)
|
||||||
|
|
||||||
|
|
||||||
inline fun <M : MutableMeta<M>, reified E : Enum<E>> M.enum(default: E, key: String? = null) =
|
inline fun <M : MutableMeta<M>, reified E : Enum<E>> M.enum(default: E, key: String? = null) =
|
||||||
SafeEnumvConfigDelegate(this, key, default) { enumValueOf(it) }
|
SafeEnumvConfigDelegate(this, key, default) { enumValueOf(it) }
|
||||||
|
Loading…
Reference in New Issue
Block a user