dataforge-meta cleanup
This commit is contained in:
parent
87af89b47d
commit
52a3c8bc6f
@ -2,7 +2,6 @@ package hep.dataforge.context
|
|||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.meta.MetaRepr
|
import hep.dataforge.meta.MetaRepr
|
||||||
import hep.dataforge.meta.buildMeta
|
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.toName
|
import hep.dataforge.names.toName
|
||||||
import hep.dataforge.provider.Provider
|
import hep.dataforge.provider.Provider
|
||||||
|
@ -2,7 +2,6 @@ package hep.dataforge.context
|
|||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.meta.MetaRepr
|
import hep.dataforge.meta.MetaRepr
|
||||||
import hep.dataforge.meta.buildMeta
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The tag which contains information about name, group and version of some
|
* The tag which contains information about name, group and version of some
|
||||||
@ -10,7 +9,7 @@ import hep.dataforge.meta.buildMeta
|
|||||||
*
|
*
|
||||||
* @author Alexander Nozik
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
data class PluginTag(
|
public data class PluginTag(
|
||||||
val name: String,
|
val name: String,
|
||||||
val group: String = "",
|
val group: String = "",
|
||||||
val version: String = ""
|
val version: String = ""
|
||||||
@ -22,7 +21,7 @@ data class PluginTag(
|
|||||||
* @param otherTag
|
* @param otherTag
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fun matches(otherTag: PluginTag): Boolean {
|
public fun matches(otherTag: PluginTag): Boolean {
|
||||||
return matchesName(otherTag) && matchesGroup(otherTag)
|
return matchesName(otherTag) && matchesGroup(otherTag)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,9 +41,9 @@ data class PluginTag(
|
|||||||
"version" put version
|
"version" put version
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
public companion object {
|
||||||
|
|
||||||
const val DATAFORGE_GROUP = "hep.dataforge"
|
public const val DATAFORGE_GROUP: String = "hep.dataforge"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build new PluginTag from standard string representation
|
* Build new PluginTag from standard string representation
|
||||||
@ -52,7 +51,7 @@ data class PluginTag(
|
|||||||
* @param tag
|
* @param tag
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fun fromString(tag: String): PluginTag {
|
public fun fromString(tag: String): PluginTag {
|
||||||
val sepIndex = tag.indexOf(":")
|
val sepIndex = tag.indexOf(":")
|
||||||
return if (sepIndex >= 0) {
|
return if (sepIndex >= 0) {
|
||||||
PluginTag(group = tag.substring(0, sepIndex), name = tag.substring(sepIndex + 1))
|
PluginTag(group = tag.substring(0, sepIndex), name = tag.substring(sepIndex + 1))
|
||||||
|
@ -3,7 +3,6 @@ package hep.dataforge.data
|
|||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.full.isSubclassOf
|
import kotlin.reflect.full.isSubclassOf
|
||||||
import kotlin.reflect.full.isSuperclassOf
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Block the thread and get data content
|
* Block the thread and get data content
|
||||||
@ -14,7 +13,7 @@ public fun <T : Any> Data<T>.get(): T = runBlocking { await() }
|
|||||||
* Check that node is compatible with given type meaning that each element could be cast to the type
|
* Check that node is compatible with given type meaning that each element could be cast to the type
|
||||||
*/
|
*/
|
||||||
internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean =
|
internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean =
|
||||||
this.type.isSubclassOf(type)
|
type.isSubclassOf(this.type)
|
||||||
|
|
||||||
internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean =
|
internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean =
|
||||||
this.type.isSubclassOf(type)
|
this.type.isSubclassOf(type)
|
||||||
|
@ -12,6 +12,7 @@ import kotlinx.serialization.Serializer
|
|||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.Decoder
|
||||||
import kotlinx.serialization.encoding.Encoder
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -96,8 +97,12 @@ public interface MetaRepr {
|
|||||||
public fun toMeta(): Meta
|
public fun toMeta(): Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface ItemProvider{
|
public fun interface ItemProvider {
|
||||||
public fun getItem(name: Name): MetaItem<*>?
|
public fun getItem(name: Name): MetaItem<*>?
|
||||||
|
|
||||||
|
public companion object {
|
||||||
|
public val EMPTY: ItemProvider = ItemProvider { null }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -107,6 +112,7 @@ public interface ItemProvider{
|
|||||||
*
|
*
|
||||||
* * Same name siblings are supported via elements with the same [Name] but different queries
|
* * Same name siblings are supported via elements with the same [Name] but different queries
|
||||||
*/
|
*/
|
||||||
|
@Serializable(MetaSerializer::class)
|
||||||
public interface Meta : MetaRepr, ItemProvider {
|
public interface Meta : MetaRepr, ItemProvider {
|
||||||
/**
|
/**
|
||||||
* Top level items of meta tree
|
* Top level items of meta tree
|
||||||
@ -226,7 +232,10 @@ public abstract class MetaBase : Meta {
|
|||||||
|
|
||||||
override fun hashCode(): Int = items.hashCode()
|
override fun hashCode(): Int = items.hashCode()
|
||||||
|
|
||||||
override fun toString(): String = JSON_PRETTY.encodeToString(MetaSerializer, this)
|
override fun toString(): String = Json {
|
||||||
|
prettyPrint = true
|
||||||
|
useArrayPolymorphism = true
|
||||||
|
}.encodeToString(MetaSerializer, this)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -240,7 +249,7 @@ public abstract class AbstractMetaNode<M : MetaNode<M>> : MetaNode<M>, MetaBase(
|
|||||||
* If the argument is possibly mutable node, it is copied on creation
|
* If the argument is possibly mutable node, it is copied on creation
|
||||||
*/
|
*/
|
||||||
public class SealedMeta internal constructor(
|
public class SealedMeta internal constructor(
|
||||||
override val items: Map<NameToken, MetaItem<SealedMeta>>
|
override val items: Map<NameToken, MetaItem<SealedMeta>>,
|
||||||
) : AbstractMetaNode<SealedMeta>()
|
) : AbstractMetaNode<SealedMeta>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,113 +11,109 @@ import kotlin.jvm.JvmName
|
|||||||
* DSL builder for meta. Is not intended to store mutable state
|
* DSL builder for meta. Is not intended to store mutable state
|
||||||
*/
|
*/
|
||||||
@DFBuilder
|
@DFBuilder
|
||||||
class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
|
public class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
|
||||||
override fun wrapNode(meta: Meta): MetaBuilder = if (meta is MetaBuilder) meta else meta.builder()
|
override fun wrapNode(meta: Meta): MetaBuilder = if (meta is MetaBuilder) meta else meta.builder()
|
||||||
override fun empty(): MetaBuilder = MetaBuilder()
|
override fun empty(): MetaBuilder = MetaBuilder()
|
||||||
|
|
||||||
infix fun String.put(item: MetaItem<*>?) {
|
public infix fun String.put(item: MetaItem<*>?) {
|
||||||
set(this, item)
|
set(this, item)
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun String.put(value: Value?) {
|
public infix fun String.put(value: Value?) {
|
||||||
set(this, value)
|
set(this, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun String.put(string: String?) {
|
public infix fun String.put(string: String?) {
|
||||||
set(this, string?.asValue())
|
set(this, string?.asValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun String.put(number: Number?) {
|
public infix fun String.put(number: Number?) {
|
||||||
set(this, number?.asValue())
|
set(this, number?.asValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun String.put(boolean: Boolean?) {
|
public infix fun String.put(boolean: Boolean?) {
|
||||||
set(this, boolean?.asValue())
|
set(this, boolean?.asValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun String.put(enum: Enum<*>) {
|
public infix fun String.put(enum: Enum<*>) {
|
||||||
set(this, EnumValue(enum))
|
set(this, EnumValue(enum))
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmName("putValues")
|
@JvmName("putValues")
|
||||||
infix fun String.put(iterable: Iterable<Value>) {
|
public infix fun String.put(iterable: Iterable<Value>) {
|
||||||
set(this, iterable.asValue())
|
set(this, iterable.asValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmName("putNumbers")
|
@JvmName("putNumbers")
|
||||||
infix fun String.put(iterable: Iterable<Number>) {
|
public infix fun String.put(iterable: Iterable<Number>) {
|
||||||
set(this, iterable.map { it.asValue() }.asValue())
|
set(this, iterable.map { it.asValue() }.asValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmName("putStrings")
|
@JvmName("putStrings")
|
||||||
infix fun String.put(iterable: Iterable<String>) {
|
public infix fun String.put(iterable: Iterable<String>) {
|
||||||
set(this, iterable.map { it.asValue() }.asValue())
|
set(this, iterable.map { it.asValue() }.asValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun String.put(array: DoubleArray) {
|
public infix fun String.put(array: DoubleArray) {
|
||||||
set(this, array.asValue())
|
set(this, array.asValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun String.putValue(any: Any?) {
|
public infix fun String.put(meta: Meta?) {
|
||||||
set(this, Value.of(any))
|
|
||||||
}
|
|
||||||
|
|
||||||
infix fun String.put(meta: Meta?) {
|
|
||||||
this@MetaBuilder[this] = meta
|
this@MetaBuilder[this] = meta
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun String.put(repr: MetaRepr?) {
|
public infix fun String.put(repr: MetaRepr?) {
|
||||||
set(this, repr?.toMeta())
|
set(this, repr?.toMeta())
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmName("putMetas")
|
@JvmName("putMetas")
|
||||||
infix fun String.put(value: Iterable<Meta>) {
|
public infix fun String.put(value: Iterable<Meta>) {
|
||||||
this@MetaBuilder[this] = value.toList()
|
this@MetaBuilder[this] = value.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun String.put(metaBuilder: MetaBuilder.() -> Unit) {
|
public infix fun String.put(metaBuilder: MetaBuilder.() -> Unit) {
|
||||||
this@MetaBuilder[this] = MetaBuilder().apply(metaBuilder)
|
this@MetaBuilder[this] = MetaBuilder().apply(metaBuilder)
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun Name.put(value: Value?) {
|
public infix fun Name.put(value: Value?) {
|
||||||
set(this, value)
|
set(this, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun Name.put(string: String?) {
|
public infix fun Name.put(string: String?) {
|
||||||
set(this, string?.asValue())
|
set(this, string?.asValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun Name.put(number: Number?) {
|
public infix fun Name.put(number: Number?) {
|
||||||
set(this, number?.asValue())
|
set(this, number?.asValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun Name.put(boolean: Boolean?) {
|
public infix fun Name.put(boolean: Boolean?) {
|
||||||
set(this, boolean?.asValue())
|
set(this, boolean?.asValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun Name.put(enum: Enum<*>) {
|
public infix fun Name.put(enum: Enum<*>) {
|
||||||
set(this, EnumValue(enum))
|
set(this, EnumValue(enum))
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmName("putValues")
|
@JvmName("putValues")
|
||||||
infix fun Name.put(iterable: Iterable<Value>) {
|
public infix fun Name.put(iterable: Iterable<Value>) {
|
||||||
set(this, iterable.asValue())
|
set(this, iterable.asValue())
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun Name.put(meta: Meta?) {
|
public infix fun Name.put(meta: Meta?) {
|
||||||
this@MetaBuilder[this] = meta
|
this@MetaBuilder[this] = meta
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun Name.put(repr: MetaRepr?) {
|
public infix fun Name.put(repr: MetaRepr?) {
|
||||||
set(this, repr?.toMeta())
|
set(this, repr?.toMeta())
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmName("putMetas")
|
@JvmName("putMetas")
|
||||||
infix fun Name.put(value: Iterable<Meta>) {
|
public infix fun Name.put(value: Iterable<Meta>) {
|
||||||
this@MetaBuilder[this] = value.toList()
|
this@MetaBuilder[this] = value.toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
infix fun Name.put(metaBuilder: MetaBuilder.() -> Unit) {
|
public infix fun Name.put(metaBuilder: MetaBuilder.() -> Unit) {
|
||||||
this@MetaBuilder[this] = MetaBuilder().apply(metaBuilder)
|
this@MetaBuilder[this] = MetaBuilder().apply(metaBuilder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -125,7 +121,7 @@ class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
|
|||||||
/**
|
/**
|
||||||
* For safety, builder always copies the initial meta even if it is builder itself
|
* For safety, builder always copies the initial meta even if it is builder itself
|
||||||
*/
|
*/
|
||||||
fun Meta.builder(): MetaBuilder {
|
public fun Meta.builder(): MetaBuilder {
|
||||||
return MetaBuilder().also { builder ->
|
return MetaBuilder().also { builder ->
|
||||||
items.mapValues { entry ->
|
items.mapValues { entry ->
|
||||||
val item = entry.value
|
val item = entry.value
|
||||||
@ -140,16 +136,10 @@ fun Meta.builder(): MetaBuilder {
|
|||||||
/**
|
/**
|
||||||
* Create a deep copy of this meta and apply builder to it
|
* Create a deep copy of this meta and apply builder to it
|
||||||
*/
|
*/
|
||||||
fun Meta.edit(builder: MetaBuilder.() -> Unit): MetaBuilder = builder().apply(builder)
|
public fun Meta.edit(builder: MetaBuilder.() -> Unit): MetaBuilder = builder().apply(builder)
|
||||||
|
|
||||||
/**
|
|
||||||
* Build a [MetaBuilder] using given transformation
|
|
||||||
*/
|
|
||||||
@Deprecated("To be replaced with fake constructor", ReplaceWith("Meta"))
|
|
||||||
fun buildMeta(builder: MetaBuilder.() -> Unit): MetaBuilder = MetaBuilder().apply(builder)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a [MetaBuilder] using given transformation
|
* Build a [MetaBuilder] using given transformation
|
||||||
*/
|
*/
|
||||||
@Suppress("FunctionName")
|
@Suppress("FunctionName")
|
||||||
fun Meta(builder: MetaBuilder.() -> Unit): MetaBuilder = MetaBuilder().apply(builder)
|
public fun Meta(builder: MetaBuilder.() -> Unit): MetaBuilder = MetaBuilder().apply(builder)
|
@ -1,6 +1,7 @@
|
|||||||
package hep.dataforge.meta
|
package hep.dataforge.meta
|
||||||
|
|
||||||
import hep.dataforge.names.NameToken
|
import hep.dataforge.names.NameToken
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.Serializer
|
import kotlinx.serialization.Serializer
|
||||||
import kotlinx.serialization.builtins.MapSerializer
|
import kotlinx.serialization.builtins.MapSerializer
|
||||||
@ -11,12 +12,13 @@ import kotlinx.serialization.json.JsonDecoder
|
|||||||
import kotlinx.serialization.json.JsonEncoder
|
import kotlinx.serialization.json.JsonEncoder
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Serialized for meta
|
* Serialized for meta
|
||||||
*/
|
*/
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
@Serializer(Meta::class)
|
@Serializer(Meta::class)
|
||||||
object MetaSerializer : KSerializer<Meta> {
|
public object MetaSerializer : KSerializer<Meta> {
|
||||||
|
|
||||||
private val mapSerializer = MapSerializer(
|
private val mapSerializer = MapSerializer(
|
||||||
NameToken.serializer(),
|
NameToken.serializer(),
|
||||||
MetaItem.serializer(MetaSerializer)
|
MetaItem.serializer(MetaSerializer)
|
||||||
|
@ -15,7 +15,6 @@ import kotlin.reflect.KProperty
|
|||||||
public typealias MutableItemDelegate = ReadWriteProperty<Any?, MetaItem<*>?>
|
public typealias MutableItemDelegate = ReadWriteProperty<Any?, MetaItem<*>?>
|
||||||
|
|
||||||
public fun MutableItemProvider.item(key: Name? = null): MutableItemDelegate = object : MutableItemDelegate {
|
public fun MutableItemProvider.item(key: Name? = null): MutableItemDelegate = object : MutableItemDelegate {
|
||||||
|
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): MetaItem<*>? {
|
override fun getValue(thisRef: Any?, property: KProperty<*>): MetaItem<*>? {
|
||||||
return getItem(key ?: property.name.asName())
|
return getItem(key ?: property.name.asName())
|
||||||
}
|
}
|
||||||
@ -24,7 +23,6 @@ public fun MutableItemProvider.item(key: Name? = null): MutableItemDelegate = ob
|
|||||||
val name = key ?: property.name.asName()
|
val name = key ?: property.name.asName()
|
||||||
setItem(name, value)
|
setItem(name, value)
|
||||||
}
|
}
|
||||||
//MutableItemDelegate(this, key)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Mutable converters */
|
/* Mutable converters */
|
||||||
@ -111,7 +109,10 @@ public fun MutableItemProvider.boolean(key: Name? = null, default: () -> Boolean
|
|||||||
public fun MutableItemProvider.number(key: Name? = null, default: () -> Number): ReadWriteProperty<Any?, Number> =
|
public fun MutableItemProvider.number(key: Name? = null, default: () -> Number): ReadWriteProperty<Any?, Number> =
|
||||||
item(key).convert(MetaConverter.number, default)
|
item(key).convert(MetaConverter.number, default)
|
||||||
|
|
||||||
public inline fun <reified E : Enum<E>> MutableItemProvider.enum(default: E, key: Name? = null): ReadWriteProperty<Any?, E> =
|
public inline fun <reified E : Enum<E>> MutableItemProvider.enum(
|
||||||
|
default: E,
|
||||||
|
key: Name? = null,
|
||||||
|
): ReadWriteProperty<Any?, E> =
|
||||||
item(key).convert(MetaConverter.enum()) { default }
|
item(key).convert(MetaConverter.enum()) { default }
|
||||||
|
|
||||||
public inline fun <reified M : MutableMeta<M>> M.node(key: Name? = null): ReadWriteProperty<Any?, M?> =
|
public inline fun <reified M : MutableMeta<M>> M.node(key: Name? = null): ReadWriteProperty<Any?, M?> =
|
||||||
@ -155,14 +156,14 @@ public fun MutableItemProvider.float(default: Float, key: Name? = null): ReadWri
|
|||||||
|
|
||||||
public fun MutableItemProvider.stringList(
|
public fun MutableItemProvider.stringList(
|
||||||
vararg default: String,
|
vararg default: String,
|
||||||
key: Name? = null
|
key: Name? = null,
|
||||||
): ReadWriteProperty<Any?, List<String>> = item(key).convert(
|
): ReadWriteProperty<Any?, List<String>> = item(key).convert(
|
||||||
reader = { it?.stringList ?: listOf(*default) },
|
reader = { it?.stringList ?: listOf(*default) },
|
||||||
writer = { it.map { str -> str.asValue() }.asValue().asMetaItem() }
|
writer = { it.map { str -> str.asValue() }.asValue().asMetaItem() }
|
||||||
)
|
)
|
||||||
|
|
||||||
public fun MutableItemProvider.stringList(
|
public fun MutableItemProvider.stringList(
|
||||||
key: Name? = null
|
key: Name? = null,
|
||||||
): ReadWriteProperty<Any?, List<String>?> = item(key).convert(
|
): ReadWriteProperty<Any?, List<String>?> = item(key).convert(
|
||||||
reader = { it?.stringList },
|
reader = { it?.stringList },
|
||||||
writer = { it?.map { str -> str.asValue() }?.asValue()?.asMetaItem() }
|
writer = { it?.map { str -> str.asValue() }?.asValue()?.asMetaItem() }
|
||||||
@ -170,7 +171,7 @@ public fun MutableItemProvider.stringList(
|
|||||||
|
|
||||||
public fun MutableItemProvider.numberList(
|
public fun MutableItemProvider.numberList(
|
||||||
vararg default: Number,
|
vararg default: Number,
|
||||||
key: Name? = null
|
key: Name? = null,
|
||||||
): ReadWriteProperty<Any?, List<Number>> = item(key).convert(
|
): ReadWriteProperty<Any?, List<Number>> = item(key).convert(
|
||||||
reader = { it?.value?.list?.map { value -> value.number } ?: listOf(*default) },
|
reader = { it?.value?.list?.map { value -> value.number } ?: listOf(*default) },
|
||||||
writer = { it.map { num -> num.asValue() }.asValue().asMetaItem() }
|
writer = { it.map { num -> num.asValue() }.asValue().asMetaItem() }
|
||||||
@ -181,7 +182,7 @@ public fun MutableItemProvider.numberList(
|
|||||||
|
|
||||||
public fun MutableItemProvider.doubleArray(
|
public fun MutableItemProvider.doubleArray(
|
||||||
vararg default: Double,
|
vararg default: Double,
|
||||||
key: Name? = null
|
key: Name? = null,
|
||||||
): ReadWriteProperty<Any?, DoubleArray> = item(key).convert(
|
): ReadWriteProperty<Any?, DoubleArray> = item(key).convert(
|
||||||
reader = { it?.value?.doubleArray ?: doubleArrayOf(*default) },
|
reader = { it?.value?.doubleArray ?: doubleArrayOf(*default) },
|
||||||
writer = { DoubleArrayValue(it).asMetaItem() }
|
writer = { DoubleArrayValue(it).asMetaItem() }
|
||||||
@ -190,5 +191,5 @@ public fun MutableItemProvider.doubleArray(
|
|||||||
public fun <T> MutableItemProvider.listValue(
|
public fun <T> MutableItemProvider.listValue(
|
||||||
key: Name? = null,
|
key: Name? = null,
|
||||||
writer: (T) -> Value = { Value.of(it) },
|
writer: (T) -> Value = { Value.of(it) },
|
||||||
reader: (Value) -> T
|
reader: (Value) -> T,
|
||||||
): ReadWriteProperty<Any?, List<T>?> = item(key).convert(MetaConverter.valueList(writer, reader))
|
): ReadWriteProperty<Any?, List<T>?> = item(key).convert(MetaConverter.valueList(writer, reader))
|
||||||
|
@ -3,11 +3,11 @@ package hep.dataforge.meta
|
|||||||
import hep.dataforge.names.*
|
import hep.dataforge.names.*
|
||||||
import hep.dataforge.values.Value
|
import hep.dataforge.values.Value
|
||||||
|
|
||||||
interface MutableItemProvider : ItemProvider {
|
public interface MutableItemProvider : ItemProvider {
|
||||||
fun setItem(name: Name, item: MetaItem<*>?)
|
public fun setItem(name: Name, item: MetaItem<*>?)
|
||||||
}
|
}
|
||||||
|
|
||||||
interface MutableMeta<out M : MutableMeta<M>> : MetaNode<M>, MutableItemProvider {
|
public interface MutableMeta<out M : MutableMeta<M>> : MetaNode<M>, MutableItemProvider {
|
||||||
override val items: Map<NameToken, MetaItem<M>>
|
override val items: Map<NameToken, MetaItem<M>>
|
||||||
// fun onChange(owner: Any? = null, action: (Name, MetaItem<*>?, MetaItem<*>?) -> Unit)
|
// fun onChange(owner: Any? = null, action: (Name, MetaItem<*>?, MetaItem<*>?) -> Unit)
|
||||||
// fun removeListener(owner: Any? = null)
|
// fun removeListener(owner: Any? = null)
|
||||||
@ -18,7 +18,7 @@ interface MutableMeta<out M : MutableMeta<M>> : MetaNode<M>, MutableItemProvider
|
|||||||
*
|
*
|
||||||
* Changes in Meta are not thread safe.
|
* Changes in Meta are not thread safe.
|
||||||
*/
|
*/
|
||||||
abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(), MutableMeta<M> {
|
public abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(), MutableMeta<M> {
|
||||||
protected val _items: MutableMap<NameToken, MetaItem<M>> = LinkedHashMap()
|
protected val _items: MutableMap<NameToken, MetaItem<M>> = LinkedHashMap()
|
||||||
|
|
||||||
override val items: Map<NameToken, MetaItem<M>>
|
override val items: Map<NameToken, MetaItem<M>>
|
||||||
@ -74,28 +74,28 @@ abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(),
|
|||||||
|
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun MutableMeta<*>.remove(name: Name) = setItem(name, null)
|
public inline fun MutableMeta<*>.remove(name: Name): Unit = setItem(name, null)
|
||||||
|
|
||||||
@Suppress("NOTHING_TO_INLINE")
|
@Suppress("NOTHING_TO_INLINE")
|
||||||
inline fun MutableMeta<*>.remove(name: String) = remove(name.toName())
|
public inline fun MutableMeta<*>.remove(name: String): Unit = remove(name.toName())
|
||||||
|
|
||||||
operator fun MutableMeta<*>.set(name: Name, item: MetaItem<*>?) = setItem(name, item)
|
public operator fun MutableMeta<*>.set(name: Name, item: MetaItem<*>?): Unit = setItem(name, item)
|
||||||
|
|
||||||
fun MutableMeta<*>.setValue(name: Name, value: Value) = setItem(name, MetaItem.ValueItem(value))
|
public fun MutableMeta<*>.setValue(name: Name, value: Value): Unit = setItem(name, MetaItem.ValueItem(value))
|
||||||
|
|
||||||
fun MutableMeta<*>.setValue(name: String, value: Value) = set(name.toName(), value)
|
public fun MutableMeta<*>.setValue(name: String, value: Value): Unit = set(name.toName(), value)
|
||||||
|
|
||||||
fun MutableMeta<*>.setItem(name: String, item: MetaItem<*>?) = setItem(name.toName(), item)
|
public fun MutableMeta<*>.setItem(name: String, item: MetaItem<*>?): Unit = setItem(name.toName(), item)
|
||||||
|
|
||||||
fun MutableMeta<*>.setNode(name: Name, node: Meta) =
|
public fun MutableMeta<*>.setNode(name: Name, node: Meta): Unit =
|
||||||
setItem(name, MetaItem.NodeItem(node))
|
setItem(name, MetaItem.NodeItem(node))
|
||||||
|
|
||||||
fun MutableMeta<*>.setNode(name: String, node: Meta) = setNode(name.toName(), node)
|
public fun MutableMeta<*>.setNode(name: String, node: Meta): Unit = setNode(name.toName(), node)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Universal unsafe set method
|
* Universal unsafe set method
|
||||||
*/
|
*/
|
||||||
operator fun MutableMeta<*>.set(name: Name, value: Any?) {
|
public operator fun MutableMeta<*>.set(name: Name, value: Any?) {
|
||||||
when (value) {
|
when (value) {
|
||||||
null -> remove(name)
|
null -> remove(name)
|
||||||
is MetaItem<*> -> setItem(name, value)
|
is MetaItem<*> -> setItem(name, value)
|
||||||
@ -105,11 +105,14 @@ operator fun MutableMeta<*>.set(name: Name, value: Any?) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun MutableMeta<*>.set(name: NameToken, value: Any?) = set(name.asName(), value)
|
public operator fun MutableMeta<*>.set(name: NameToken, value: Any?): Unit =
|
||||||
|
set(name.asName(), value)
|
||||||
|
|
||||||
operator fun MutableMeta<*>.set(key: String, value: Any?) = set(key.toName(), value)
|
public operator fun MutableMeta<*>.set(key: String, value: Any?): Unit =
|
||||||
|
set(key.toName(), value)
|
||||||
|
|
||||||
operator fun MutableMeta<*>.set(key: String, index: String, value: Any?) = set(key.toName().withIndex(index), value)
|
public operator fun MutableMeta<*>.set(key: String, index: String, value: Any?): Unit =
|
||||||
|
set(key.toName().withIndex(index), value)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update existing mutable node with another node. The rules are following:
|
* Update existing mutable node with another node. The rules are following:
|
||||||
@ -117,7 +120,7 @@ operator fun MutableMeta<*>.set(key: String, index: String, value: Any?) = set(k
|
|||||||
* * node updates node and replaces anything but node
|
* * node updates node and replaces anything but node
|
||||||
* * node list updates node list if number of nodes in the list is the same and replaces anything otherwise
|
* * node list updates node list if number of nodes in the list is the same and replaces anything otherwise
|
||||||
*/
|
*/
|
||||||
fun <M : MutableMeta<M>> M.update(meta: Meta) {
|
public fun <M : MutableMeta<M>> M.update(meta: Meta) {
|
||||||
meta.items.forEach { entry ->
|
meta.items.forEach { entry ->
|
||||||
when (val value = entry.value) {
|
when (val value = entry.value) {
|
||||||
is MetaItem.ValueItem -> setValue(entry.key.asName(), value.value)
|
is MetaItem.ValueItem -> setValue(entry.key.asName(), value.value)
|
||||||
@ -129,7 +132,7 @@ fun <M : MutableMeta<M>> M.update(meta: Meta) {
|
|||||||
|
|
||||||
/* Same name siblings generation */
|
/* Same name siblings generation */
|
||||||
|
|
||||||
fun MutableMeta<*>.setIndexedItems(
|
public fun MutableMeta<*>.setIndexedItems(
|
||||||
name: Name,
|
name: Name,
|
||||||
items: Iterable<MetaItem<*>>,
|
items: Iterable<MetaItem<*>>,
|
||||||
indexFactory: (MetaItem<*>, index: Int) -> String = { _, index -> index.toString() }
|
indexFactory: (MetaItem<*>, index: Int) -> String = { _, index -> index.toString() }
|
||||||
@ -143,7 +146,7 @@ fun MutableMeta<*>.setIndexedItems(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun MutableMeta<*>.setIndexed(
|
public fun MutableMeta<*>.setIndexed(
|
||||||
name: Name,
|
name: Name,
|
||||||
metas: Iterable<Meta>,
|
metas: Iterable<Meta>,
|
||||||
indexFactory: (Meta, index: Int) -> String = { _, index -> index.toString() }
|
indexFactory: (Meta, index: Int) -> String = { _, index -> index.toString() }
|
||||||
@ -151,13 +154,13 @@ fun MutableMeta<*>.setIndexed(
|
|||||||
setIndexedItems(name, metas.map { MetaItem.NodeItem(it) }) { item, index -> indexFactory(item.node!!, index) }
|
setIndexedItems(name, metas.map { MetaItem.NodeItem(it) }) { item, index -> indexFactory(item.node!!, index) }
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun MutableMeta<*>.set(name: Name, metas: Iterable<Meta>): Unit = setIndexed(name, metas)
|
public operator fun MutableMeta<*>.set(name: Name, metas: Iterable<Meta>): Unit = setIndexed(name, metas)
|
||||||
operator fun MutableMeta<*>.set(name: String, metas: Iterable<Meta>): Unit = setIndexed(name.toName(), metas)
|
public operator fun MutableMeta<*>.set(name: String, metas: Iterable<Meta>): Unit = setIndexed(name.toName(), metas)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append the node with a same-name-sibling, automatically generating numerical index
|
* Append the node with a same-name-sibling, automatically generating numerical index
|
||||||
*/
|
*/
|
||||||
fun <M : MutableMeta<M>> M.append(name: Name, value: Any?) {
|
public fun <M : MutableMeta<M>> M.append(name: Name, value: Any?) {
|
||||||
require(!name.isEmpty()) { "Name could not be empty for append operation" }
|
require(!name.isEmpty()) { "Name could not be empty for append operation" }
|
||||||
val newIndex = name.lastOrNull()!!.index
|
val newIndex = name.lastOrNull()!!.index
|
||||||
if (newIndex != null) {
|
if (newIndex != null) {
|
||||||
@ -168,13 +171,13 @@ fun <M : MutableMeta<M>> M.append(name: Name, value: Any?) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <M : MutableMeta<M>> M.append(name: String, value: Any?) = append(name.toName(), value)
|
public fun <M : MutableMeta<M>> M.append(name: String, value: Any?): Unit = append(name.toName(), value)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply existing node with given [builder] or create a new element with it.
|
* Apply existing node with given [builder] or create a new element with it.
|
||||||
*/
|
*/
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
fun <M : AbstractMutableMeta<M>> M.edit(name: Name, builder: M.() -> Unit) {
|
public fun <M : AbstractMutableMeta<M>> M.edit(name: Name, builder: M.() -> Unit) {
|
||||||
val item = when (val existingItem = get(name)) {
|
val item = when (val existingItem = get(name)) {
|
||||||
null -> empty().also { set(name, it) }
|
null -> empty().also { set(name, it) }
|
||||||
is MetaItem.NodeItem<M> -> existingItem.node
|
is MetaItem.NodeItem<M> -> existingItem.node
|
||||||
|
@ -8,23 +8,21 @@ import hep.dataforge.names.plus
|
|||||||
/**
|
/**
|
||||||
* A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [Specification].
|
* A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [Specification].
|
||||||
*/
|
*/
|
||||||
open class Scheme() : Configurable, Described, MetaRepr {
|
public open class Scheme(
|
||||||
constructor(config: Config, defaultProvider: (Name) -> MetaItem<*>?) : this() {
|
config: Config,
|
||||||
this.config = config
|
defaultProvider: ItemProvider,
|
||||||
this.defaultProvider = defaultProvider
|
) : Configurable, Described, MetaRepr {
|
||||||
}
|
|
||||||
|
|
||||||
//constructor(config: Config, default: Meta) : this(config, { default[it] })
|
override var config: Config = config
|
||||||
constructor(config: Config) : this(config, { null })
|
|
||||||
|
|
||||||
final override var config: Config = Config()
|
|
||||||
internal set
|
internal set
|
||||||
|
|
||||||
var defaultProvider: (Name) -> MetaItem<*>? = { null }
|
public var defaultProvider: ItemProvider = defaultProvider
|
||||||
internal set
|
internal set
|
||||||
|
|
||||||
|
public constructor() : this(Config(), ItemProvider { null })
|
||||||
|
|
||||||
override fun getDefaultItem(name: Name): MetaItem<*>? {
|
override fun getDefaultItem(name: Name): MetaItem<*>? {
|
||||||
return defaultProvider(name) ?: descriptor?.get(name)?.defaultItem()
|
return defaultProvider.getItem(name) ?: descriptor?.get(name)?.defaultItem()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -32,7 +30,7 @@ open class Scheme() : Configurable, Described, MetaRepr {
|
|||||||
* values if default value is unavailable.
|
* values if default value is unavailable.
|
||||||
* Values from [defaultProvider] completely replace
|
* Values from [defaultProvider] completely replace
|
||||||
*/
|
*/
|
||||||
open val defaultLayer: Meta get() = DefaultLayer(Name.EMPTY)
|
public open val defaultLayer: Meta get() = DefaultLayer(Name.EMPTY)
|
||||||
|
|
||||||
override fun toMeta(): Laminate = Laminate(config, defaultLayer)
|
override fun toMeta(): Laminate = Laminate(config, defaultLayer)
|
||||||
|
|
||||||
@ -50,38 +48,45 @@ open class Scheme() : Configurable, Described, MetaRepr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline operator fun <T : Scheme> T.invoke(block: T.() -> Unit) = apply(block)
|
/**
|
||||||
|
* A shortcut to edit a [Scheme] object in-place
|
||||||
|
*/
|
||||||
|
public inline operator fun <T : Scheme> T.invoke(block: T.() -> Unit): T = apply(block)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A specification for simplified generation of wrappers
|
* A specification for simplified generation of wrappers
|
||||||
*/
|
*/
|
||||||
open class SchemeSpec<T : Scheme>(val builder: () -> T) :
|
public open class SchemeSpec<T : Scheme>(
|
||||||
Specification<T> {
|
private val builder: (config: Config, defaultProvider: ItemProvider) -> T,
|
||||||
override fun empty(): T = builder()
|
) : Specification<T> {
|
||||||
|
|
||||||
override fun wrap(config: Config, defaultProvider: (Name) -> MetaItem<*>?): T {
|
public constructor(emptyBuilder: () -> T) : this({ config: Config, defaultProvider: ItemProvider ->
|
||||||
return empty().apply {
|
emptyBuilder().apply {
|
||||||
this.config = config
|
this.config = config
|
||||||
this.defaultProvider = defaultProvider
|
this.defaultProvider = defaultProvider
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
|
||||||
|
override fun empty(): T = builder(Config(), ItemProvider.EMPTY)
|
||||||
|
|
||||||
|
override fun wrap(config: Config, defaultProvider: ItemProvider): T = builder(config, defaultProvider)
|
||||||
|
|
||||||
@Suppress("OVERRIDE_BY_INLINE")
|
@Suppress("OVERRIDE_BY_INLINE")
|
||||||
final override inline operator fun invoke(action: T.() -> Unit) = empty().apply(action)
|
final override inline operator fun invoke(action: T.() -> Unit): T = empty().apply(action)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A scheme that uses [Meta] as a default layer
|
* A scheme that uses [Meta] as a default layer
|
||||||
*/
|
*/
|
||||||
open class MetaScheme(
|
public open class MetaScheme(
|
||||||
val meta: Meta,
|
private val meta: Meta,
|
||||||
override val descriptor: NodeDescriptor? = null,
|
override val descriptor: NodeDescriptor? = null,
|
||||||
config: Config = Config()
|
config: Config = Config(),
|
||||||
) : Scheme(config, meta::get) {
|
) : Scheme(config, meta::get) {
|
||||||
override val defaultLayer: Meta get() = Laminate(meta, descriptor?.defaultItem().node)
|
override val defaultLayer: Meta get() = Laminate(meta, descriptor?.defaultItem().node)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Meta.asScheme() =
|
public fun Meta.asScheme(): MetaScheme = MetaScheme(this)
|
||||||
MetaScheme(this)
|
|
||||||
|
|
||||||
fun <T : Configurable> Meta.toScheme(spec: Specification<T>, block: T.() -> Unit) = spec.wrap(this).apply(block)
|
public fun <T : Configurable> Meta.toScheme(spec: Specification<T>, block: T.() -> Unit): T =
|
||||||
|
spec.wrap(this).apply(block)
|
@ -1,6 +1,5 @@
|
|||||||
package hep.dataforge.meta
|
package hep.dataforge.meta
|
||||||
|
|
||||||
import hep.dataforge.names.Name
|
|
||||||
import kotlin.jvm.JvmName
|
import kotlin.jvm.JvmName
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -8,32 +7,32 @@ import kotlin.jvm.JvmName
|
|||||||
* By convention [Scheme] companion should inherit this class
|
* By convention [Scheme] companion should inherit this class
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
interface Specification<T : Configurable> {
|
public interface Specification<T : Configurable> {
|
||||||
fun empty() = wrap()
|
public fun empty(): T = wrap()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap generic configuration producing instance of desired type
|
* Wrap generic configuration producing instance of desired type
|
||||||
*/
|
*/
|
||||||
fun wrap(config: Config = Config(), defaultProvider: (Name) -> MetaItem<*>? = { null }): T
|
public fun wrap(config: Config = Config(), defaultProvider: ItemProvider = ItemProvider{ null }): T
|
||||||
|
|
||||||
operator fun invoke(action: T.() -> Unit): T = empty().apply(action)
|
public operator fun invoke(action: T.() -> Unit): T = empty().apply(action)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update given configuration using given type as a builder
|
* Update given configuration using given type as a builder
|
||||||
*/
|
*/
|
||||||
fun <T : Configurable> Specification<T>.update(config: Config, action: T.() -> Unit): T = wrap(config).apply(action)
|
public fun <T : Configurable> Specification<T>.update(config: Config, action: T.() -> Unit): T = wrap(config).apply(action)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap a configuration using static meta as default
|
* Wrap a configuration using static meta as default
|
||||||
*/
|
*/
|
||||||
fun <T : Configurable> Specification<T>.wrap(config: Config = Config(), default: Meta = Meta.EMPTY): T =
|
public fun <T : Configurable> Specification<T>.wrap(config: Config = Config(), default: Meta = Meta.EMPTY): T =
|
||||||
wrap(config) { default[it] }
|
wrap(config, default)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap a configuration using static meta as default
|
* Wrap a configuration using static meta as default
|
||||||
*/
|
*/
|
||||||
fun <T : Configurable> Specification<T>.wrap(source: Meta): T {
|
public fun <T : Configurable> Specification<T>.wrap(source: Meta): T {
|
||||||
val default = source.seal()
|
val default = source.seal()
|
||||||
return wrap(source.asConfig(), default)
|
return wrap(source.asConfig(), default)
|
||||||
}
|
}
|
||||||
@ -42,26 +41,26 @@ fun <T : Configurable> Specification<T>.wrap(source: Meta): T {
|
|||||||
/**
|
/**
|
||||||
* Apply specified configuration to configurable
|
* Apply specified configuration to configurable
|
||||||
*/
|
*/
|
||||||
fun <T : Configurable, C : Configurable, S : Specification<C>> T.configure(spec: S, action: C.() -> Unit) =
|
public fun <T : Configurable, C : Configurable, S : Specification<C>> T.configure(spec: S, action: C.() -> Unit): T =
|
||||||
apply { spec.update(config, action) }
|
apply { spec.update(config, action) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update configuration using given specification
|
* Update configuration using given specification
|
||||||
*/
|
*/
|
||||||
fun <C : Configurable, S : Specification<C>> Configurable.update(spec: S, action: C.() -> Unit) =
|
public fun <C : Configurable, S : Specification<C>> Configurable.update(spec: S, action: C.() -> Unit): Configurable =
|
||||||
apply { spec.update(config, action) }
|
apply { spec.update(config, action) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a style based on given specification
|
* Create a style based on given specification
|
||||||
*/
|
*/
|
||||||
fun <C : Configurable, S : Specification<C>> S.createStyle(action: C.() -> Unit): Meta =
|
public fun <C : Configurable, S : Specification<C>> S.createStyle(action: C.() -> Unit): Meta =
|
||||||
Config().also { update(it, action) }
|
Config().also { update(it, action) }
|
||||||
|
|
||||||
fun <T : Configurable> MetaItem<*>.spec(spec: Specification<T>): T? = node?.let {
|
public fun <T : Configurable> MetaItem<*>.spec(spec: Specification<T>): T? = node?.let {
|
||||||
spec.wrap(
|
spec.wrap(
|
||||||
Config(), it
|
Config(), it
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmName("configSpec")
|
@JvmName("configSpec")
|
||||||
fun <T : Configurable> MetaItem<Config>.spec(spec: Specification<T>): T? = node?.let { spec.wrap(it) }
|
public fun <T : Configurable> MetaItem<Config>.spec(spec: Specification<T>): T? = node?.let { spec.wrap(it) }
|
||||||
|
@ -4,8 +4,8 @@ package hep.dataforge.meta
|
|||||||
* General marker for dataforge builders
|
* General marker for dataforge builders
|
||||||
*/
|
*/
|
||||||
@DslMarker
|
@DslMarker
|
||||||
annotation class DFBuilder
|
public annotation class DFBuilder
|
||||||
|
|
||||||
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
|
@RequiresOptIn(level = RequiresOptIn.Level.WARNING)
|
||||||
@Retention(AnnotationRetention.BINARY)
|
@Retention(AnnotationRetention.BINARY)
|
||||||
annotation class DFExperimental
|
public annotation class DFExperimental
|
@ -6,7 +6,7 @@ import hep.dataforge.names.*
|
|||||||
* Get all items matching given name. The index of the last element, if present is used as a [Regex],
|
* Get all items matching given name. The index of the last element, if present is used as a [Regex],
|
||||||
* against which indexes of elements are matched.
|
* against which indexes of elements are matched.
|
||||||
*/
|
*/
|
||||||
fun Meta.getIndexed(name: Name): Map<String?, MetaItem<*>> {
|
public fun Meta.getIndexed(name: Name): Map<String?, MetaItem<*>> {
|
||||||
val root = when (name.length) {
|
val root = when (name.length) {
|
||||||
0 -> error("Can't use empty name for 'getIndexed'")
|
0 -> error("Can't use empty name for 'getIndexed'")
|
||||||
1 -> this
|
1 -> this
|
||||||
@ -18,19 +18,19 @@ fun Meta.getIndexed(name: Name): Map<String?, MetaItem<*>> {
|
|||||||
root.items.filter { it.key.body == body }.mapKeys { it.key.index }
|
root.items.filter { it.key.body == body }.mapKeys { it.key.index }
|
||||||
} else {
|
} else {
|
||||||
val regex = index.toRegex()
|
val regex = index.toRegex()
|
||||||
root.items
|
root.items.filter { it.key.body == body && (regex.matches(it.key.index ?: "")) }
|
||||||
.filter { it.key.body == body && (regex.matches(it.key.index ?: "")) }
|
|
||||||
.mapKeys { it.key.index }
|
.mapKeys { it.key.index }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Meta.getIndexed(name: String): Map<String?, MetaItem<*>> = this@getIndexed.getIndexed(name.toName())
|
public fun Meta.getIndexed(name: String): Map<String?, MetaItem<*>> = this@getIndexed.getIndexed(name.toName())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get all items matching given name.
|
* Get all items matching given name.
|
||||||
*/
|
*/
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun <M : MetaNode<M>> M.getIndexed(name: Name): Map<String, MetaItem<M>> =
|
public fun <M : MetaNode<M>> M.getIndexed(name: Name): Map<String, MetaItem<M>> =
|
||||||
(this as Meta).getIndexed(name) as Map<String, MetaItem<M>>
|
(this as Meta).getIndexed(name) as Map<String, MetaItem<M>>
|
||||||
|
|
||||||
fun <M : MetaNode<M>> M.getIndexed(name: String): Map<String, MetaItem<M>> = getIndexed(name.toName())
|
public fun <M : MetaNode<M>> M.getIndexed(name: String): Map<String, MetaItem<M>> =
|
||||||
|
getIndexed(name.toName())
|
@ -8,7 +8,7 @@ import hep.dataforge.values.Value
|
|||||||
/**
|
/**
|
||||||
* Convert meta to map of maps
|
* Convert meta to map of maps
|
||||||
*/
|
*/
|
||||||
fun Meta.toMap(descriptor: NodeDescriptor? = null): Map<String, Any?> {
|
public fun Meta.toMap(descriptor: NodeDescriptor? = null): Map<String, Any?> {
|
||||||
return items.entries.associate { (token, item) ->
|
return items.entries.associate { (token, item) ->
|
||||||
token.toString() to when (item) {
|
token.toString() to when (item) {
|
||||||
is MetaItem.NodeItem -> item.node.toMap()
|
is MetaItem.NodeItem -> item.node.toMap()
|
||||||
@ -22,7 +22,7 @@ fun Meta.toMap(descriptor: NodeDescriptor? = null): Map<String, Any?> {
|
|||||||
* All other values will be converted to values.
|
* All other values will be converted to values.
|
||||||
*/
|
*/
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
fun Map<String, Any?>.toMeta(descriptor: NodeDescriptor? = null): Meta = Meta {
|
public fun Map<String, Any?>.toMeta(descriptor: NodeDescriptor? = null): Meta = Meta {
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun toItem(value: Any?): MetaItem<*> = when (value) {
|
fun toItem(value: Any?): MetaItem<*> = when (value) {
|
||||||
is MetaItem<*> -> value
|
is MetaItem<*> -> value
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
package hep.dataforge.meta
|
|
||||||
|
|
||||||
import kotlinx.serialization.InternalSerializationApi
|
|
||||||
import kotlinx.serialization.builtins.DoubleArraySerializer
|
|
||||||
import kotlinx.serialization.builtins.serializer
|
|
||||||
import kotlinx.serialization.descriptors.*
|
|
||||||
import kotlinx.serialization.encoding.CompositeDecoder
|
|
||||||
import kotlinx.serialization.encoding.CompositeEncoder
|
|
||||||
import kotlinx.serialization.encoding.Decoder
|
|
||||||
import kotlinx.serialization.encoding.Encoder
|
|
||||||
import kotlinx.serialization.json.Json
|
|
||||||
|
|
||||||
fun ClassSerialDescriptorBuilder.boolean(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
|
|
||||||
element(name, Boolean.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
|
|
||||||
|
|
||||||
fun ClassSerialDescriptorBuilder.string(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
|
|
||||||
element(name, String.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
|
|
||||||
|
|
||||||
fun ClassSerialDescriptorBuilder.int(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
|
|
||||||
element(name, Int.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
|
|
||||||
|
|
||||||
fun ClassSerialDescriptorBuilder.double(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
|
|
||||||
element(name, Double.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
|
|
||||||
|
|
||||||
fun ClassSerialDescriptorBuilder.float(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
|
|
||||||
element(name, Float.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
|
|
||||||
|
|
||||||
fun ClassSerialDescriptorBuilder.long(name: String, isOptional: Boolean = false, vararg annotations: Annotation) =
|
|
||||||
element(name, Long.serializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
|
|
||||||
|
|
||||||
fun ClassSerialDescriptorBuilder.doubleArray(
|
|
||||||
name: String,
|
|
||||||
isOptional: Boolean = false,
|
|
||||||
vararg annotations: Annotation,
|
|
||||||
) =
|
|
||||||
element(name, DoubleArraySerializer().descriptor, isOptional = isOptional, annotations = annotations.toList())
|
|
||||||
|
|
||||||
@OptIn(InternalSerializationApi::class)
|
|
||||||
inline fun <reified E : Enum<E>> ClassSerialDescriptorBuilder.enum(
|
|
||||||
name: String,
|
|
||||||
isOptional: Boolean = false,
|
|
||||||
vararg annotations: Annotation,
|
|
||||||
) {
|
|
||||||
val enumDescriptor = buildSerialDescriptor(serialName, SerialKind.ENUM) {
|
|
||||||
enumValues<E>().forEach {
|
|
||||||
val fqn = "$serialName.${it.name}"
|
|
||||||
val enumMemberDescriptor = buildSerialDescriptor(fqn, StructureKind.OBJECT)
|
|
||||||
element(it.name, enumMemberDescriptor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
element(name, enumDescriptor, isOptional = isOptional, annotations = annotations.toList())
|
|
||||||
}
|
|
||||||
|
|
||||||
@DFExperimental
|
|
||||||
inline fun <R> Decoder.decodeStructure(
|
|
||||||
desc: SerialDescriptor,
|
|
||||||
crossinline block: CompositeDecoder.() -> R,
|
|
||||||
): R {
|
|
||||||
val decoder = beginStructure(desc)
|
|
||||||
val res = decoder.block()
|
|
||||||
decoder.endStructure(desc)
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
|
|
||||||
@DFExperimental
|
|
||||||
inline fun Encoder.encodeStructure(
|
|
||||||
desc: SerialDescriptor,
|
|
||||||
block: CompositeEncoder.() -> Unit,
|
|
||||||
) {
|
|
||||||
val encoder = beginStructure(desc)
|
|
||||||
encoder.block()
|
|
||||||
encoder.endStructure(desc)
|
|
||||||
}
|
|
||||||
|
|
||||||
val JSON_PRETTY = Json { prettyPrint = true; useArrayPolymorphism = true }
|
|
||||||
val JSON_PLAIN = Json { prettyPrint = false; useArrayPolymorphism = true }
|
|
@ -10,7 +10,7 @@ import kotlinx.serialization.Serializable
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
enum class ValueType {
|
public enum class ValueType {
|
||||||
NUMBER, STRING, BOOLEAN, NULL
|
NUMBER, STRING, BOOLEAN, NULL
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -19,44 +19,44 @@ enum class ValueType {
|
|||||||
*
|
*
|
||||||
* Value can represent a list of value objects.
|
* Value can represent a list of value objects.
|
||||||
*/
|
*/
|
||||||
interface Value {
|
@Serializable(ValueSerializer::class)
|
||||||
|
public interface Value {
|
||||||
/**
|
/**
|
||||||
* Get raw value of this value
|
* Get raw value of this value
|
||||||
*/
|
*/
|
||||||
val value: Any?
|
public val value: Any?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the value
|
* The type of the value
|
||||||
*/
|
*/
|
||||||
val type: ValueType
|
public val type: ValueType
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get this value represented as Number
|
* get this value represented as Number
|
||||||
*/
|
*/
|
||||||
val number: Number
|
public val number: Number
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get this value represented as String
|
* get this value represented as String
|
||||||
*/
|
*/
|
||||||
val string: String
|
public val string: String
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* get this value represented as List
|
* get this value represented as List
|
||||||
*/
|
*/
|
||||||
val list: List<Value>
|
public val list: List<Value> get() = if (this == Null) emptyList() else listOf(this)
|
||||||
get() = if (this == Null) emptyList() else listOf(this)
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean
|
override fun equals(other: Any?): Boolean
|
||||||
|
|
||||||
override fun hashCode(): Int
|
override fun hashCode(): Int
|
||||||
|
|
||||||
companion object {
|
public companion object {
|
||||||
const val TYPE = "value"
|
public const val TYPE: String = "value"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert object to value
|
* Convert object to value
|
||||||
*/
|
*/
|
||||||
fun of(value: Any?): Value {
|
public fun of(value: Any?): Value {
|
||||||
return when (value) {
|
return when (value) {
|
||||||
null -> Null
|
null -> Null
|
||||||
is Value -> value
|
is Value -> value
|
||||||
@ -89,7 +89,7 @@ interface Value {
|
|||||||
/**
|
/**
|
||||||
* A singleton null value
|
* A singleton null value
|
||||||
*/
|
*/
|
||||||
object Null : Value {
|
public object Null : Value {
|
||||||
override val value: Any? get() = null
|
override val value: Any? get() = null
|
||||||
override val type: ValueType get() = ValueType.NULL
|
override val type: ValueType get() = ValueType.NULL
|
||||||
override val number: Number get() = Double.NaN
|
override val number: Number get() = Double.NaN
|
||||||
@ -104,7 +104,7 @@ object Null : Value {
|
|||||||
/**
|
/**
|
||||||
* Singleton true value
|
* Singleton true value
|
||||||
*/
|
*/
|
||||||
object True : Value {
|
public object True : Value {
|
||||||
override val value: Any? get() = true
|
override val value: Any? get() = true
|
||||||
override val type: ValueType get() = ValueType.BOOLEAN
|
override val type: ValueType get() = ValueType.BOOLEAN
|
||||||
override val number: Number get() = 1.0
|
override val number: Number get() = 1.0
|
||||||
@ -119,7 +119,7 @@ object True : Value {
|
|||||||
/**
|
/**
|
||||||
* Singleton false value
|
* Singleton false value
|
||||||
*/
|
*/
|
||||||
object False : Value {
|
public object False : Value {
|
||||||
override val value: Any? get() = false
|
override val value: Any? get() = false
|
||||||
override val type: ValueType get() = ValueType.BOOLEAN
|
override val type: ValueType get() = ValueType.BOOLEAN
|
||||||
override val number: Number get() = -1.0
|
override val number: Number get() = -1.0
|
||||||
@ -131,7 +131,7 @@ object False : Value {
|
|||||||
override fun hashCode(): Int = -1
|
override fun hashCode(): Int = -1
|
||||||
}
|
}
|
||||||
|
|
||||||
class NumberValue(override val number: Number) : Value {
|
public class NumberValue(override val number: Number) : Value {
|
||||||
override val value: Any? get() = number
|
override val value: Any? get() = number
|
||||||
override val type: ValueType get() = ValueType.NUMBER
|
override val type: ValueType get() = ValueType.NUMBER
|
||||||
override val string: String get() = number.toString()
|
override val string: String get() = number.toString()
|
||||||
@ -154,7 +154,7 @@ class NumberValue(override val number: Number) : Value {
|
|||||||
override fun toString(): String = value.toString()
|
override fun toString(): String = value.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
class StringValue(override val string: String) : Value {
|
public class StringValue(override val string: String) : Value {
|
||||||
override val value: Any? get() = string
|
override val value: Any? get() = string
|
||||||
override val type: ValueType get() = ValueType.STRING
|
override val type: ValueType get() = ValueType.STRING
|
||||||
override val number: Number get() = string.toDouble()
|
override val number: Number get() = string.toDouble()
|
||||||
@ -168,7 +168,7 @@ class StringValue(override val string: String) : Value {
|
|||||||
override fun toString(): String = "\"${value.toString()}\""
|
override fun toString(): String = "\"${value.toString()}\""
|
||||||
}
|
}
|
||||||
|
|
||||||
class EnumValue<E : Enum<*>>(override val value: E) : Value {
|
public class EnumValue<E : Enum<*>>(override val value: E) : Value {
|
||||||
override val type: ValueType get() = ValueType.STRING
|
override val type: ValueType get() = ValueType.STRING
|
||||||
override val number: Number get() = value.ordinal
|
override val number: Number get() = value.ordinal
|
||||||
override val string: String get() = value.name
|
override val string: String get() = value.name
|
||||||
@ -182,7 +182,7 @@ class EnumValue<E : Enum<*>>(override val value: E) : Value {
|
|||||||
override fun toString(): String = value.toString()
|
override fun toString(): String = value.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
class ListValue(override val list: List<Value>) : Value {
|
public class ListValue(override val list: List<Value>) : Value {
|
||||||
init {
|
init {
|
||||||
require(list.isNotEmpty()) { "Can't create list value from empty list" }
|
require(list.isNotEmpty()) { "Can't create list value from empty list" }
|
||||||
}
|
}
|
||||||
@ -210,34 +210,34 @@ class ListValue(override val list: List<Value>) : Value {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Number.asValue(): Value = NumberValue(this)
|
public fun Number.asValue(): Value = NumberValue(this)
|
||||||
|
|
||||||
fun Boolean.asValue(): Value = if (this) True else False
|
public fun Boolean.asValue(): Value = if (this) True else False
|
||||||
|
|
||||||
fun String.asValue(): Value = StringValue(this)
|
public fun String.asValue(): Value = StringValue(this)
|
||||||
|
|
||||||
fun Iterable<Value>.asValue(): Value {
|
public fun Iterable<Value>.asValue(): Value {
|
||||||
val list = toList()
|
val list = toList()
|
||||||
return if (list.isEmpty()) Null else ListValue(this.toList())
|
return if (list.isEmpty()) Null else ListValue(this.toList())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun IntArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
|
public fun IntArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
|
||||||
|
|
||||||
fun LongArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
|
public fun LongArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
|
||||||
|
|
||||||
fun ShortArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
|
public fun ShortArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
|
||||||
|
|
||||||
fun FloatArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
|
public fun FloatArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
|
||||||
|
|
||||||
fun ByteArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
|
public fun ByteArray.asValue(): Value = if (isEmpty()) Null else ListValue(map { NumberValue(it) })
|
||||||
|
|
||||||
fun <E : Enum<E>> E.asValue(): Value = EnumValue(this)
|
public fun <E : Enum<E>> E.asValue(): Value = EnumValue(this)
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create Value from String using closest match conversion
|
* Create Value from String using closest match conversion
|
||||||
*/
|
*/
|
||||||
fun String.parseValue(): Value {
|
public fun String.parseValue(): Value {
|
||||||
|
|
||||||
//Trying to get integer
|
//Trying to get integer
|
||||||
if (isEmpty() || this == Null.string) {
|
if (isEmpty() || this == Null.string) {
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
package hep.dataforge.values
|
package hep.dataforge.values
|
||||||
|
|
||||||
import hep.dataforge.meta.boolean
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import hep.dataforge.meta.enum
|
|
||||||
import hep.dataforge.meta.string
|
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.Serializer
|
import kotlinx.serialization.Serializer
|
||||||
import kotlinx.serialization.builtins.ListSerializer
|
import kotlinx.serialization.builtins.ListSerializer
|
||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
|
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
|
||||||
|
import kotlinx.serialization.descriptors.element
|
||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.Decoder
|
||||||
import kotlinx.serialization.encoding.Encoder
|
import kotlinx.serialization.encoding.Encoder
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
@Serializer(Value::class)
|
@Serializer(Value::class)
|
||||||
object ValueSerializer : KSerializer<Value> {
|
public object ValueSerializer : KSerializer<Value> {
|
||||||
private val listSerializer by lazy { ListSerializer(ValueSerializer) }
|
private val listSerializer by lazy { ListSerializer(ValueSerializer) }
|
||||||
|
|
||||||
override val descriptor: SerialDescriptor =
|
override val descriptor: SerialDescriptor =
|
||||||
buildClassSerialDescriptor("hep.dataforge.values.Value") {
|
buildClassSerialDescriptor("hep.dataforge.values.Value") {
|
||||||
boolean("isList")
|
element<Boolean>("isList")
|
||||||
enum<ValueType>("valueType")
|
element<ValueType>("valueType")
|
||||||
string("value")
|
element<String>("value")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Decoder.decodeValue(): Value {
|
private fun Decoder.decodeValue(): Value {
|
||||||
|
@ -4,7 +4,7 @@ package hep.dataforge.values
|
|||||||
/**
|
/**
|
||||||
* A value built from string which content and type are parsed on-demand
|
* A value built from string which content and type are parsed on-demand
|
||||||
*/
|
*/
|
||||||
class LazyParsedValue(override val string: String) : Value {
|
public class LazyParsedValue(override val string: String) : Value {
|
||||||
private val parsedValue by lazy { string.parseValue() }
|
private val parsedValue by lazy { string.parseValue() }
|
||||||
|
|
||||||
override val value: Any? get() = parsedValue.value
|
override val value: Any? get() = parsedValue.value
|
||||||
@ -18,12 +18,12 @@ class LazyParsedValue(override val string: String) : Value {
|
|||||||
override fun hashCode(): Int = string.hashCode()
|
override fun hashCode(): Int = string.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun String.lazyParseValue(): LazyParsedValue = LazyParsedValue(this)
|
public fun String.lazyParseValue(): LazyParsedValue = LazyParsedValue(this)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A performance optimized version of list value for doubles
|
* A performance optimized version of list value for doubles
|
||||||
*/
|
*/
|
||||||
class DoubleArrayValue(override val value: DoubleArray) : Value {
|
public class DoubleArrayValue(override val value: DoubleArray) : Value {
|
||||||
override val type: ValueType get() = ValueType.NUMBER
|
override val type: ValueType get() = ValueType.NUMBER
|
||||||
override val number: Double get() = value.first()
|
override val number: Double get() = value.first()
|
||||||
override val string: String get() = value.first().toString()
|
override val string: String get() = value.first().toString()
|
||||||
@ -46,4 +46,4 @@ class DoubleArrayValue(override val value: DoubleArray) : Value {
|
|||||||
override fun toString(): String = list.joinToString (prefix = "[", postfix = "]")
|
override fun toString(): String = list.joinToString (prefix = "[", postfix = "]")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun DoubleArray.asValue(): Value = if(isEmpty()) Null else DoubleArrayValue(this)
|
public fun DoubleArray.asValue(): Value = if(isEmpty()) Null else DoubleArrayValue(this)
|
||||||
|
@ -1,32 +1,33 @@
|
|||||||
package hep.dataforge.values
|
package hep.dataforge.values
|
||||||
|
|
||||||
import hep.dataforge.meta.Meta
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.meta.MetaBuilder
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if value is null
|
* Check if value is null
|
||||||
*/
|
*/
|
||||||
fun Value.isNull(): Boolean = this == Null
|
public fun Value.isNull(): Boolean = this == Null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if value is list
|
* Check if value is list
|
||||||
*/
|
*/
|
||||||
fun Value.isList(): Boolean = this.list.size > 1
|
public fun Value.isList(): Boolean = this.list.size > 1
|
||||||
|
|
||||||
val Value.boolean
|
public val Value.boolean
|
||||||
get() = this == True
|
get() = this == True
|
||||||
|| this.list.firstOrNull() == True
|
|| this.list.firstOrNull() == True
|
||||||
|| (type == ValueType.STRING && string.toBoolean())
|
|| (type == ValueType.STRING && string.toBoolean())
|
||||||
|
|
||||||
|
|
||||||
val Value.int get() = number.toInt()
|
public val Value.int: Int get() = number.toInt()
|
||||||
val Value.double get() = number.toDouble()
|
public val Value.double: Double get() = number.toDouble()
|
||||||
val Value.float get() = number.toFloat()
|
public val Value.float: Float get() = number.toFloat()
|
||||||
val Value.short get() = number.toShort()
|
public val Value.short: Short get() = number.toShort()
|
||||||
val Value.long get() = number.toLong()
|
public val Value.long: Long get() = number.toLong()
|
||||||
|
|
||||||
val Value.stringList: List<String> get() = list.map { it.string }
|
public val Value.stringList: List<String> get() = list.map { it.string }
|
||||||
|
|
||||||
val Value.doubleArray: DoubleArray
|
public val Value.doubleArray: DoubleArray
|
||||||
get() = if (this is DoubleArrayValue) {
|
get() = if (this is DoubleArrayValue) {
|
||||||
value
|
value
|
||||||
} else {
|
} else {
|
||||||
@ -34,4 +35,4 @@ val Value.doubleArray: DoubleArray
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun Value.toMeta() = Meta { Meta.VALUE_KEY put this }
|
public fun Value.toMeta(): MetaBuilder = Meta { Meta.VALUE_KEY put this }
|
@ -1,18 +1,17 @@
|
|||||||
package hep.dataforge.meta
|
package hep.dataforge.meta
|
||||||
|
|
||||||
import hep.dataforge.names.Name
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
class SpecificationTest {
|
class SpecificationTest {
|
||||||
class TestStyled(config: Config, defaultProvider: (Name) -> MetaItem<*>?) :
|
class TestStyled(config: Config, defaultProvider: ItemProvider) :
|
||||||
Scheme(config, defaultProvider) {
|
Scheme(config, defaultProvider) {
|
||||||
var list by numberList(1, 2, 3)
|
var list by numberList(1, 2, 3)
|
||||||
|
|
||||||
companion object : Specification<TestStyled> {
|
companion object : Specification<TestStyled> {
|
||||||
override fun wrap(
|
override fun wrap(
|
||||||
config: Config,
|
config: Config,
|
||||||
defaultProvider: (Name) -> MetaItem<*>?
|
defaultProvider: ItemProvider
|
||||||
): TestStyled = TestStyled(config, defaultProvider)
|
): TestStyled = TestStyled(config, defaultProvider)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
package hep.dataforge.meta
|
||||||
|
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
|
||||||
|
public val JSON_PRETTY: Json = Json { prettyPrint = true; useArrayPolymorphism = true }
|
||||||
|
public val JSON_PLAIN: Json = Json { prettyPrint = false; useArrayPolymorphism = true }
|
Loading…
Reference in New Issue
Block a user