Name comparison
This commit is contained in:
parent
59c46344fa
commit
f0413464a3
@ -1,8 +1,29 @@
|
|||||||
package hep.dataforge.descriptors
|
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
|
* An object which provides its descriptor
|
||||||
*/
|
*/
|
||||||
interface Described {
|
interface Described {
|
||||||
val descriptor: NodeDescriptor
|
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"
|
const val VALUE_KEY = "value"
|
||||||
|
|
||||||
override fun wrap(config: Config): NodeDescriptor = NodeDescriptor(config)
|
override fun wrap(config: Config): NodeDescriptor = NodeDescriptor(config)
|
||||||
|
|
||||||
|
//TODO infer descriptor from spec
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package hep.dataforge.meta
|
package hep.dataforge.meta
|
||||||
|
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
|
import hep.dataforge.names.startsWith
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A transformation for meta item or a group of items
|
* 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 {
|
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) {
|
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(
|
data class SingleItemTransformationRule(
|
||||||
val from: Name,
|
val from: Name,
|
||||||
val to: Name,
|
val transform: MutableMeta<*>.(Name, MetaItem<*>?) -> Unit
|
||||||
val transform: MutableMeta<*>.(MetaItem<*>?) -> Unit
|
|
||||||
) : TransformationRule {
|
) : TransformationRule {
|
||||||
override fun matches(name: Name, item: MetaItem<*>?): Boolean {
|
override fun matches(name: Name, item: MetaItem<*>?): Boolean {
|
||||||
return name == from
|
return name == from
|
||||||
@ -57,14 +58,29 @@ data class SingleItemTransformationRule(
|
|||||||
|
|
||||||
override fun <M : MutableMeta<M>> transformItem(name: Name, item: MetaItem<*>?, target: M) {
|
override fun <M : MutableMeta<M>> transformItem(name: Name, item: MetaItem<*>?, target: M) {
|
||||||
if (name == this.from) {
|
if (name == this.from) {
|
||||||
target.transform(item)
|
target.transform(name, item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class MetaTransformation {
|
data class RegexpItemTransformationRule(
|
||||||
private val transformations = HashSet<TransformationRule>()
|
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
|
* Produce new meta using only those items that match transformation rules
|
||||||
@ -89,7 +105,36 @@ class MetaTransformation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object{
|
/**
|
||||||
|
* 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)}
|
||||||
|
}
|
||||||
}
|
}
|
@ -122,4 +122,14 @@ fun Name.withIndex(index: String): Name {
|
|||||||
}
|
}
|
||||||
|
|
||||||
operator fun <T> Map<Name, T>.get(name: String) = get(name.toName())
|
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)
|
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
|
package hep.dataforge.names
|
||||||
|
|
||||||
import kotlin.test.Test
|
import kotlin.test.*
|
||||||
import kotlin.test.assertEquals
|
|
||||||
|
|
||||||
class NameTest {
|
class NameTest {
|
||||||
@Test
|
@Test
|
||||||
@ -16,4 +15,14 @@ class NameTest {
|
|||||||
val name2 = "token1".toName() + "token2[2].token3"
|
val name2 = "token1".toName() + "token2[2].token3"
|
||||||
assertEquals(name1, name2)
|
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