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> {
|
override fun listTop(target: String): Sequence<Name> {
|
||||||
return when (target) {
|
return when (target) {
|
||||||
Plugin.PLUGIN_TARGET -> plugins.asSequence().map { it.name.toName() }
|
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()
|
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())
|
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 ->
|
return items.asSequence().flatMap { entry ->
|
||||||
val item = entry.value
|
val item = entry.value
|
||||||
when (item) {
|
when (item) {
|
||||||
is ValueItem -> sequenceOf(entry.key.asName() to item.value)
|
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
|
* 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>>
|
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>? {
|
operator fun <M : MetaNode<M>> MetaNode<M>.get(name: Name): MetaItem<M>? {
|
||||||
return name.first()?.let { token ->
|
return name.first()?.let { token ->
|
||||||
val tail = name.cutFirst()
|
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
|
* Equals and hash code implementation for meta node
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
package hep.dataforge.meta
|
package hep.dataforge.meta
|
||||||
|
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.*
|
||||||
import hep.dataforge.names.NameToken
|
|
||||||
import hep.dataforge.names.plus
|
|
||||||
import hep.dataforge.names.toName
|
|
||||||
import hep.dataforge.names.asName
|
|
||||||
import hep.dataforge.values.Value
|
import hep.dataforge.values.Value
|
||||||
|
|
||||||
internal data class MetaListener(
|
internal data class MetaListener(
|
||||||
@ -152,12 +148,12 @@ fun <M : MutableMetaNode<M>> M.update(meta: Meta) {
|
|||||||
fun <M : MutableMeta<M>> M.setIndexed(
|
fun <M : MutableMeta<M>> M.setIndexed(
|
||||||
name: Name,
|
name: Name,
|
||||||
items: Iterable<MetaItem<M>>,
|
items: Iterable<MetaItem<M>>,
|
||||||
queryFactory: (Int) -> String = { it.toString() }
|
indexFactory: MetaItem<M>.(index: Int) -> String = { it.toString() }
|
||||||
) {
|
) {
|
||||||
val tokens = name.tokens.toMutableList()
|
val tokens = name.tokens.toMutableList()
|
||||||
val last = tokens.last()
|
val last = tokens.last()
|
||||||
items.forEachIndexed { index, meta ->
|
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
|
tokens[tokens.lastIndex] = indexedToken
|
||||||
set(Name(tokens), meta)
|
set(Name(tokens), meta)
|
||||||
}
|
}
|
||||||
@ -166,10 +162,24 @@ fun <M : MutableMeta<M>> M.setIndexed(
|
|||||||
fun <M : MutableMetaNode<M>> M.setIndexed(
|
fun <M : MutableMetaNode<M>> M.setIndexed(
|
||||||
name: Name,
|
name: Name,
|
||||||
metas: Iterable<Meta>,
|
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: Name, metas: Iterable<Meta>) = setIndexed(name, metas)
|
||||||
operator fun <M : MutableMetaNode<M>> M.set(name: String, metas: Iterable<Meta>) = setIndexed(name.toName(), 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -106,3 +106,14 @@ fun NameToken.asName() = Name(listOf(this))
|
|||||||
val EmptyName = Name(emptyList())
|
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
|
"b.a[$it]" to it
|
||||||
}
|
}
|
||||||
}.seal()
|
}.seal()
|
||||||
assertEquals(10, meta.asValueSequence().count())
|
assertEquals(10, meta.values().count())
|
||||||
|
|
||||||
val nodes = meta.getAll("b.a")
|
val nodes = meta.getAll("b.a")
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ class StyledTest{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.seal().withStyle()
|
}.seal().withStyle()
|
||||||
assertEquals(10, meta.asValueSequence().count())
|
assertEquals(10, meta.values().count())
|
||||||
|
|
||||||
val bNode = meta["b"].node
|
val bNode = meta["b"].node
|
||||||
|
|
||||||
@ -22,8 +22,8 @@ class StyledTest{
|
|||||||
|
|
||||||
val allNodes = meta.getAll("b.a")
|
val allNodes = meta.getAll("b.a")
|
||||||
|
|
||||||
assertEquals(3, aNodes?.get("3")?.node["d"]?.int)
|
assertEquals(3, aNodes?.get("3").node["d"].int)
|
||||||
assertEquals(3, allNodes["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 {
|
class DynamicMeta(val obj: dynamic) : Meta {
|
||||||
private fun keys() = js("Object.keys(this.obj)") as Array<String>
|
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>? {
|
private fun asItem(obj: dynamic): MetaItem<DynamicMeta>? {
|
||||||
if (obj == null) return MetaItem.ValueItem(Null)
|
if (obj == null) return MetaItem.ValueItem(Null)
|
||||||
|
Loading…
Reference in New Issue
Block a user