Minor API fixed for Meta
This commit is contained in:
parent
8f5a20bb22
commit
4e679b8971
@ -69,7 +69,7 @@ open class Context(final override val name: String, val parent: Context? = Globa
|
||||
override fun listTop(target: String): Sequence<Name> {
|
||||
return when (target) {
|
||||
Plugin.PLUGIN_TARGET -> plugins.asSequence().map { it.name.toName() }
|
||||
Value.TYPE -> properties.asValueSequence().map { it.first }
|
||||
Value.TYPE -> properties.values().map { it.first }
|
||||
else -> emptySequence()
|
||||
}
|
||||
}
|
||||
|
@ -91,19 +91,19 @@ fun Meta.getAll(name: Name): Map<String, MetaItem<out Meta>> {
|
||||
fun Meta.getAll(name: String): Map<String, MetaItem<out Meta>> = getAll(name.toName())
|
||||
|
||||
/**
|
||||
* Transform meta to sequence of [Name]-[Value] pairs
|
||||
* Get a sequence of [Name]-[Value] pairs
|
||||
*/
|
||||
fun Meta.asValueSequence(): Sequence<Pair<Name, Value>> {
|
||||
fun Meta.values(): Sequence<Pair<Name, Value>> {
|
||||
return items.asSequence().flatMap { entry ->
|
||||
val item = entry.value
|
||||
when (item) {
|
||||
is ValueItem -> sequenceOf(entry.key.asName() to item.value)
|
||||
is NodeItem -> item.node.asValueSequence().map { pair -> (entry.key.asName() + pair.first) to pair.second }
|
||||
is NodeItem -> item.node.values().map { pair -> (entry.key.asName() + pair.first) to pair.second }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
operator fun Meta.iterator(): Iterator<Pair<Name, Value>> = asValueSequence().iterator()
|
||||
operator fun Meta.iterator(): Iterator<Pair<Name, Value>> = values().iterator()
|
||||
|
||||
/**
|
||||
* A meta node that ensures that all of its descendants has at least the same type
|
||||
@ -112,6 +112,27 @@ interface MetaNode<M : MetaNode<M>> : Meta {
|
||||
override val items: Map<NameToken, MetaItem<M>>
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all items matching given name.
|
||||
*/
|
||||
fun <M : MetaNode<M>> MetaNode<M>.getAll(name: Name): Map<String, MetaItem<M>> {
|
||||
val root: MetaNode<M>? = when (name.length) {
|
||||
0 -> error("Can't use empty name for that")
|
||||
1 -> this
|
||||
else -> (this[name.cutLast()] as? NodeItem<M>)?.node
|
||||
}
|
||||
|
||||
val (body, index) = name.last()!!
|
||||
val regex = index.toRegex()
|
||||
|
||||
return root?.items
|
||||
?.filter { it.key.body == body && (index.isEmpty() || regex.matches(it.key.index)) }
|
||||
?.mapKeys { it.key.index }
|
||||
?: emptyMap()
|
||||
}
|
||||
|
||||
fun <M : MetaNode<M>> M.getAll(name: String): Map<String, MetaItem<M>> = getAll(name.toName())
|
||||
|
||||
operator fun <M : MetaNode<M>> MetaNode<M>.get(name: Name): MetaItem<M>? {
|
||||
return name.first()?.let { token ->
|
||||
val tail = name.cutFirst()
|
||||
@ -122,7 +143,7 @@ operator fun <M : MetaNode<M>> MetaNode<M>.get(name: Name): MetaItem<M>? {
|
||||
}
|
||||
}
|
||||
|
||||
operator fun <M : MetaNode<M>> MetaNode<M>.get(key: String): MetaItem<M>? = get(key.toName())
|
||||
operator fun <M : MetaNode<M>> MetaNode<M>?.get(key: String): MetaItem<M>? = this?.let { get(key.toName()) }
|
||||
|
||||
/**
|
||||
* Equals and hash code implementation for meta node
|
||||
|
@ -1,10 +1,6 @@
|
||||
package hep.dataforge.meta
|
||||
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.NameToken
|
||||
import hep.dataforge.names.plus
|
||||
import hep.dataforge.names.toName
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.names.*
|
||||
import hep.dataforge.values.Value
|
||||
|
||||
internal data class MetaListener(
|
||||
@ -152,12 +148,12 @@ fun <M : MutableMetaNode<M>> M.update(meta: Meta) {
|
||||
fun <M : MutableMeta<M>> M.setIndexed(
|
||||
name: Name,
|
||||
items: Iterable<MetaItem<M>>,
|
||||
queryFactory: (Int) -> String = { it.toString() }
|
||||
indexFactory: MetaItem<M>.(index: Int) -> String = { it.toString() }
|
||||
) {
|
||||
val tokens = name.tokens.toMutableList()
|
||||
val last = tokens.last()
|
||||
items.forEachIndexed { index, meta ->
|
||||
val indexedToken = NameToken(last.body, last.index + queryFactory(index))
|
||||
val indexedToken = NameToken(last.body, last.index + meta.indexFactory(index))
|
||||
tokens[tokens.lastIndex] = indexedToken
|
||||
set(Name(tokens), meta)
|
||||
}
|
||||
@ -166,10 +162,24 @@ fun <M : MutableMeta<M>> M.setIndexed(
|
||||
fun <M : MutableMetaNode<M>> M.setIndexed(
|
||||
name: Name,
|
||||
metas: Iterable<Meta>,
|
||||
queryFactory: (Int) -> String = { it.toString() }
|
||||
indexFactory: MetaItem<M>.(index: Int) -> String = { it.toString() }
|
||||
) {
|
||||
setIndexed(name, metas.map { MetaItem.NodeItem(wrap(name, it)) }, queryFactory)
|
||||
setIndexed(name, metas.map { MetaItem.NodeItem(wrap(name, it)) }, indexFactory)
|
||||
}
|
||||
|
||||
operator fun <M : MutableMetaNode<M>> M.set(name: Name, metas: Iterable<Meta>) = setIndexed(name, metas)
|
||||
operator fun <M : MutableMetaNode<M>> M.set(name: String, metas: Iterable<Meta>) = setIndexed(name.toName(), metas)
|
||||
|
||||
/**
|
||||
* Append the node with a same-name-sibling, automatically generating numerical index
|
||||
*/
|
||||
fun <M : MutableMetaNode<M>> M.append(name: Name, value: Any?) {
|
||||
require(!name.isEmpty()) { "Name could not be empty for append operation" }
|
||||
val newIndex = name.last()!!.index
|
||||
if (newIndex.isNotEmpty()) {
|
||||
set(name, value)
|
||||
} else {
|
||||
val index = (getAll(name).keys.mapNotNull { it.toIntOrNull() }.max() ?: -1) + 1
|
||||
set(name.withIndex(index.toString()), value)
|
||||
}
|
||||
}
|
||||
|
@ -105,4 +105,15 @@ fun NameToken.asName() = Name(listOf(this))
|
||||
|
||||
val EmptyName = Name(emptyList())
|
||||
|
||||
fun Name.isEmpty(): Boolean = this.length == 0
|
||||
fun Name.isEmpty(): Boolean = this.length == 0
|
||||
|
||||
/**
|
||||
* Set or replace last token index
|
||||
*/
|
||||
fun Name.withIndex(index: String): Name {
|
||||
val tokens = ArrayList(tokens)
|
||||
val last = NameToken(tokens.last().body, index)
|
||||
tokens.removeAt(tokens.size - 1)
|
||||
tokens.add(last)
|
||||
return Name(tokens)
|
||||
}
|
@ -30,7 +30,7 @@ class MetaBuilderTest {
|
||||
"b.a[$it]" to it
|
||||
}
|
||||
}.seal()
|
||||
assertEquals(10, meta.asValueSequence().count())
|
||||
assertEquals(10, meta.values().count())
|
||||
|
||||
val nodes = meta.getAll("b.a")
|
||||
|
||||
|
@ -14,7 +14,7 @@ class StyledTest{
|
||||
}
|
||||
}
|
||||
}.seal().withStyle()
|
||||
assertEquals(10, meta.asValueSequence().count())
|
||||
assertEquals(10, meta.values().count())
|
||||
|
||||
val bNode = meta["b"].node
|
||||
|
||||
@ -22,8 +22,8 @@ class StyledTest{
|
||||
|
||||
val allNodes = meta.getAll("b.a")
|
||||
|
||||
assertEquals(3, aNodes?.get("3")?.node["d"]?.int)
|
||||
assertEquals(3, allNodes["3"]?.node["d"]?.int)
|
||||
assertEquals(3, aNodes?.get("3").node["d"].int)
|
||||
assertEquals(3, allNodes["3"].node["d"].int)
|
||||
}
|
||||
|
||||
}
|
@ -32,7 +32,8 @@ fun Meta.toDynamic(): dynamic {
|
||||
class DynamicMeta(val obj: dynamic) : Meta {
|
||||
private fun keys() = js("Object.keys(this.obj)") as Array<String>
|
||||
|
||||
private fun isArray(obj: dynamic): Boolean = js("Array.isArray(obj)") as Boolean
|
||||
private fun isArray(@Suppress("UNUSED_PARAMETER") obj: dynamic): Boolean =
|
||||
js("Array.isArray(obj)") as Boolean
|
||||
|
||||
private fun asItem(obj: dynamic): MetaItem<DynamicMeta>? {
|
||||
if (obj == null) return MetaItem.ValueItem(Null)
|
||||
|
Loading…
Reference in New Issue
Block a user