Add a Config generator to MetaTransformation

This commit is contained in:
Alexander Nozik 2020-03-28 21:23:44 +03:00
parent 01711c2b8c
commit 56e7d55450
5 changed files with 41 additions and 11 deletions

View File

@ -6,7 +6,7 @@ plugins {
id("scientifik.publish") version toolsVersion apply false id("scientifik.publish") version toolsVersion apply false
} }
val dataforgeVersion by extra("0.1.6-dev-1") val dataforgeVersion by extra("0.1.6-dev-2")
val bintrayRepo by extra("dataforge") val bintrayRepo by extra("dataforge")
val githubProject by extra("dataforge-core") val githubProject by extra("dataforge-core")

View File

@ -34,7 +34,7 @@ class YamlMetaFormatTest {
assertEquals<Meta>(meta, meta.seal()) assertEquals<Meta>(meta, meta.seal())
meta.items.keys.forEach { meta.items.keys.forEach {
if (meta[it] != result[it]) error("${meta[it]} != ${result[it]}") assertEquals(meta[it],result[it],"${meta[it]} != ${result[it]}")
} }
assertEquals(meta, result) assertEquals(meta, result)

View File

@ -1,8 +1,8 @@
@file:Suppress("UNUSED_PARAMETER")
package hep.dataforge.meta package hep.dataforge.meta
import hep.dataforge.meta.descriptors.NodeDescriptor import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.names.toName
import hep.dataforge.values.ListValue
import hep.dataforge.values.Value import hep.dataforge.values.Value
/** /**
@ -18,14 +18,29 @@ fun Meta.toMap(descriptor: NodeDescriptor? = null): Map<String, Any?> {
} }
/** /**
* Convert map of maps to meta * Convert map of maps to meta. This method will recognize [MetaItem], [Map]<String,Any?> and [List] of all mentioned above as value.
* All other values will be converted to values.
*/ */
@DFExperimental
fun Map<String, Any?>.toMeta(descriptor: NodeDescriptor? = null): Meta = Meta { fun Map<String, Any?>.toMeta(descriptor: NodeDescriptor? = null): Meta = Meta {
@Suppress("UNCHECKED_CAST")
fun toItem(value: Any?): MetaItem<*> = when (value) {
is MetaItem<*> -> value
is Meta -> MetaItem.NodeItem(value)
is Map<*, *> -> MetaItem.NodeItem((value as Map<String, Any?>).toMeta())
else -> MetaItem.ValueItem(Value.of(value))
}
entries.forEach { (key, value) -> entries.forEach { (key, value) ->
@Suppress("UNCHECKED_CAST") if (value is List<*>) {
when (value) { val items = value.map { toItem(it) }
is Map<*, *> -> setNode(key, (value as Map<String, Any?>).toMeta()) if (items.all { it is MetaItem.ValueItem }) {
else -> setValue(key, Value.of(value)) setValue(key, ListValue(items.map { it.value!! }))
} else {
setIndexedItems(key.toName(), value.map { toItem(it) })
}
} else {
setItem(key, toItem(value))
} }
} }
} }

View File

@ -22,7 +22,7 @@ interface TransformationRule {
meta.sequence().filter { matches(it.first, it.second) }.map { it.first } meta.sequence().filter { matches(it.first, it.second) }.map { it.first }
/** /**
* Apply transformation for a single item (Node or Value) and return resulting tree with absolute path * Apply transformation for a single item (Node or Value) to the target
*/ */
fun <M : MutableMeta<M>> transformItem(name: Name, item: MetaItem<*>?, target: M): Unit fun <M : MutableMeta<M>> transformItem(name: Name, item: MetaItem<*>?, target: M): Unit
} }
@ -89,7 +89,7 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
/** /**
* Produce new meta using only those items that match transformation rules * Produce new meta using only those items that match transformation rules
*/ */
fun transform(source: Meta): Meta = fun generate(source: Meta): Meta =
Meta { Meta {
transformations.forEach { rule -> transformations.forEach { rule ->
rule.selectItems(source).forEach { name -> rule.selectItems(source).forEach { name ->
@ -98,6 +98,20 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
} }
} }
/**
* Generate an observable configuration that contains only elements defined by transformation rules and changes with the source
*/
@DFExperimental
fun generate(source: Config): ObservableMeta = Config().apply {
transformations.forEach { rule ->
rule.selectItems(source).forEach { name ->
rule.transformItem(name, source[name], this)
}
}
bind(source, this)
}
/** /**
* Transform a meta, replacing all elements found in rules with transformed entries * Transform a meta, replacing all elements found in rules with transformed entries
*/ */

View File

@ -31,6 +31,7 @@ class MetaTest {
assertEquals<Meta>(meta1, meta2) assertEquals<Meta>(meta1, meta2)
} }
@OptIn(DFExperimental::class)
@Test @Test
fun metaToMap() { fun metaToMap() {
val meta = Meta { val meta = Meta {