Simplified mutable meta hierarchy

This commit is contained in:
Alexander Nozik 2019-05-28 19:24:23 +03:00
parent cffb02d483
commit 59c46344fa
6 changed files with 42 additions and 33 deletions

View File

@ -9,7 +9,7 @@ import hep.dataforge.names.asName
/**
* Mutable meta representing object state
*/
open class Config : MutableMetaNode<Config>() {
open class Config : AbstractMutableMeta<Config>() {
/**
* Attach configuration node instead of creating one

View File

@ -327,7 +327,7 @@ class MutableSafeEnumvDelegate<M : MutableMeta<M>, E : Enum<E>>(
//Child node delegate
class MutableNodeDelegate<M : MutableMetaNode<M>>(
class MutableNodeDelegate<M : MutableMeta<M>>(
val meta: M,
private val key: String? = null
) : ReadWriteProperty<Any?, Meta?> {
@ -340,7 +340,7 @@ class MutableNodeDelegate<M : MutableMetaNode<M>>(
}
}
class MutableMorphDelegate<M : MutableMetaNode<M>, T : Configurable>(
class MutableMorphDelegate<M : MutableMeta<M>, T : Configurable>(
val meta: M,
private val key: String? = null,
private val converter: (Meta) -> T
@ -390,7 +390,7 @@ fun <M : MutableMeta<M>> M.boolean(default: Boolean? = null, key: String? = null
fun <M : MutableMeta<M>> M.number(default: Number? = null, key: String? = null) =
MutableNumberDelegate(this, key, default)
fun <M : MutableMetaNode<M>> M.node(key: String? = null) = MutableNodeDelegate(this, key)
fun <M : MutableMeta<M>> M.node(key: String? = null) = MutableNodeDelegate(this, key)
@JvmName("safeString")
fun <M : MutableMeta<M>> M.string(default: String, key: String? = null) =

View File

@ -7,7 +7,7 @@ import hep.dataforge.values.Value
/**
* DSL builder for meta. Is not intended to store mutable state
*/
class MetaBuilder : MutableMetaNode<MetaBuilder>() {
class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
override fun wrap(name: Name, meta: Meta): MetaBuilder = meta.builder()
override fun empty(): MetaBuilder = MetaBuilder()

View File

@ -23,7 +23,7 @@ interface TransformationRule {
/**
* Apply transformation for a single item (Node or Value) and return resulting tree with absolute path
*/
fun <M : MutableMetaNode<M>> transformItem(name: Name, item: MetaItem<*>?, target: M): Unit
fun <M : MutableMeta<M>> transformItem(name: Name, item: MetaItem<*>?, target: M): Unit
}
/**
@ -36,7 +36,7 @@ data class SelfTransformationRule(val name: Name) : TransformationRule {
override fun selectItems(meta: Meta): Sequence<Name> = sequenceOf(name)
override fun <M : MutableMetaNode<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
}
}
@ -47,7 +47,7 @@ data class SelfTransformationRule(val name: Name) : TransformationRule {
data class SingleItemTransformationRule(
val from: Name,
val to: Name,
val transform: MutableMetaNode<*>.(MetaItem<*>?) -> Unit
val transform: MutableMeta<*>.(MetaItem<*>?) -> Unit
) : TransformationRule {
override fun matches(name: Name, item: MetaItem<*>?): Boolean {
return name == from
@ -55,7 +55,7 @@ data class SingleItemTransformationRule(
override fun selectItems(meta: Meta): Sequence<Name> = sequenceOf(from)
override fun <M : MutableMetaNode<M>> transformItem(name: Name, item: MetaItem<*>?, target: M) {
override fun <M : MutableMeta<M>> transformItem(name: Name, item: MetaItem<*>?, target: M) {
if (name == this.from) {
target.transform(item)
}

View File

@ -10,6 +10,13 @@ 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>?)
fun onChange(owner: Any? = null, action: (Name, MetaItem<*>?, MetaItem<*>?) -> Unit)
@ -21,7 +28,7 @@ interface MutableMeta<M : MutableMeta<M>> : MetaNode<M> {
*
* Changes in Meta are not thread safe.
*/
abstract class MutableMetaNode<M : MutableMetaNode<M>> : AbstractMetaNode<M>(), MutableMeta<M> {
abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(), MutableMeta<M> {
private val listeners = HashSet<MetaListener>()
/**
@ -62,13 +69,6 @@ abstract class MutableMetaNode<M : MutableMetaNode<M>> : AbstractMetaNode<M>(),
itemChanged(key.asName(), oldItem, newItem)
}
/**
* 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
*/
internal abstract fun wrap(name: Name, meta: Meta): M
/**
* Create empty node
*/
@ -97,30 +97,31 @@ fun <M : MutableMeta<M>> MutableMeta<M>.remove(name: String) = remove(name.toNam
fun <M : MutableMeta<M>> MutableMeta<M>.setValue(name: Name, value: Value) =
set(name, MetaItem.ValueItem(value))
fun <M : MutableMeta<M>> MutableMeta<M>.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 : MutableMetaNode<M>> MutableMetaNode<M>.setItem(name: Name, item: MetaItem<*>) {
fun <M : MutableMeta<M>> MutableMeta<M>.setItem(name: Name, item: MetaItem<*>) {
when (item) {
is MetaItem.ValueItem<*> -> setValue(name, item.value)
is MetaItem.NodeItem<*> -> setNode(name, item.node)
}
}
fun <M : MutableMetaNode<M>> MutableMetaNode<M>.setItem(name: String, item: MetaItem<*>) = setItem(name.toName(), item)
fun <M : MutableMeta<M>> MutableMeta<M>.setItem(name: String, item: MetaItem<*>) = setItem(name.toName(), item)
fun <M : MutableMetaNode<M>> MutableMetaNode<M>.setNode(name: Name, node: Meta) =
fun <M : MutableMeta<M>> MutableMeta<M>.setNode(name: Name, node: Meta) =
set(name, MetaItem.NodeItem(wrap(name, node)))
fun <M : MutableMetaNode<M>> MutableMetaNode<M>.setNode(name: String, node: Meta) = setNode(name.toName(), node)
fun <M : MutableMeta<M>> MutableMeta<M>.setNode(name: String, node: Meta) = setNode(name.toName(), node)
/**
* Universal set method
*/
operator fun <M : MutableMetaNode<M>> MutableMetaNode<M>.set(name: Name, value: Any?) {
operator fun <M : MutableMeta<M>> MutableMeta<M>.set(name: Name, value: Any?) {
when (value) {
null -> remove(name)
is MetaItem<*> -> setItem(name, value)
@ -130,9 +131,9 @@ operator fun <M : MutableMetaNode<M>> MutableMetaNode<M>.set(name: Name, value:
}
}
operator fun <M : MutableMetaNode<M>> M.set(name: NameToken, value: Any?) = set(name.asName(), value)
operator fun <M : MutableMeta<M>> M.set(name: NameToken, value: Any?) = set(name.asName(), value)
operator fun <M : MutableMetaNode<M>> M.set(key: String, value: Any?) = set(key.toName(), value)
operator fun <M : MutableMeta<M>> M.set(key: String, value: Any?) = set(key.toName(), value)
/**
* Update existing mutable node with another node. The rules are following:
@ -140,7 +141,7 @@ operator fun <M : MutableMetaNode<M>> M.set(key: String, value: Any?) = set(key.
* * node updates node and replaces anything but node
* * node list updates node list if number of nodes in the list is the same and replaces anything otherwise
*/
fun <M : MutableMetaNode<M>> M.update(meta: Meta) {
fun <M : MutableMeta<M>> M.update(meta: Meta) {
meta.items.forEach { entry ->
val value = entry.value
when (value) {
@ -153,7 +154,7 @@ fun <M : MutableMetaNode<M>> M.update(meta: Meta) {
/* Same name siblings generation */
fun <M : MutableMeta<M>> M.setIndexed(
fun <M : MutableMeta<M>> M.setIndexedItems(
name: Name,
items: Iterable<MetaItem<M>>,
indexFactory: MetaItem<M>.(index: Int) -> String = { it.toString() }
@ -167,21 +168,21 @@ fun <M : MutableMeta<M>> M.setIndexed(
}
}
fun <M : MutableMetaNode<M>> M.setIndexed(
fun <M : MutableMeta<M>> M.setIndexed(
name: Name,
metas: Iterable<Meta>,
indexFactory: MetaItem<M>.(index: Int) -> String = { it.toString() }
) {
setIndexed(name, metas.map { MetaItem.NodeItem(wrap(name, it)) }, indexFactory)
setIndexedItems(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)
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)
/**
* Append the node with a same-name-sibling, automatically generating numerical index
*/
fun <M : MutableMetaNode<M>> M.append(name: Name, value: Any?) {
fun <M : MutableMeta<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()) {
@ -192,4 +193,4 @@ fun <M : MutableMetaNode<M>> M.append(name: Name, value: Any?) {
}
}
fun <M : MutableMetaNode<M>> M.append(name: String, value: Any?) = append(name.toName(), value)
fun <M : MutableMeta<M>> M.append(name: String, value: Any?) = append(name.toName(), value)

View File

@ -11,7 +11,15 @@ import kotlin.reflect.KProperty
* @param base - unchangeable base
* @param style - the style
*/
class Styled(val base: Meta, val style: Config = Config().empty()) : MutableMeta<Styled> {
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 empty(): Styled {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
override val items: Map<NameToken, MetaItem<Styled>>
get() = (base.items.keys + style.items.keys).associate { key ->
val value = base.items[key]