Working on meta transformations
This commit is contained in:
parent
343ba84118
commit
54c7b55bc4
@ -1,4 +1,4 @@
|
||||
val dataforgeVersion by extra("0.1.2")
|
||||
val dataforgeVersion by extra("0.1.3-dev-1")
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
|
@ -94,16 +94,31 @@ fun Meta.getAll(name: String): Map<String, MetaItem<out Meta>> = getAll(name.toN
|
||||
* Get a sequence of [Name]-[Value] pairs
|
||||
*/
|
||||
fun Meta.values(): Sequence<Pair<Name, Value>> {
|
||||
return items.asSequence().flatMap { entry ->
|
||||
val item = entry.value
|
||||
return items.asSequence().flatMap { (key, item) ->
|
||||
when (item) {
|
||||
is ValueItem -> sequenceOf(entry.key.asName() to item.value)
|
||||
is NodeItem -> item.node.values().map { pair -> (entry.key.asName() + pair.first) to pair.second }
|
||||
is ValueItem -> sequenceOf(key.asName() to item.value)
|
||||
is NodeItem -> item.node.values().map { pair -> (key.asName() + pair.first) to pair.second }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
operator fun Meta.iterator(): Iterator<Pair<Name, Value>> = values().iterator()
|
||||
/**
|
||||
* Get a sequence of all [Name]-[MetaItem] pairs for all items including nodes
|
||||
*/
|
||||
fun Meta.sequence(): Sequence<Pair<Name, MetaItem<*>>> {
|
||||
return sequence {
|
||||
items.forEach { (key, item) ->
|
||||
yield(key.asName() to item)
|
||||
if(item is NodeItem<*>) {
|
||||
yieldAll(item.node.sequence().map { (innerKey, innerItem)->
|
||||
(key + innerKey) to innerItem
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
operator fun Meta.iterator(): Iterator<Pair<Name, MetaItem<*>>> = sequence().iterator()
|
||||
|
||||
/**
|
||||
* A meta node that ensures that all of its descendants has at least the same type
|
||||
|
@ -46,4 +46,12 @@ fun Meta.builder(): MetaBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build a [MetaBuilder] using given transformation
|
||||
*/
|
||||
fun buildMeta(builder: MetaBuilder.() -> Unit): MetaBuilder = MetaBuilder().apply(builder)
|
||||
|
||||
/**
|
||||
* Build meta using given source meta as a base
|
||||
*/
|
||||
fun buildMeta(source: Meta, builder: MetaBuilder.() -> Unit): MetaBuilder = source.builder().apply(builder)
|
@ -0,0 +1,72 @@
|
||||
package hep.dataforge.meta
|
||||
|
||||
import hep.dataforge.names.Name
|
||||
|
||||
/**
|
||||
* A transformation for meta item or a group of items
|
||||
*/
|
||||
interface TransformationRule {
|
||||
|
||||
/**
|
||||
* Check if this transformation
|
||||
*/
|
||||
fun matches(name: Name, item: MetaItem<*>?): Boolean
|
||||
|
||||
/**
|
||||
* Select all items to be transformed. Item could be a value as well as node
|
||||
*
|
||||
* @return a sequence of item paths to be transformed
|
||||
*/
|
||||
fun selectItems(meta: Meta): Sequence<Name> =
|
||||
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
|
||||
*/
|
||||
fun <M : MutableMetaNode<M>> transformItem(name: Name, item: MetaItem<*>?, target: M): Unit
|
||||
}
|
||||
|
||||
data class SelfTransformationRule(val name: Name) : TransformationRule {
|
||||
override fun matches(name: Name, item: MetaItem<*>?): Boolean {
|
||||
return name == name
|
||||
}
|
||||
|
||||
override fun selectItems(meta: Meta): Sequence<Name> = sequenceOf(name)
|
||||
|
||||
override fun <M : MutableMetaNode<M>> transformItem(name: Name, item: MetaItem<*>?, target: M) {
|
||||
if (name == this.name) target[name] = item
|
||||
}
|
||||
}
|
||||
|
||||
data class SingleItemTransformationRule(
|
||||
val from: Name,
|
||||
val to: Name,
|
||||
val transform: MutableMetaNode<*>.(MetaItem<*>?) -> Unit
|
||||
) : TransformationRule {
|
||||
override fun matches(name: Name, item: MetaItem<*>?): Boolean {
|
||||
return name == from
|
||||
}
|
||||
|
||||
override fun selectItems(meta: Meta): Sequence<Name> = sequenceOf(from)
|
||||
|
||||
override fun <M : MutableMetaNode<M>> transformItem(name: Name, item: MetaItem<*>?, target: M) {
|
||||
if (name == this.from) {
|
||||
target.transform(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MetaTransformation {
|
||||
private val transformations = HashSet<TransformationRule>()
|
||||
|
||||
/**
|
||||
* Produce new meta using only those items that match transformation rules
|
||||
*/
|
||||
fun produce(source: Meta): Meta = buildMeta {
|
||||
transformations.forEach { rule ->
|
||||
rule.selectItems(source).forEach { name ->
|
||||
rule.transformItem(name, source[name], this)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -96,11 +96,20 @@ fun <M : MutableMeta<M>> MutableMeta<M>.remove(name: Name) = set(name, null)
|
||||
fun <M : MutableMeta<M>> MutableMeta<M>.remove(name: String) = remove(name.toName())
|
||||
|
||||
fun <M : MutableMeta<M>> MutableMeta<M>.setValue(name: Name, value: Value) = set(name, MetaItem.ValueItem(value))
|
||||
fun <M : MutableMeta<M>> MutableMeta<M>.setItem(name: String, item: MetaItem<M>) = set(name.toName(), item)
|
||||
//fun <M : MutableMeta<M>> MutableMeta<M>.setItem(name: String, item: MetaItem<M>) = set(name.toName(), item)
|
||||
fun <M : MutableMeta<M>> MutableMeta<M>.setValue(name: String, value: Value) =
|
||||
set(name.toName(), MetaItem.ValueItem(value))
|
||||
|
||||
fun <M : MutableMeta<M>> MutableMeta<M>.setItem(token: NameToken, item: MetaItem<M>?) = set(token.asName(), item)
|
||||
//fun <M : MutableMeta<M>> MutableMeta<M>.setItem(token: NameToken, item: MetaItem<M>?) = set(token.asName(), item)
|
||||
|
||||
fun <M : MutableMetaNode<M>> MutableMetaNode<M>.setItem(name: Name, item: MetaItem<*>) {
|
||||
when (item) {
|
||||
is MetaItem.ValueItem<*> -> setValue(name, item.value)
|
||||
is MetaItem.NodeItem<*> -> setNode(name, item.node)
|
||||
}
|
||||
}
|
||||
|
||||
fun <M : MutableMetaNode<M>> MutableMetaNode<M>.setItem(name: String, item: MetaItem<*>) = setItem(name.toName(), item)
|
||||
|
||||
fun <M : MutableMetaNode<M>> MutableMetaNode<M>.setNode(name: Name, node: Meta) =
|
||||
set(name, MetaItem.NodeItem(wrap(name, node)))
|
||||
@ -110,13 +119,10 @@ fun <M : MutableMetaNode<M>> MutableMetaNode<M>.setNode(name: String, node: Meta
|
||||
/**
|
||||
* Universal set method
|
||||
*/
|
||||
operator fun <M : MutableMetaNode<M>> M.set(name: Name, value: Any?) {
|
||||
operator fun <M : MutableMetaNode<M>> MutableMetaNode<M>.set(name: Name, value: Any?) {
|
||||
when (value) {
|
||||
null -> remove(name)
|
||||
is MetaItem<*> -> when (value) {
|
||||
is MetaItem.ValueItem<*> -> setValue(name, value.value)
|
||||
is MetaItem.NodeItem<*> -> setNode(name, value.node)
|
||||
}
|
||||
is MetaItem<*> -> setItem(name, value)
|
||||
is Meta -> setNode(name, value)
|
||||
is Specific -> setNode(name, value.config)
|
||||
else -> setValue(name, Value.of(value))
|
||||
|
Loading…
Reference in New Issue
Block a user