Working on meta transformations

This commit is contained in:
Alexander Nozik 2019-05-19 21:42:56 +03:00
parent 343ba84118
commit 54c7b55bc4
5 changed files with 115 additions and 14 deletions

View File

@ -1,4 +1,4 @@
val dataforgeVersion by extra("0.1.2") val dataforgeVersion by extra("0.1.3-dev-1")
allprojects { allprojects {
repositories { repositories {

View File

@ -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

View File

@ -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)

View File

@ -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)
}
}
}
}

View File

@ -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))