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
}
val dataforgeVersion by extra("0.1.6-dev-1")
val dataforgeVersion by extra("0.1.6-dev-2")
val bintrayRepo by extra("dataforge")
val githubProject by extra("dataforge-core")

View File

@ -34,7 +34,7 @@ class YamlMetaFormatTest {
assertEquals<Meta>(meta, meta.seal())
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)

View File

@ -1,8 +1,8 @@
@file:Suppress("UNUSED_PARAMETER")
package hep.dataforge.meta
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.names.toName
import hep.dataforge.values.ListValue
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 {
@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) ->
@Suppress("UNCHECKED_CAST")
when (value) {
is Map<*, *> -> setNode(key, (value as Map<String, Any?>).toMeta())
else -> setValue(key, Value.of(value))
if (value is List<*>) {
val items = value.map { toItem(it) }
if (items.all { it is MetaItem.ValueItem }) {
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 }
/**
* 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
}
@ -89,7 +89,7 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
/**
* Produce new meta using only those items that match transformation rules
*/
fun transform(source: Meta): Meta =
fun generate(source: Meta): Meta =
Meta {
transformations.forEach { rule ->
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
*/

View File

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