Fix meta node listeners and attachements
This commit is contained in:
parent
ce8074c104
commit
a71bb732da
@ -10,6 +10,7 @@
|
|||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
- MutableMetaImpl attachment and checks
|
||||||
|
|
||||||
### Security
|
### Security
|
||||||
## [0.5.0]
|
## [0.5.0]
|
||||||
|
@ -4,7 +4,7 @@ plugins {
|
|||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
group = "space.kscience"
|
group = "space.kscience"
|
||||||
version = "0.5.0"
|
version = "0.5.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
subprojects {
|
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].
|
* A general implementation of mutable [Meta] which implements both [MutableTypedMeta] and [ObservableMeta].
|
||||||
* The implementation uses blocking synchronization on mutation on JVM
|
* The implementation uses blocking synchronization on mutation on JVM
|
||||||
@ -280,17 +287,11 @@ private class MutableMetaImpl(
|
|||||||
|
|
||||||
private val children: LinkedHashMap<NameToken, ObservableMutableMeta> =
|
private val children: LinkedHashMap<NameToken, ObservableMutableMeta> =
|
||||||
LinkedHashMap(children.mapValues { (key, meta) ->
|
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
|
override val items: Map<NameToken, ObservableMutableMeta> get() = children
|
||||||
|
|
||||||
private fun ObservableMeta.adoptBy(parent: MutableMetaImpl, key: NameToken) {
|
|
||||||
onChange(parent) { name ->
|
|
||||||
parent.invalidate(key + name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@DFExperimental
|
@DFExperimental
|
||||||
override fun attach(name: Name, node: ObservableMutableMeta) {
|
override fun attach(name: Name, node: ObservableMutableMeta) {
|
||||||
when (name.length) {
|
when (name.length) {
|
||||||
@ -338,9 +339,14 @@ private class MutableMetaImpl(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun wrapItem(meta: Meta): 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?) {
|
override fun setMeta(name: Name, node: Meta?) {
|
||||||
val oldItem: ObservableMutableMeta? = get(name)
|
val oldItem: ObservableMutableMeta? = get(name)
|
||||||
if (oldItem != node) {
|
if (oldItem != node) {
|
||||||
@ -348,13 +354,24 @@ private class MutableMetaImpl(
|
|||||||
0 -> error("Can't set a meta with empty name")
|
0 -> error("Can't set a meta with empty name")
|
||||||
1 -> {
|
1 -> {
|
||||||
val token = name.firstOrNull()!!
|
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 -> {
|
else -> {
|
||||||
val token = name.firstOrNull()!!
|
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) {
|
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)
|
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)
|
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
|
* 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 {
|
internal abstract class AbstractObservableMeta : ObservableMeta {
|
||||||
private val listeners = HashSet<MetaListener>()
|
private val listeners = ArrayList<MetaListener>()
|
||||||
|
|
||||||
override fun invalidate(name: Name) {
|
override fun invalidate(name: Name) {
|
||||||
listeners.forEach { it.callback(this, name) }
|
listeners.forEach { it.callback(this, name) }
|
||||||
|
@ -68,7 +68,7 @@ private class ObservableMetaWrapper(
|
|||||||
override fun attach(name: Name, node: ObservableMutableMeta) {
|
override fun attach(name: Name, node: ObservableMutableMeta) {
|
||||||
set(name, node)
|
set(name, node)
|
||||||
node.onChange(this) { changeName ->
|
node.onChange(this) { changeName ->
|
||||||
setMeta(name + changeName, node[changeName])
|
setMeta(name + changeName, this[changeName])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user