Transformation of Meta to Map and back
This commit is contained in:
parent
d3dd15884c
commit
cd4736ab5e
@ -1,9 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id("scientifik.jvm")
|
|
||||||
}
|
|
||||||
|
|
||||||
description = "YAML meta IO"
|
|
||||||
|
|
||||||
dependencies{
|
|
||||||
api(project(":dataforge-io"))
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package hep.dataforge.meta
|
|
||||||
|
|
||||||
/**
|
|
||||||
* General marker for dataforge builders
|
|
||||||
*/
|
|
||||||
@DslMarker
|
|
||||||
annotation class DFBuilder
|
|
@ -4,8 +4,6 @@ import hep.dataforge.names.NameToken
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A meta laminate consisting of multiple immutable meta layers. For mutable front layer, use [Styled].
|
* A meta laminate consisting of multiple immutable meta layers. For mutable front layer, use [Styled].
|
||||||
*
|
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
class Laminate(layers: List<Meta>) : MetaBase() {
|
class Laminate(layers: List<Meta>) : MetaBase() {
|
||||||
|
|
||||||
|
@ -80,27 +80,6 @@ operator fun Meta?.get(name: Name): MetaItem<*>? {
|
|||||||
operator fun Meta?.get(token: NameToken): MetaItem<*>? = this?.items?.get(token)
|
operator fun Meta?.get(token: NameToken): MetaItem<*>? = this?.items?.get(token)
|
||||||
operator fun Meta?.get(key: String): MetaItem<*>? = get(key.toName())
|
operator fun Meta?.get(key: String): MetaItem<*>? = get(key.toName())
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all items matching given name.
|
|
||||||
*/
|
|
||||||
fun Meta.getAll(name: Name): Map<String, MetaItem<*>> {
|
|
||||||
val root = when (name.length) {
|
|
||||||
0 -> error("Can't use empty name for that")
|
|
||||||
1 -> this
|
|
||||||
else -> (this[name.cutLast()] as? NodeItem<*>)?.node
|
|
||||||
}
|
|
||||||
|
|
||||||
val (body, index) = name.last()!!
|
|
||||||
val regex = index.toRegex()
|
|
||||||
|
|
||||||
return root?.items
|
|
||||||
?.filter { it.key.body == body && (index.isEmpty() || regex.matches(it.key.index)) }
|
|
||||||
?.mapKeys { it.key.index }
|
|
||||||
?: emptyMap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Meta.getAll(name: String): Map<String, MetaItem<*>> = getAll(name.toName())
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a sequence of [Name]-[Value] pairs
|
* Get a sequence of [Name]-[Value] pairs
|
||||||
*/
|
*/
|
||||||
@ -138,27 +117,6 @@ interface MetaNode<M : MetaNode<M>> : Meta {
|
|||||||
override val items: Map<NameToken, MetaItem<M>>
|
override val items: Map<NameToken, MetaItem<M>>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get all items matching given name.
|
|
||||||
*/
|
|
||||||
fun <M : MetaNode<M>> M.getAll(name: Name): Map<String, MetaItem<M>> {
|
|
||||||
val root: MetaNode<M>? = when (name.length) {
|
|
||||||
0 -> error("Can't use empty name for that")
|
|
||||||
1 -> this
|
|
||||||
else -> (this[name.cutLast()] as? NodeItem<M>)?.node
|
|
||||||
}
|
|
||||||
|
|
||||||
val (body, index) = name.last()!!
|
|
||||||
val regex = index.toRegex()
|
|
||||||
|
|
||||||
return root?.items
|
|
||||||
?.filter { it.key.body == body && (index.isEmpty() || regex.matches(it.key.index)) }
|
|
||||||
?.mapKeys { it.key.index }
|
|
||||||
?: emptyMap()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun <M : MetaNode<M>> M.getAll(name: String): Map<String, MetaItem<M>> = getAll(name.toName())
|
|
||||||
|
|
||||||
operator fun <M : MetaNode<M>> MetaNode<M>?.get(name: Name): MetaItem<M>? {
|
operator fun <M : MetaNode<M>> MetaNode<M>?.get(name: Name): MetaItem<M>? {
|
||||||
if (this == null) return null
|
if (this == null) return null
|
||||||
return name.first()?.let { token ->
|
return name.first()?.let { token ->
|
||||||
@ -229,7 +187,6 @@ object EmptyMeta : MetaBase() {
|
|||||||
/**
|
/**
|
||||||
* Unsafe methods to access values and nodes directly from [MetaItem]
|
* Unsafe methods to access values and nodes directly from [MetaItem]
|
||||||
*/
|
*/
|
||||||
|
|
||||||
val MetaItem<*>?.value: Value?
|
val MetaItem<*>?.value: Value?
|
||||||
get() = (this as? ValueItem)?.value
|
get() = (this as? ValueItem)?.value
|
||||||
?: (this?.node?.get(VALUE_KEY) as? ValueItem)?.value
|
?: (this?.node?.get(VALUE_KEY) as? ValueItem)?.value
|
||||||
@ -258,11 +215,4 @@ val <M : Meta> MetaItem<M>?.node: M?
|
|||||||
is NodeItem -> node
|
is NodeItem -> node
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
fun Meta.isEmpty() = this === EmptyMeta || this.items.isEmpty()
|
||||||
* Generic meta-holder object
|
|
||||||
*/
|
|
||||||
interface Metoid {
|
|
||||||
val meta: Meta
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Meta.isEmpty() = this === EmptyMeta || this.items.isEmpty()
|
|
@ -0,0 +1,11 @@
|
|||||||
|
package hep.dataforge.meta
|
||||||
|
|
||||||
|
/**
|
||||||
|
* General marker for dataforge builders
|
||||||
|
*/
|
||||||
|
@DslMarker
|
||||||
|
annotation class DFBuilder
|
||||||
|
|
||||||
|
@Experimental(level = Experimental.Level.WARNING)
|
||||||
|
@Retention(AnnotationRetention.BINARY)
|
||||||
|
annotation class DFExperimental
|
@ -0,0 +1,36 @@
|
|||||||
|
package hep.dataforge.meta
|
||||||
|
|
||||||
|
import hep.dataforge.values.Value
|
||||||
|
|
||||||
|
///**
|
||||||
|
// * Find all elements with given body
|
||||||
|
// */
|
||||||
|
//private fun Meta.byBody(body: String): Map<String, MetaItem<*>> =
|
||||||
|
// items.filter { it.key.body == body }.mapKeys { it.key.index }
|
||||||
|
//
|
||||||
|
//private fun Meta.distinctNames() = items.keys.map { it.body }.distinct()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert meta to map of maps
|
||||||
|
*/
|
||||||
|
fun Meta.toMap(): Map<String, Any?> {
|
||||||
|
return items.entries.associate { (token, item) ->
|
||||||
|
token.toString() to when (item) {
|
||||||
|
is MetaItem.NodeItem -> item.node.toMap()
|
||||||
|
is MetaItem.ValueItem -> item.value.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert map of maps to meta
|
||||||
|
*/
|
||||||
|
fun Map<String, Any?>.toMeta(): Meta = buildMeta {
|
||||||
|
entries.forEach { (key, value) ->
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
when (value) {
|
||||||
|
is Map<*, *> -> setNode(key, (value as Map<String, Any?>).toMeta())
|
||||||
|
else -> setValue(key, Value.of(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -28,15 +28,21 @@ class StringDelegate(val meta: Meta, private val key: String? = null, private va
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class BooleanDelegate(val meta: Meta, private val key: String? = null, private val default: Boolean? = null) :
|
class BooleanDelegate(
|
||||||
ReadOnlyProperty<Metoid, Boolean?> {
|
val meta: Meta,
|
||||||
override fun getValue(thisRef: Metoid, property: KProperty<*>): Boolean? {
|
private val key: String? = null,
|
||||||
|
private val default: Boolean? = null
|
||||||
|
) : ReadOnlyProperty<Any?, Boolean?> {
|
||||||
|
override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean? {
|
||||||
return meta[key ?: property.name]?.boolean ?: default
|
return meta[key ?: property.name]?.boolean ?: default
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class NumberDelegate(val meta: Meta, private val key: String? = null, private val default: Number? = null) :
|
class NumberDelegate(
|
||||||
ReadOnlyProperty<Any?, Number?> {
|
val meta: Meta,
|
||||||
|
private val key: String? = null,
|
||||||
|
private val default: Number? = null
|
||||||
|
) : ReadOnlyProperty<Any?, Number?> {
|
||||||
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
|
||||||
}
|
}
|
||||||
@ -168,9 +174,6 @@ fun Meta.number(key: String? = null, default: () -> Number) =
|
|||||||
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) }
|
||||||
|
|
||||||
|
|
||||||
fun <T : Metoid> Metoid.node(key: String? = null, converter: (Meta) -> T) = ChildDelegate(meta, key, converter)
|
|
||||||
|
|
||||||
/* Read-write delegates */
|
/* Read-write delegates */
|
||||||
|
|
||||||
class MutableValueDelegate<M : MutableMeta<M>>(
|
class MutableValueDelegate<M : MutableMeta<M>>(
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
package hep.dataforge.meta
|
||||||
|
|
||||||
|
import hep.dataforge.names.Name
|
||||||
|
import hep.dataforge.names.toName
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all items matching given name.
|
||||||
|
*/
|
||||||
|
@DFExperimental
|
||||||
|
fun Meta.getAll(name: Name): Map<String, MetaItem<*>> {
|
||||||
|
val root = when (name.length) {
|
||||||
|
0 -> error("Can't use empty name for that")
|
||||||
|
1 -> this
|
||||||
|
else -> (this[name.cutLast()] as? MetaItem.NodeItem<*>)?.node
|
||||||
|
}
|
||||||
|
|
||||||
|
val (body, index) = name.last()!!
|
||||||
|
val regex = index.toRegex()
|
||||||
|
|
||||||
|
return root?.items
|
||||||
|
?.filter { it.key.body == body && (index.isEmpty() || regex.matches(it.key.index)) }
|
||||||
|
?.mapKeys { it.key.index }
|
||||||
|
?: emptyMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
@DFExperimental
|
||||||
|
fun Meta.getAll(name: String): Map<String, MetaItem<*>> = getAll(name.toName())
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all items matching given name.
|
||||||
|
*/
|
||||||
|
@DFExperimental
|
||||||
|
fun <M : MetaNode<M>> M.getAll(name: Name): Map<String, MetaItem<M>> {
|
||||||
|
val root: MetaNode<M>? = when (name.length) {
|
||||||
|
0 -> error("Can't use empty name for that")
|
||||||
|
1 -> this
|
||||||
|
else -> (this[name.cutLast()] as? MetaItem.NodeItem<M>)?.node
|
||||||
|
}
|
||||||
|
|
||||||
|
val (body, index) = name.last()!!
|
||||||
|
val regex = index.toRegex()
|
||||||
|
|
||||||
|
return root?.items
|
||||||
|
?.filter { it.key.body == body && (index.isEmpty() || regex.matches(it.key.index)) }
|
||||||
|
?.mapKeys { it.key.index }
|
||||||
|
?: emptyMap()
|
||||||
|
}
|
||||||
|
|
||||||
|
@DFExperimental
|
||||||
|
fun <M : MetaNode<M>> M.getAll(name: String): Map<String, MetaItem<M>> = getAll(name.toName())
|
@ -30,4 +30,23 @@ class MetaTest {
|
|||||||
}.seal()
|
}.seal()
|
||||||
assertEquals<Meta>(meta1, meta2)
|
assertEquals<Meta>(meta1, meta2)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun metaToMap(){
|
||||||
|
val meta = buildMeta {
|
||||||
|
"a" to 22
|
||||||
|
"b" to {
|
||||||
|
"c" to "ddd"
|
||||||
|
}
|
||||||
|
"list" to (0..4).map {
|
||||||
|
buildMeta {
|
||||||
|
"value" to it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
val map = meta.toMap()
|
||||||
|
val reconstructed = map.toMeta()
|
||||||
|
|
||||||
|
assertEquals(meta,reconstructed)
|
||||||
|
}
|
||||||
}
|
}
|
@ -24,7 +24,6 @@ enableFeaturePreview("GRADLE_METADATA")
|
|||||||
include(
|
include(
|
||||||
":dataforge-meta",
|
":dataforge-meta",
|
||||||
":dataforge-io",
|
":dataforge-io",
|
||||||
":dataforge-io:dataforge-io-yaml",
|
|
||||||
":dataforge-context",
|
":dataforge-context",
|
||||||
":dataforge-data",
|
":dataforge-data",
|
||||||
":dataforge-output",
|
":dataforge-output",
|
||||||
|
Loading…
Reference in New Issue
Block a user