Name comparison
This commit is contained in:
parent
59c46344fa
commit
f0413464a3
@ -1,8 +1,29 @@
|
||||
package hep.dataforge.descriptors
|
||||
|
||||
import hep.dataforge.descriptors.Described.Companion.DESCRIPTOR_NODE
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.get
|
||||
import hep.dataforge.meta.node
|
||||
|
||||
/**
|
||||
* An object which provides its descriptor
|
||||
*/
|
||||
interface Described {
|
||||
val descriptor: NodeDescriptor
|
||||
|
||||
companion object {
|
||||
const val DESCRIPTOR_NODE = "@descriptor"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If meta node supplies explicit descriptor, return it, otherwise try to use descriptor node from meta itself
|
||||
*/
|
||||
val Meta.descriptor: NodeDescriptor?
|
||||
get() {
|
||||
return if (this is Described) {
|
||||
descriptor
|
||||
} else {
|
||||
get(DESCRIPTOR_NODE).node?.let { NodeDescriptor.wrap(it) }
|
||||
}
|
||||
}
|
@ -126,5 +126,7 @@ class NodeDescriptor(override val config: Config) : Specific {
|
||||
const val VALUE_KEY = "value"
|
||||
|
||||
override fun wrap(config: Config): NodeDescriptor = NodeDescriptor(config)
|
||||
|
||||
//TODO infer descriptor from spec
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package hep.dataforge.meta
|
||||
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.startsWith
|
||||
|
||||
/**
|
||||
* A transformation for meta item or a group of items
|
||||
@ -27,17 +28,18 @@ interface TransformationRule {
|
||||
}
|
||||
|
||||
/**
|
||||
* A transformation which transforms an element with given [name] to itself.
|
||||
* A transformation which keeps all elements, matching [selector] unchanged.
|
||||
*/
|
||||
data class SelfTransformationRule(val name: Name) : TransformationRule {
|
||||
data class KeepTransformationRule(val selector: (Name) -> Boolean) : TransformationRule {
|
||||
override fun matches(name: Name, item: MetaItem<*>?): Boolean {
|
||||
return name == name
|
||||
return selector(name)
|
||||
}
|
||||
|
||||
override fun selectItems(meta: Meta): Sequence<Name> = sequenceOf(name)
|
||||
override fun selectItems(meta: Meta): Sequence<Name> =
|
||||
meta.sequence().map { it.first }.filter(selector)
|
||||
|
||||
override fun <M : MutableMeta<M>> transformItem(name: Name, item: MetaItem<*>?, target: M) {
|
||||
if (name == this.name) target[name] = item
|
||||
if (selector(name)) target[name] = item
|
||||
}
|
||||
}
|
||||
|
||||
@ -46,8 +48,7 @@ data class SelfTransformationRule(val name: Name) : TransformationRule {
|
||||
*/
|
||||
data class SingleItemTransformationRule(
|
||||
val from: Name,
|
||||
val to: Name,
|
||||
val transform: MutableMeta<*>.(MetaItem<*>?) -> Unit
|
||||
val transform: MutableMeta<*>.(Name, MetaItem<*>?) -> Unit
|
||||
) : TransformationRule {
|
||||
override fun matches(name: Name, item: MetaItem<*>?): Boolean {
|
||||
return name == from
|
||||
@ -57,14 +58,29 @@ data class SingleItemTransformationRule(
|
||||
|
||||
override fun <M : MutableMeta<M>> transformItem(name: Name, item: MetaItem<*>?, target: M) {
|
||||
if (name == this.from) {
|
||||
target.transform(item)
|
||||
target.transform(name, item)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class MetaTransformation {
|
||||
private val transformations = HashSet<TransformationRule>()
|
||||
data class RegexpItemTransformationRule(
|
||||
val from: Regex,
|
||||
val transform: MutableMeta<*>.(MatchResult, MetaItem<*>?) -> Unit
|
||||
) : TransformationRule {
|
||||
override fun matches(name: Name, item: MetaItem<*>?): Boolean {
|
||||
return from.matches(name.toString())
|
||||
}
|
||||
|
||||
override fun <M : MutableMeta<M>> transformItem(name: Name, item: MetaItem<*>?, target: M) {
|
||||
val match = from.matchEntire(name.toString())
|
||||
if (match != null) {
|
||||
target.transform(match, item)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline class MetaTransformation(val transformations: Collection<TransformationRule>) {
|
||||
|
||||
/**
|
||||
* Produce new meta using only those items that match transformation rules
|
||||
@ -89,7 +105,36 @@ class MetaTransformation {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for changes in the source node and translates them into second node if transformation set contains a corresponding rule.
|
||||
*/
|
||||
fun <M : MutableMeta<M>> bind(source: MutableMeta<*>, target: M) {
|
||||
source.onChange(target) { name, oldItem, newItem ->
|
||||
transformations.forEach { t ->
|
||||
if (t.matches(name, newItem)) {
|
||||
t.transformItem(name, newItem, target)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
class MetaTransformationBuilder {
|
||||
val transformations = HashSet<TransformationRule>()
|
||||
|
||||
fun keep(selector: (Name) -> Boolean) {
|
||||
transformations.add(KeepTransformationRule(selector))
|
||||
}
|
||||
|
||||
fun keep(name: Name) {
|
||||
keep{it == name}
|
||||
}
|
||||
|
||||
fun keepNode(name: Name){
|
||||
keep{it.startsWith(name)}
|
||||
}
|
||||
}
|
@ -123,3 +123,13 @@ fun Name.withIndex(index: String): Name {
|
||||
|
||||
operator fun <T> Map<Name, T>.get(name: String) = get(name.toName())
|
||||
operator fun <T> MutableMap<Name, T>.set(name: String, value: T) = set(name.toName(), value)
|
||||
|
||||
/* Name comparison operations */
|
||||
|
||||
fun Name.startsWith(token: NameToken): Boolean = first() == token
|
||||
|
||||
fun Name.endsWith(token: NameToken): Boolean = last() == token
|
||||
|
||||
fun Name.startsWith(name: Name): Boolean = tokens.subList(0, name.length) == name.tokens
|
||||
|
||||
fun Name.endsWith(name: Name): Boolean = tokens.subList(length - name.length, length) == name.tokens
|
@ -1,7 +1,6 @@
|
||||
package hep.dataforge.names
|
||||
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.*
|
||||
|
||||
class NameTest {
|
||||
@Test
|
||||
@ -16,4 +15,14 @@ class NameTest {
|
||||
val name2 = "token1".toName() + "token2[2].token3"
|
||||
assertEquals(name1, name2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun comparisonTest(){
|
||||
val name1 = "token1.token2.token3".toName()
|
||||
val name2 = "token1.token2".toName()
|
||||
val name3 = "token3".toName()
|
||||
assertTrue { name1.startsWith(name2) }
|
||||
assertTrue { name1.endsWith(name3) }
|
||||
assertFalse { name1.startsWith(name3) }
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user