Fix meta node listeners and attachements
This commit is contained in:
parent
ce8074c104
commit
a71bb732da
@ -10,6 +10,7 @@
|
||||
### Removed
|
||||
|
||||
### Fixed
|
||||
- MutableMetaImpl attachment and checks
|
||||
|
||||
### Security
|
||||
## [0.5.0]
|
||||
|
@ -4,7 +4,7 @@ plugins {
|
||||
|
||||
allprojects {
|
||||
group = "space.kscience"
|
||||
version = "0.5.0"
|
||||
version = "0.5.1"
|
||||
}
|
||||
|
||||
subprojects {
|
||||
|
@ -261,6 +261,13 @@ public operator fun <M : MutableTypedMeta<M>> MutableTypedMeta<M>.set(name: Name
|
||||
}
|
||||
}
|
||||
|
||||
private fun ObservableMeta.adoptBy(parent: MutableMetaImpl, key: NameToken) {
|
||||
if (this === parent) error("Can't attach a node to itself")
|
||||
onChange(parent) { name ->
|
||||
parent.invalidate(key + name)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A general implementation of mutable [Meta] which implements both [MutableTypedMeta] and [ObservableMeta].
|
||||
* The implementation uses blocking synchronization on mutation on JVM
|
||||
@ -280,17 +287,11 @@ private class MutableMetaImpl(
|
||||
|
||||
private val children: LinkedHashMap<NameToken, ObservableMutableMeta> =
|
||||
LinkedHashMap(children.mapValues { (key, meta) ->
|
||||
MutableMetaImpl(meta.value, meta.items).apply { adoptBy(this, key) }
|
||||
MutableMetaImpl(meta.value, meta.items).also { it.adoptBy(this, key) }
|
||||
})
|
||||
|
||||
override val items: Map<NameToken, ObservableMutableMeta> get() = children
|
||||
|
||||
private fun ObservableMeta.adoptBy(parent: MutableMetaImpl, key: NameToken) {
|
||||
onChange(parent) { name ->
|
||||
parent.invalidate(key + name)
|
||||
}
|
||||
}
|
||||
|
||||
@DFExperimental
|
||||
override fun attach(name: Name, node: ObservableMutableMeta) {
|
||||
when (name.length) {
|
||||
@ -338,9 +339,14 @@ private class MutableMetaImpl(
|
||||
}
|
||||
|
||||
private fun wrapItem(meta: Meta): MutableMetaImpl =
|
||||
MutableMetaImpl(meta.value, meta.items.mapValuesTo(LinkedHashMap()) { wrapItem(it.value) })
|
||||
|
||||
meta as? MutableMetaImpl ?: MutableMetaImpl(
|
||||
meta.value,
|
||||
meta.items.mapValuesTo(LinkedHashMap()) {
|
||||
wrapItem(it.value)
|
||||
}
|
||||
)
|
||||
|
||||
@Synchronized
|
||||
override fun setMeta(name: Name, node: Meta?) {
|
||||
val oldItem: ObservableMutableMeta? = get(name)
|
||||
if (oldItem != node) {
|
||||
@ -348,13 +354,24 @@ private class MutableMetaImpl(
|
||||
0 -> error("Can't set a meta with empty name")
|
||||
1 -> {
|
||||
val token = name.firstOrNull()!!
|
||||
replaceItem(token, oldItem, node?.let { wrapItem(node) })
|
||||
//remove child and invalidate if argument is null
|
||||
if (node == null) {
|
||||
children.remove(token)?.removeListener(this)
|
||||
// old item is not null otherwise we can't be here
|
||||
invalidate(name)
|
||||
} else {
|
||||
val newNode = wrapItem(node)
|
||||
newNode.adoptBy(this, token)
|
||||
children[token] = newNode
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
val token = name.firstOrNull()!!
|
||||
//get existing or create new node. Index is ignored for new node
|
||||
//get existing or create new node.
|
||||
if (items[token] == null) {
|
||||
replaceItem(token, null, MutableMetaImpl(null))
|
||||
val newNode = MutableMetaImpl(null)
|
||||
newNode.adoptBy(this, token)
|
||||
children[token] = newNode
|
||||
}
|
||||
items[token]?.setMeta(name.cutFirst(), node)
|
||||
}
|
||||
@ -384,19 +401,6 @@ public fun MutableMeta.append(name: Name, value: Value): Unit = append(name, Met
|
||||
|
||||
public fun MutableMeta.append(key: String, value: Value): Unit = append(Name.parse(key), value)
|
||||
|
||||
///**
|
||||
// * Apply existing node with given [builder] or create a new element with it.
|
||||
// */
|
||||
//@DFExperimental
|
||||
//public fun MutableMeta.edit(name: Name, builder: MutableMeta.() -> Unit) {
|
||||
// val item = when (val existingItem = get(name)) {
|
||||
// null -> MutableMeta().also { set(name, it) }
|
||||
// is MetaItemNode<MutableMeta> -> existingItem.node
|
||||
// else -> error("Can't edit value meta item")
|
||||
// }
|
||||
// item.apply(builder)
|
||||
//}
|
||||
|
||||
/**
|
||||
* Create a mutable copy of this meta. The copy is created even if the Meta is already mutable
|
||||
*/
|
||||
|
@ -48,7 +48,7 @@ public interface ObservableMutableMeta : ObservableMeta, MutableMeta, MutableTyp
|
||||
}
|
||||
|
||||
internal abstract class AbstractObservableMeta : ObservableMeta {
|
||||
private val listeners = HashSet<MetaListener>()
|
||||
private val listeners = ArrayList<MetaListener>()
|
||||
|
||||
override fun invalidate(name: Name) {
|
||||
listeners.forEach { it.callback(this, name) }
|
||||
|
@ -68,7 +68,7 @@ private class ObservableMetaWrapper(
|
||||
override fun attach(name: Name, node: ObservableMutableMeta) {
|
||||
set(name, node)
|
||||
node.onChange(this) { changeName ->
|
||||
setMeta(name + changeName, node[changeName])
|
||||
setMeta(name + changeName, this[changeName])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user