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 {
|
allprojects {
|
||||||
repositories {
|
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
|
* Get a sequence of [Name]-[Value] pairs
|
||||||
*/
|
*/
|
||||||
fun Meta.values(): Sequence<Pair<Name, Value>> {
|
fun Meta.values(): Sequence<Pair<Name, Value>> {
|
||||||
return items.asSequence().flatMap { entry ->
|
return items.asSequence().flatMap { (key, item) ->
|
||||||
val item = entry.value
|
|
||||||
when (item) {
|
when (item) {
|
||||||
is ValueItem -> sequenceOf(entry.key.asName() to item.value)
|
is ValueItem -> sequenceOf(key.asName() to item.value)
|
||||||
is NodeItem -> item.node.values().map { pair -> (entry.key.asName() + pair.first) to pair.second }
|
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
|
* 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)
|
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>.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>.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) =
|
fun <M : MutableMeta<M>> MutableMeta<M>.setValue(name: String, value: Value) =
|
||||||
set(name.toName(), MetaItem.ValueItem(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) =
|
fun <M : MutableMetaNode<M>> MutableMetaNode<M>.setNode(name: Name, node: Meta) =
|
||||||
set(name, MetaItem.NodeItem(wrap(name, node)))
|
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
|
* 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) {
|
when (value) {
|
||||||
null -> remove(name)
|
null -> remove(name)
|
||||||
is MetaItem<*> -> when (value) {
|
is MetaItem<*> -> setItem(name, value)
|
||||||
is MetaItem.ValueItem<*> -> setValue(name, value.value)
|
|
||||||
is MetaItem.NodeItem<*> -> setNode(name, value.node)
|
|
||||||
}
|
|
||||||
is Meta -> setNode(name, value)
|
is Meta -> setNode(name, value)
|
||||||
is Specific -> setNode(name, value.config)
|
is Specific -> setNode(name, value.config)
|
||||||
else -> setValue(name, Value.of(value))
|
else -> setValue(name, Value.of(value))
|
||||||
|
Loading…
Reference in New Issue
Block a user