Optimized type projections in meta. Set operations are now non-generic
This commit is contained in:
parent
f0413464a3
commit
d08e1ee57d
@ -90,6 +90,7 @@ object BinaryMetaFormat : MetaFormat {
|
||||
return readText(max = length)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun Input.readMetaItem(): MetaItem<MetaBuilder> {
|
||||
val keyChar = readByte().toChar()
|
||||
return when (keyChar) {
|
||||
@ -119,6 +120,6 @@ object BinaryMetaFormat : MetaFormat {
|
||||
MetaItem.NodeItem(meta)
|
||||
}
|
||||
else -> error("Unknown serialization key character: $keyChar")
|
||||
}
|
||||
} as MetaItem<MetaBuilder>
|
||||
}
|
||||
}
|
@ -49,8 +49,7 @@ fun Value.toJson(): JsonElement {
|
||||
|
||||
fun Meta.toJson(): JsonObject {
|
||||
val map = this.items.mapValues { entry ->
|
||||
val value = entry.value
|
||||
when (value) {
|
||||
when (val value = entry.value) {
|
||||
is MetaItem.ValueItem -> value.value.toJson()
|
||||
is MetaItem.NodeItem -> value.node.toJson()
|
||||
}
|
||||
@ -70,8 +69,9 @@ class JsonMeta(val json: JsonObject) : Meta {
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private operator fun MutableMap<String, MetaItem<JsonMeta>>.set(key: String, value: JsonElement) = when (value) {
|
||||
is JsonPrimitive -> this[key] = MetaItem.ValueItem(value.toValue())
|
||||
is JsonPrimitive -> this[key] = MetaItem.ValueItem(value.toValue()) as MetaItem<JsonMeta>
|
||||
is JsonObject -> this[key] = MetaItem.NodeItem(value.toMeta())
|
||||
is JsonArray -> {
|
||||
when {
|
||||
@ -82,12 +82,12 @@ class JsonMeta(val json: JsonObject) : Meta {
|
||||
(it as JsonPrimitive).toValue()
|
||||
}
|
||||
)
|
||||
this[key] = MetaItem.ValueItem(listValue)
|
||||
this[key] = MetaItem.ValueItem(listValue) as MetaItem<JsonMeta>
|
||||
}
|
||||
else -> value.forEachIndexed { index, jsonElement ->
|
||||
when (jsonElement) {
|
||||
is JsonObject -> this["$key[$index]"] = MetaItem.NodeItem(JsonMeta(jsonElement))
|
||||
is JsonPrimitive -> this["$key[$index]"] = MetaItem.ValueItem(jsonElement.toValue())
|
||||
is JsonPrimitive -> this["$key[$index]"] = MetaItem.ValueItem(jsonElement.toValue()) as MetaItem<JsonMeta>
|
||||
is JsonArray -> TODO("Nested arrays not supported")
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
package hep.dataforge.meta
|
||||
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.NameToken
|
||||
import hep.dataforge.names.asName
|
||||
|
||||
@ -9,12 +8,12 @@ import hep.dataforge.names.asName
|
||||
/**
|
||||
* Mutable meta representing object state
|
||||
*/
|
||||
open class Config : AbstractMutableMeta<Config>() {
|
||||
class Config : AbstractMutableMeta<Config>() {
|
||||
|
||||
/**
|
||||
* Attach configuration node instead of creating one
|
||||
*/
|
||||
override fun wrap(name: Name, meta: Meta): Config = meta.toConfig()
|
||||
override fun wrapNode(meta: Meta): Config = meta.toConfig()
|
||||
|
||||
override fun empty(): Config = Config()
|
||||
|
||||
@ -29,7 +28,7 @@ fun Meta.toConfig(): Config = this as? Config ?: Config().also { builder ->
|
||||
this.items.mapValues { entry ->
|
||||
val item = entry.value
|
||||
builder[entry.key.asName()] = when (item) {
|
||||
is MetaItem.ValueItem -> MetaItem.ValueItem(item.value)
|
||||
is MetaItem.ValueItem -> item.value
|
||||
is MetaItem.NodeItem -> MetaItem.NodeItem(item.node.toConfig())
|
||||
}
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ import hep.dataforge.values.boolean
|
||||
* * a [ValueItem] (leaf)
|
||||
* * a [NodeItem] (node)
|
||||
*/
|
||||
sealed class MetaItem<M : Meta> {
|
||||
data class ValueItem<M : Meta>(val value: Value) : MetaItem<M>()
|
||||
sealed class MetaItem<out M : Meta> {
|
||||
data class ValueItem(val value: Value) : MetaItem<Nothing>()
|
||||
data class NodeItem<M : Meta>(val node: M) : MetaItem<M>()
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ interface MetaRepr {
|
||||
* * Same name siblings are supported via elements with the same [Name] but different queries
|
||||
*/
|
||||
interface Meta : MetaRepr {
|
||||
val items: Map<NameToken, MetaItem<out Meta>>
|
||||
val items: Map<NameToken, MetaItem<*>>
|
||||
|
||||
override fun toMeta(): Meta = this
|
||||
|
||||
@ -50,12 +50,7 @@ interface Meta : MetaRepr {
|
||||
|
||||
/* Get operations*/
|
||||
|
||||
/**
|
||||
* Fast [String]-based accessor for item map
|
||||
*/
|
||||
operator fun <T> Map<NameToken, T>.get(body: String, query: String = ""): T? = get(NameToken(body, query))
|
||||
|
||||
operator fun Meta?.get(name: Name): MetaItem<out Meta>? {
|
||||
operator fun Meta?.get(name: Name): MetaItem<*>? {
|
||||
if (this == null) return null
|
||||
return name.first()?.let { token ->
|
||||
val tail = name.cutFirst()
|
||||
@ -66,13 +61,13 @@ operator fun Meta?.get(name: Name): MetaItem<out Meta>? {
|
||||
}
|
||||
}
|
||||
|
||||
operator fun Meta?.get(token: NameToken): MetaItem<out Meta>? = this?.items?.get(token)
|
||||
operator fun Meta?.get(key: String): MetaItem<out Meta>? = get(key.toName())
|
||||
operator fun Meta?.get(token: NameToken): MetaItem<*>? = this?.items?.get(token)
|
||||
operator fun Meta?.get(key: String): MetaItem<*>? = get(key.toName())
|
||||
|
||||
/**
|
||||
* Get all items matching given name.
|
||||
*/
|
||||
fun Meta.getAll(name: Name): Map<String, MetaItem<out Meta>> {
|
||||
fun Meta.getAll(name: Name): Map<String, MetaItem<*>> {
|
||||
val root = when (name.length) {
|
||||
0 -> error("Can't use empty name for that")
|
||||
1 -> this
|
||||
@ -88,7 +83,7 @@ fun Meta.getAll(name: Name): Map<String, MetaItem<out Meta>> {
|
||||
?: emptyMap()
|
||||
}
|
||||
|
||||
fun Meta.getAll(name: String): Map<String, MetaItem<out Meta>> = getAll(name.toName())
|
||||
fun Meta.getAll(name: String): Map<String, MetaItem<*>> = getAll(name.toName())
|
||||
|
||||
/**
|
||||
* Get a sequence of [Name]-[Value] pairs
|
||||
@ -109,8 +104,8 @@ 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)->
|
||||
if (item is NodeItem<*>) {
|
||||
yieldAll(item.node.sequence().map { (innerKey, innerItem) ->
|
||||
(key + innerKey) to innerItem
|
||||
})
|
||||
}
|
||||
@ -130,7 +125,7 @@ interface MetaNode<M : MetaNode<M>> : Meta {
|
||||
/**
|
||||
* Get all items matching given name.
|
||||
*/
|
||||
fun <M : MetaNode<M>> MetaNode<M>.getAll(name: Name): Map<String, MetaItem<M>> {
|
||||
fun <M : MetaNode<M>> 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
|
||||
@ -158,7 +153,11 @@ operator fun <M : MetaNode<M>> MetaNode<M>.get(name: Name): MetaItem<M>? {
|
||||
}
|
||||
}
|
||||
|
||||
operator fun <M : MetaNode<M>> MetaNode<M>?.get(key: String): MetaItem<M>? = this?.let { get(key.toName()) }
|
||||
operator fun <M : MetaNode<M>> MetaNode<M>?.get(key: String): MetaItem<M>? = if (this == null) {
|
||||
null
|
||||
} else {
|
||||
this[key.toName()]
|
||||
}
|
||||
|
||||
/**
|
||||
* Equals and hash code implementation for meta node
|
||||
@ -189,13 +188,14 @@ class SealedMeta internal constructor(override val items: Map<NameToken, MetaIte
|
||||
*/
|
||||
fun Meta.seal(): SealedMeta = this as? SealedMeta ?: SealedMeta(items.mapValues { entry -> entry.value.seal() })
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun MetaItem<*>.seal(): MetaItem<SealedMeta> = when (this) {
|
||||
is MetaItem.ValueItem -> MetaItem.ValueItem(value)
|
||||
is MetaItem.NodeItem -> MetaItem.NodeItem(node.seal())
|
||||
is ValueItem -> this as MetaItem<SealedMeta>
|
||||
is NodeItem -> NodeItem(node.seal())
|
||||
}
|
||||
|
||||
object EmptyMeta : Meta {
|
||||
override val items: Map<NameToken, MetaItem<out Meta>> = emptyMap()
|
||||
override val items: Map<NameToken, MetaItem<*>> = emptyMap()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -203,8 +203,8 @@ object EmptyMeta : Meta {
|
||||
*/
|
||||
|
||||
val MetaItem<*>?.value
|
||||
get() = (this as? MetaItem.ValueItem)?.value
|
||||
?: (this?.node?.get(VALUE_KEY) as? MetaItem.ValueItem)?.value
|
||||
get() = (this as? ValueItem)?.value
|
||||
?: (this?.node?.get(VALUE_KEY) as? ValueItem)?.value
|
||||
|
||||
val MetaItem<*>?.string get() = value?.string
|
||||
val MetaItem<*>?.boolean get() = value?.boolean
|
||||
@ -226,8 +226,8 @@ val MetaItem<*>?.stringList get() = value?.list?.map { it.string } ?: emptyList(
|
||||
val <M : Meta> MetaItem<M>?.node: M?
|
||||
get() = when (this) {
|
||||
null -> null
|
||||
is MetaItem.ValueItem -> error("Trying to interpret value meta item as node item")
|
||||
is MetaItem.NodeItem -> node
|
||||
is ValueItem -> error("Trying to interpret value meta item as node item")
|
||||
is NodeItem -> node
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,6 +1,5 @@
|
||||
package hep.dataforge.meta
|
||||
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.values.Value
|
||||
|
||||
@ -8,7 +7,7 @@ import hep.dataforge.values.Value
|
||||
* DSL builder for meta. Is not intended to store mutable state
|
||||
*/
|
||||
class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
|
||||
override fun wrap(name: Name, meta: Meta): MetaBuilder = meta.builder()
|
||||
override fun wrapNode(meta: Meta): MetaBuilder = meta.builder()
|
||||
override fun empty(): MetaBuilder = MetaBuilder()
|
||||
|
||||
infix fun String.to(value: Any) {
|
||||
@ -39,7 +38,7 @@ fun Meta.builder(): MetaBuilder {
|
||||
items.mapValues { entry ->
|
||||
val item = entry.value
|
||||
builder[entry.key.asName()] = when (item) {
|
||||
is MetaItem.ValueItem -> MetaItem.ValueItem<MetaBuilder>(item.value)
|
||||
is MetaItem.ValueItem -> item.value
|
||||
is MetaItem.NodeItem -> MetaItem.NodeItem(item.node.builder())
|
||||
}
|
||||
}
|
||||
|
@ -80,6 +80,9 @@ data class RegexpItemTransformationRule(
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A set of [TransformationRule] to either transform static meta or create dynamically updated [MutableMeta]
|
||||
*/
|
||||
inline class MetaTransformation(val transformations: Collection<TransformationRule>) {
|
||||
|
||||
/**
|
||||
@ -109,7 +112,7 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
|
||||
* 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 ->
|
||||
source.onChange(target) { name, _, newItem ->
|
||||
transformations.forEach { t ->
|
||||
if (t.matches(name, newItem)) {
|
||||
t.transformItem(name, newItem, target)
|
||||
@ -123,18 +126,29 @@ inline class MetaTransformation(val transformations: Collection<TransformationRu
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for a set of transformation rules
|
||||
*/
|
||||
class MetaTransformationBuilder {
|
||||
val transformations = HashSet<TransformationRule>()
|
||||
|
||||
/**
|
||||
* Keep all items with name satisfying the criteria
|
||||
*/
|
||||
fun keep(selector: (Name) -> Boolean) {
|
||||
transformations.add(KeepTransformationRule(selector))
|
||||
}
|
||||
|
||||
/**
|
||||
* Keep specific item (including its descendants)
|
||||
*/
|
||||
fun keep(name: Name) {
|
||||
keep{it == name}
|
||||
}
|
||||
|
||||
fun keepNode(name: Name){
|
||||
keep{it.startsWith(name)}
|
||||
fun move(from: Name, to: Name){
|
||||
transformations.add(
|
||||
SingleItemTransformationRule(from){ _, item -> setItem(to, item)}
|
||||
)
|
||||
}
|
||||
}
|
@ -10,15 +10,8 @@ internal data class MetaListener(
|
||||
|
||||
|
||||
interface MutableMeta<M : MutableMeta<M>> : MetaNode<M> {
|
||||
/**
|
||||
* Transform given meta to node type of this meta tree
|
||||
* @param name the name of the node where meta should be attached. Needed for correct assignment validators and styles
|
||||
* @param meta the node itself
|
||||
*/
|
||||
fun wrap(name: Name, meta: Meta): M
|
||||
|
||||
override val items: Map<NameToken, MetaItem<M>>
|
||||
operator fun set(name: Name, item: MetaItem<M>?)
|
||||
operator fun set(name: Name, item: MetaItem<*>?)
|
||||
fun onChange(owner: Any? = null, action: (Name, MetaItem<*>?, MetaItem<*>?) -> Unit)
|
||||
fun removeListener(owner: Any? = null)
|
||||
}
|
||||
@ -69,59 +62,70 @@ abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(),
|
||||
itemChanged(key.asName(), oldItem, newItem)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
protected fun wrapItem(item: MetaItem<*>?): MetaItem<M>? = when (item) {
|
||||
null -> null
|
||||
is MetaItem.ValueItem -> item as MetaItem<M>
|
||||
is MetaItem.NodeItem<*> -> MetaItem.NodeItem(wrapNode(item.node))
|
||||
}
|
||||
|
||||
/**
|
||||
* Transform given meta to node type of this meta tree
|
||||
*/
|
||||
protected abstract fun wrapNode(meta: Meta): M
|
||||
|
||||
/**
|
||||
* Create empty node
|
||||
*/
|
||||
internal abstract fun empty(): M
|
||||
|
||||
override operator fun set(name: Name, item: MetaItem<M>?) {
|
||||
override operator fun set(name: Name, item: MetaItem<*>?) {
|
||||
when (name.length) {
|
||||
0 -> error("Can't setValue meta item for empty name")
|
||||
1 -> {
|
||||
val token = name.first()!!
|
||||
replaceItem(token, get(name), item)
|
||||
replaceItem(token, get(name), wrapItem(item))
|
||||
}
|
||||
else -> {
|
||||
val token = name.first()!!
|
||||
//get existing or create new node. Query is ignored for new node
|
||||
val child = this.items[token]?.node
|
||||
?: empty().also { this[token.body.toName()] = MetaItem.NodeItem(it) }
|
||||
child[name.cutFirst()] = item
|
||||
if(items[token] == null){
|
||||
replaceItem(token,null, MetaItem.NodeItem(empty()))
|
||||
}
|
||||
items[token]?.node!![name.cutFirst()] = item
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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 MutableMeta<*>.remove(name: Name) = set(name, null)
|
||||
fun MutableMeta<*>.remove(name: String) = remove(name.toName())
|
||||
|
||||
fun <M : MutableMeta<M>> MutableMeta<M>.setValue(name: Name, value: Value) =
|
||||
fun MutableMeta<*>.setValue(name: Name, value: Value) =
|
||||
set(name, MetaItem.ValueItem(value))
|
||||
|
||||
fun <M : MutableMeta<M>> MutableMeta<M>.setValue(name: String, value: Value) =
|
||||
fun MutableMeta<*>.setValue(name: String, value: 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(name: String, item: MetaItem<M>) = set(name.toName(), item)
|
||||
|
||||
fun <M : MutableMeta<M>> MutableMeta<M>.setItem(name: Name, item: MetaItem<*>) {
|
||||
fun MutableMeta<*>.setItem(name: Name, item: MetaItem<*>?) {
|
||||
when (item) {
|
||||
is MetaItem.ValueItem<*> -> setValue(name, item.value)
|
||||
null -> remove(name)
|
||||
is MetaItem.ValueItem -> setValue(name, item.value)
|
||||
is MetaItem.NodeItem<*> -> setNode(name, item.node)
|
||||
}
|
||||
}
|
||||
|
||||
fun <M : MutableMeta<M>> MutableMeta<M>.setItem(name: String, item: MetaItem<*>) = setItem(name.toName(), item)
|
||||
fun MutableMeta<*>.setItem(name: String, item: MetaItem<*>?) = setItem(name.toName(), item)
|
||||
|
||||
fun <M : MutableMeta<M>> MutableMeta<M>.setNode(name: Name, node: Meta) =
|
||||
set(name, MetaItem.NodeItem(wrap(name, node)))
|
||||
fun MutableMeta<*>.setNode(name: Name, node: Meta) =
|
||||
set(name, MetaItem.NodeItem(node))
|
||||
|
||||
fun <M : MutableMeta<M>> MutableMeta<M>.setNode(name: String, node: Meta) = setNode(name.toName(), node)
|
||||
fun MutableMeta<*>.setNode(name: String, node: Meta) = setNode(name.toName(), node)
|
||||
|
||||
/**
|
||||
* Universal set method
|
||||
*/
|
||||
operator fun <M : MutableMeta<M>> MutableMeta<M>.set(name: Name, value: Any?) {
|
||||
operator fun MutableMeta<*>.set(name: Name, value: Any?) {
|
||||
when (value) {
|
||||
null -> remove(name)
|
||||
is MetaItem<*> -> setItem(name, value)
|
||||
@ -131,9 +135,9 @@ operator fun <M : MutableMeta<M>> MutableMeta<M>.set(name: Name, value: Any?) {
|
||||
}
|
||||
}
|
||||
|
||||
operator fun <M : MutableMeta<M>> M.set(name: NameToken, value: Any?) = set(name.asName(), value)
|
||||
operator fun MutableMeta<*>.set(name: NameToken, value: Any?) = set(name.asName(), value)
|
||||
|
||||
operator fun <M : MutableMeta<M>> M.set(key: String, value: Any?) = set(key.toName(), value)
|
||||
operator fun MutableMeta<*>.set(key: String, value: Any?) = set(key.toName(), value)
|
||||
|
||||
/**
|
||||
* Update existing mutable node with another node. The rules are following:
|
||||
@ -143,8 +147,7 @@ operator fun <M : MutableMeta<M>> M.set(key: String, value: Any?) = set(key.toNa
|
||||
*/
|
||||
fun <M : MutableMeta<M>> M.update(meta: Meta) {
|
||||
meta.items.forEach { entry ->
|
||||
val value = entry.value
|
||||
when (value) {
|
||||
when (val value = entry.value) {
|
||||
is MetaItem.ValueItem -> setValue(entry.key.asName(), value.value)
|
||||
is MetaItem.NodeItem -> (this[entry.key.asName()] as? MetaItem.NodeItem)?.node?.update(value.node)
|
||||
?: run { setNode(entry.key.asName(), value.node) }
|
||||
@ -154,10 +157,10 @@ fun <M : MutableMeta<M>> M.update(meta: Meta) {
|
||||
|
||||
/* Same name siblings generation */
|
||||
|
||||
fun <M : MutableMeta<M>> M.setIndexedItems(
|
||||
fun MutableMeta<*>.setIndexedItems(
|
||||
name: Name,
|
||||
items: Iterable<MetaItem<M>>,
|
||||
indexFactory: MetaItem<M>.(index: Int) -> String = { it.toString() }
|
||||
items: Iterable<MetaItem<*>>,
|
||||
indexFactory: MetaItem<*>.(index: Int) -> String = { it.toString() }
|
||||
) {
|
||||
val tokens = name.tokens.toMutableList()
|
||||
val last = tokens.last()
|
||||
@ -168,21 +171,21 @@ fun <M : MutableMeta<M>> M.setIndexedItems(
|
||||
}
|
||||
}
|
||||
|
||||
fun <M : MutableMeta<M>> M.setIndexed(
|
||||
fun MutableMeta<*>.setIndexed(
|
||||
name: Name,
|
||||
metas: Iterable<Meta>,
|
||||
indexFactory: MetaItem<M>.(index: Int) -> String = { it.toString() }
|
||||
indexFactory: MetaItem<*>.(index: Int) -> String = { it.toString() }
|
||||
) {
|
||||
setIndexedItems(name, metas.map { MetaItem.NodeItem(wrap(name, it)) }, indexFactory)
|
||||
setIndexedItems(name, metas.map { MetaItem.NodeItem(it) }, indexFactory)
|
||||
}
|
||||
|
||||
operator fun <M : MutableMeta<M>> M.set(name: Name, metas: Iterable<Meta>) = setIndexed(name, metas)
|
||||
operator fun <M : MutableMeta<M>> M.set(name: String, metas: Iterable<Meta>) = setIndexed(name.toName(), metas)
|
||||
operator fun MutableMeta<*>.set(name: Name, metas: Iterable<Meta>): Unit = setIndexed(name, metas)
|
||||
operator fun MutableMeta<*>.set(name: String, metas: Iterable<Meta>): Unit = setIndexed(name.toName(), metas)
|
||||
|
||||
/**
|
||||
* Append the node with a same-name-sibling, automatically generating numerical index
|
||||
*/
|
||||
fun <M : MutableMeta<M>> M.append(name: Name, value: Any?) {
|
||||
fun MutableMeta<*>.append(name: Name, value: Any?) {
|
||||
require(!name.isEmpty()) { "Name could not be empty for append operation" }
|
||||
val newIndex = name.last()!!.index
|
||||
if (newIndex.isNotEmpty()) {
|
||||
@ -193,4 +196,4 @@ fun <M : MutableMeta<M>> M.append(name: Name, value: Any?) {
|
||||
}
|
||||
}
|
||||
|
||||
fun <M : MutableMeta<M>> M.append(name: String, value: Any?) = append(name.toName(), value)
|
||||
fun MutableMeta<*>.append(name: String, value: Any?) = append(name.toName(), value)
|
@ -12,14 +12,11 @@ import kotlin.reflect.KProperty
|
||||
* @param style - the style
|
||||
*/
|
||||
class Styled(val base: Meta, val style: Config = Config().empty()) : AbstractMutableMeta<Styled>() {
|
||||
override fun wrap(name: Name, meta: Meta): Styled {
|
||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
override fun wrapNode(meta: Meta): Styled = Styled(meta)
|
||||
|
||||
override fun empty(): Styled {
|
||||
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
|
||||
}
|
||||
override fun empty(): Styled = Styled(EmptyMeta)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override val items: Map<NameToken, MetaItem<Styled>>
|
||||
get() = (base.items.keys + style.items.keys).associate { key ->
|
||||
val value = base.items[key]
|
||||
@ -27,10 +24,10 @@ class Styled(val base: Meta, val style: Config = Config().empty()) : AbstractMut
|
||||
val item: MetaItem<Styled> = when (value) {
|
||||
null -> when (styleValue) {
|
||||
null -> error("Should be unreachable")
|
||||
is MetaItem.ValueItem -> MetaItem.ValueItem(styleValue.value)
|
||||
is MetaItem.NodeItem -> MetaItem.NodeItem(Styled(style.empty(), styleValue.node))
|
||||
else -> styleValue.value as MetaItem<Styled>
|
||||
}
|
||||
is MetaItem.ValueItem -> MetaItem.ValueItem(value.value)
|
||||
is MetaItem.ValueItem -> value as MetaItem<Styled>
|
||||
is MetaItem.NodeItem -> MetaItem.NodeItem(
|
||||
Styled(value.node, styleValue?.node ?: Config.empty())
|
||||
)
|
||||
@ -38,7 +35,7 @@ class Styled(val base: Meta, val style: Config = Config().empty()) : AbstractMut
|
||||
key to item
|
||||
}
|
||||
|
||||
override fun set(name: Name, item: MetaItem<Styled>?) {
|
||||
override fun set(name: Name, item: MetaItem<*>?) {
|
||||
if (item == null) {
|
||||
style.remove(name)
|
||||
} else {
|
||||
|
@ -121,6 +121,11 @@ fun Name.withIndex(index: String): Name {
|
||||
return Name(tokens)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fast [String]-based accessor for item map
|
||||
*/
|
||||
operator fun <T> Map<NameToken, T>.get(body: String, query: String = ""): T? = get(NameToken(body, query))
|
||||
|
||||
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)
|
||||
|
||||
|
@ -35,12 +35,13 @@ class DynamicMeta(val obj: dynamic) : Meta {
|
||||
private fun isArray(@Suppress("UNUSED_PARAMETER") obj: dynamic): Boolean =
|
||||
js("Array.isArray(obj)") as Boolean
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun asItem(obj: dynamic): MetaItem<DynamicMeta>? {
|
||||
if (obj == null) return MetaItem.ValueItem(Null)
|
||||
return when (jsTypeOf(obj)) {
|
||||
"boolean" -> MetaItem.ValueItem(Value.of(obj as Boolean))
|
||||
"number" -> MetaItem.ValueItem(Value.of(obj as Number))
|
||||
"string" -> MetaItem.ValueItem(Value.of(obj as String))
|
||||
if (obj == null) return MetaItem.ValueItem(Null) as MetaItem<DynamicMeta>
|
||||
return when (jsTypeOf(obj as? Any)) {
|
||||
"boolean" -> MetaItem.ValueItem(Value.of(obj as Boolean)) as MetaItem<DynamicMeta>
|
||||
"number" -> MetaItem.ValueItem(Value.of(obj as Number)) as MetaItem<DynamicMeta>
|
||||
"string" -> MetaItem.ValueItem(Value.of(obj as String)) as MetaItem<DynamicMeta>
|
||||
"object" -> MetaItem.NodeItem(DynamicMeta(obj))
|
||||
else -> null
|
||||
}
|
||||
|
@ -61,13 +61,13 @@ class SimpleWorkspaceTest {
|
||||
allData()
|
||||
}
|
||||
joinByGroup<Int, Double> { context ->
|
||||
group("even", filter = { name, data -> name.toString().toInt() % 2 == 0 }) {
|
||||
group("even", filter = { name, _ -> name.toString().toInt() % 2 == 0 }) {
|
||||
result { data ->
|
||||
context.logger.info { "Starting even" }
|
||||
data.values.average()
|
||||
}
|
||||
}
|
||||
group("odd", filter = { name, data -> name.toString().toInt() % 2 == 1 }) {
|
||||
group("odd", filter = { name, _ -> name.toString().toInt() % 2 == 1 }) {
|
||||
result { data ->
|
||||
context.logger.info { "Starting odd" }
|
||||
data.values.average()
|
||||
|
Loading…
Reference in New Issue
Block a user