Partially fixed a bug with MutableMeta
observable wrappers.
This commit is contained in:
parent
5461a83417
commit
946ac88480
@ -3,6 +3,7 @@
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
- Wasm artifacts
|
||||
|
||||
### Changed
|
||||
|
||||
@ -11,6 +12,7 @@
|
||||
### Removed
|
||||
|
||||
### Fixed
|
||||
- Partially fixed a bug with `MutableMeta` observable wrappers.
|
||||
|
||||
### Security
|
||||
|
||||
|
@ -8,12 +8,14 @@ kscience {
|
||||
jvm()
|
||||
js()
|
||||
native()
|
||||
wasm()
|
||||
useCoroutines()
|
||||
useSerialization()
|
||||
dependencies {
|
||||
commonMain {
|
||||
api(project(":dataforge-meta"))
|
||||
api(spclibs.atomicfu)
|
||||
}
|
||||
dependencies(jvmMain){
|
||||
jvmMain{
|
||||
api(kotlin("reflect"))
|
||||
api("org.slf4j:slf4j-api:1.7.30")
|
||||
}
|
||||
|
@ -0,0 +1,3 @@
|
||||
package space.kscience.dataforge.context
|
||||
|
||||
internal actual fun getGlobalLoggerFactory(): PluginFactory<out LogManager> = DefaultLogManager
|
@ -6,9 +6,11 @@ kscience{
|
||||
jvm()
|
||||
js()
|
||||
native()
|
||||
wasm()
|
||||
useCoroutines()
|
||||
dependencies {
|
||||
api(project(":dataforge-meta"))
|
||||
api(spclibs.atomicfu)
|
||||
api(projects.dataforgeMeta)
|
||||
api(kotlin("reflect"))
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import kotlinx.coroutines.test.runTest
|
||||
import org.junit.jupiter.api.Test
|
||||
import space.kscience.dataforge.actions.Action
|
||||
import space.kscience.dataforge.actions.invoke
|
||||
import space.kscience.dataforge.actions.map
|
||||
import space.kscience.dataforge.actions.mapping
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@ -20,7 +20,7 @@ internal class ActionsTest {
|
||||
}
|
||||
}
|
||||
|
||||
val plusOne = Action.map<Int, Int> {
|
||||
val plusOne = Action.mapping<Int, Int> {
|
||||
result { it + 1 }
|
||||
}
|
||||
val result = plusOne(data)
|
||||
@ -31,7 +31,7 @@ internal class ActionsTest {
|
||||
fun testDynamicMapAction() = runTest {
|
||||
val data: DataSourceBuilder<Int> = DataSource()
|
||||
|
||||
val plusOne = Action.map<Int, Int> {
|
||||
val plusOne = Action.mapping<Int, Int> {
|
||||
result { it + 1 }
|
||||
}
|
||||
|
||||
|
@ -4,12 +4,13 @@ plugins {
|
||||
|
||||
description = "IO module"
|
||||
|
||||
val ioVersion = "0.2.1"
|
||||
val ioVersion = "0.3.0"
|
||||
|
||||
kscience {
|
||||
jvm()
|
||||
js()
|
||||
native()
|
||||
wasm()
|
||||
useSerialization()
|
||||
useSerialization(sourceSet = space.kscience.gradle.DependencySourceSet.TEST) {
|
||||
cbor()
|
||||
|
@ -724,6 +724,7 @@ public final class space/kscience/dataforge/meta/descriptors/MetaDescriptorBuild
|
||||
public final fun getAttributes ()Lspace/kscience/dataforge/meta/MutableMeta;
|
||||
public final fun getChildren ()Ljava/util/Map;
|
||||
public final fun getDefault ()Lspace/kscience/dataforge/meta/Value;
|
||||
public final fun getDescription ()Ljava/lang/String;
|
||||
public final fun getIndexKey ()Ljava/lang/String;
|
||||
public final fun getInfo ()Ljava/lang/String;
|
||||
public final fun getMultiple ()Z
|
||||
@ -737,6 +738,7 @@ public final class space/kscience/dataforge/meta/descriptors/MetaDescriptorBuild
|
||||
public final fun setAttributes (Lspace/kscience/dataforge/meta/MutableMeta;)V
|
||||
public final fun setChildren (Ljava/util/Map;)V
|
||||
public final fun setDefault (Lspace/kscience/dataforge/meta/Value;)V
|
||||
public final fun setDescription (Ljava/lang/String;)V
|
||||
public final fun setIndexKey (Ljava/lang/String;)V
|
||||
public final fun setInfo (Ljava/lang/String;)V
|
||||
public final fun setMultiple (Z)V
|
||||
@ -903,7 +905,7 @@ public abstract interface annotation class space/kscience/dataforge/misc/DFExper
|
||||
public abstract interface annotation class space/kscience/dataforge/misc/DFInternal : java/lang/annotation/Annotation {
|
||||
}
|
||||
|
||||
public abstract interface annotation class space/kscience/dataforge/misc/DfId : java/lang/annotation/Annotation {
|
||||
public abstract interface annotation class space/kscience/dataforge/misc/DfType : java/lang/annotation/Annotation {
|
||||
public abstract fun id ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
@ -944,6 +946,7 @@ public final class space/kscience/dataforge/names/NameKt {
|
||||
public static final fun asName (Lspace/kscience/dataforge/names/NameToken;)Lspace/kscience/dataforge/names/Name;
|
||||
public static final fun cutFirst (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/names/Name;
|
||||
public static final fun cutLast (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/names/Name;
|
||||
public static final fun endsWith (Lspace/kscience/dataforge/names/Name;Ljava/lang/String;)Z
|
||||
public static final fun endsWith (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/names/Name;)Z
|
||||
public static final fun endsWith (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/names/NameToken;)Z
|
||||
public static final fun first (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/names/NameToken;
|
||||
@ -966,6 +969,7 @@ public final class space/kscience/dataforge/names/NameKt {
|
||||
public static final fun removeHeadOrNull (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/names/Name;
|
||||
public static final fun replaceLast (Lspace/kscience/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/names/Name;
|
||||
public static final fun set (Ljava/util/Map;Ljava/lang/String;Ljava/lang/Object;)V
|
||||
public static final fun startsWith (Lspace/kscience/dataforge/names/Name;Ljava/lang/String;)Z
|
||||
public static final fun startsWith (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/names/Name;)Z
|
||||
public static final fun startsWith (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/names/NameToken;)Z
|
||||
public static final fun withIndex (Lspace/kscience/dataforge/names/Name;Ljava/lang/String;)Lspace/kscience/dataforge/names/Name;
|
||||
|
@ -6,6 +6,7 @@ kscience {
|
||||
jvm()
|
||||
js()
|
||||
native()
|
||||
wasm()
|
||||
useSerialization{
|
||||
json()
|
||||
}
|
||||
|
@ -6,60 +6,71 @@ import space.kscience.dataforge.names.*
|
||||
|
||||
/**
|
||||
* A class that takes [MutableMeta] provider and adds obsevability on top of that
|
||||
*
|
||||
* TODO rewrite to properly work with detached nodes
|
||||
*/
|
||||
private class ObservableMetaWrapper(
|
||||
val root: MutableMeta,
|
||||
val absoluteName: Name,
|
||||
val nodeName: Name,
|
||||
val listeners: MutableSet<MetaListener>,
|
||||
) : ObservableMutableMeta {
|
||||
override val items: Map<NameToken, ObservableMutableMeta>
|
||||
get() = root.items.keys.associateWith {
|
||||
ObservableMetaWrapper(root, absoluteName + it, listeners)
|
||||
ObservableMetaWrapper(root, nodeName + it, listeners)
|
||||
}
|
||||
|
||||
override fun get(name: Name): ObservableMutableMeta? =
|
||||
root.get(name)?.let { ObservableMetaWrapper(root, this.absoluteName + name, listeners) }
|
||||
override fun get(name: Name): ObservableMutableMeta? = if (root[nodeName + name] == null) {
|
||||
null
|
||||
} else {
|
||||
ObservableMetaWrapper(root, nodeName + name, listeners)
|
||||
}
|
||||
|
||||
@ThreadSafe
|
||||
override fun onChange(owner: Any?, callback: Meta.(name: Name) -> Unit) {
|
||||
listeners.add(
|
||||
MetaListener(Pair(owner, absoluteName)) { name ->
|
||||
if (name.startsWith(absoluteName)) {
|
||||
(this[absoluteName] ?: Meta.EMPTY).callback(name.removeFirstOrNull(absoluteName)!!)
|
||||
MetaListener(Pair(owner, nodeName)) { fullName ->
|
||||
if (fullName.startsWith(nodeName)) {
|
||||
root[nodeName]?.callback(fullName.removeFirstOrNull(nodeName)!!)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
override fun removeListener(owner: Any?) {
|
||||
listeners.removeAll { it.owner === Pair(owner, absoluteName) }
|
||||
listeners.removeAll { it.owner === Pair(owner, nodeName) }
|
||||
}
|
||||
|
||||
override fun invalidate(name: Name) {
|
||||
listeners.forEach { it.callback(this, name) }
|
||||
listeners.forEach { it.callback(this, nodeName + name) }
|
||||
}
|
||||
|
||||
override var value: Value?
|
||||
get() = root.value
|
||||
get() = root[nodeName]?.value
|
||||
set(value) {
|
||||
root.value = value
|
||||
root.getOrCreate(nodeName).value = value
|
||||
invalidate(Name.EMPTY)
|
||||
}
|
||||
|
||||
override fun getOrCreate(name: Name): ObservableMutableMeta =
|
||||
ObservableMetaWrapper(root, this.absoluteName + name, listeners)
|
||||
ObservableMetaWrapper(root, nodeName + name, listeners)
|
||||
|
||||
override fun set(name: Name, node: Meta?) {
|
||||
fun removeNode(name: Name): Meta? {
|
||||
val oldMeta = get(name)
|
||||
//don't forget to remove listener
|
||||
oldMeta?.removeListener(this)
|
||||
root.set(absoluteName + name, node)
|
||||
|
||||
return oldMeta
|
||||
}
|
||||
|
||||
override fun set(name: Name, node: Meta?) {
|
||||
val oldMeta = removeNode(name)
|
||||
root[nodeName + name] = node
|
||||
if (oldMeta != node) {
|
||||
invalidate(name)
|
||||
}
|
||||
}
|
||||
|
||||
override fun toMeta(): Meta = root[absoluteName]?.toMeta() ?: Meta.EMPTY
|
||||
override fun toMeta(): Meta = root[nodeName]?.toMeta() ?: Meta.EMPTY
|
||||
|
||||
override fun toString(): String = Meta.toString(this)
|
||||
override fun equals(other: Any?): Boolean = Meta.equals(this, other as? Meta)
|
||||
|
@ -216,9 +216,13 @@ public fun Name.endsWith(token: NameToken): Boolean = lastOrNull() == token
|
||||
public fun Name.startsWith(name: Name): Boolean =
|
||||
this.length >= name.length && (this == name || tokens.subList(0, name.length) == name.tokens)
|
||||
|
||||
public fun Name.startsWith(name: String): Boolean = startsWith(name.parseAsName())
|
||||
|
||||
public fun Name.endsWith(name: Name): Boolean =
|
||||
this.length >= name.length && (this == name || tokens.subList(length - name.length, length) == name.tokens)
|
||||
|
||||
public fun Name.endsWith(name: String): Boolean = endsWith(name.parseAsName())
|
||||
|
||||
/**
|
||||
* if [this] starts with given [head] name, returns the reminder of the name (could be empty). Otherwise, returns null
|
||||
*/
|
||||
|
@ -0,0 +1,49 @@
|
||||
package space.kscience.dataforge.meta
|
||||
|
||||
import space.kscience.dataforge.names.startsWith
|
||||
import kotlin.test.Ignore
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class ObservableMetaTest {
|
||||
|
||||
@Test
|
||||
fun asObservable() {
|
||||
val meta = MutableMeta {
|
||||
"data" put {
|
||||
"x" put ListValue(1, 2, 3)
|
||||
"y" put ListValue(5, 6, 7)
|
||||
"type" put "scatter"
|
||||
}
|
||||
}.asObservable()
|
||||
|
||||
assertEquals("scatter", meta["data.type"].string)
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore
|
||||
fun detachNode() {
|
||||
val meta = MutableMeta {
|
||||
"data" put {
|
||||
"x" put ListValue(1, 2, 3)
|
||||
"y" put ListValue(5, 6, 7)
|
||||
"type" put "scatter"
|
||||
}
|
||||
}.asObservable()
|
||||
|
||||
var collector: Value? = null
|
||||
|
||||
meta.onChange(null) { name ->
|
||||
if (name.startsWith("data")) {
|
||||
collector = get("data.z")?.value
|
||||
}
|
||||
}
|
||||
|
||||
val data = meta["data"]!!
|
||||
|
||||
meta.remove("data")
|
||||
|
||||
data["z"] = ListValue(2, 5, 7)
|
||||
assertEquals(null, collector)
|
||||
}
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
package space.kscience.dataforge.misc
|
||||
import kotlin.js.unsafeCast as unsafeCastJs
|
||||
|
||||
@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
|
||||
public actual inline fun <T> Any?.unsafeCast(): T = this.unsafeCastJs<T>()
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
public actual inline fun <T> Any?.unsafeCast(): T = unsafeCastJs<T>()
|
@ -1,4 +1,4 @@
|
||||
package space.kscience.dataforge.misc
|
||||
|
||||
@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public actual inline fun <T> Any?.unsafeCast(): T = this as T
|
@ -0,0 +1,4 @@
|
||||
package space.kscience.dataforge.misc
|
||||
|
||||
@Suppress("UNCHECKED_CAST", "NOTHING_TO_INLINE")
|
||||
public actual inline fun <T> Any?.unsafeCast(): T = this as T
|
@ -4,15 +4,15 @@ plugins {
|
||||
|
||||
kscience{
|
||||
jvm()
|
||||
dependencies {
|
||||
commonMain {
|
||||
api(projects.dataforgeWorkspace)
|
||||
implementation(kotlin("scripting-common"))
|
||||
}
|
||||
dependencies(jvmMain){
|
||||
jvmMain{
|
||||
implementation(kotlin("scripting-jvm-host"))
|
||||
implementation(kotlin("scripting-jvm"))
|
||||
}
|
||||
dependencies(jvmTest){
|
||||
jvmTest{
|
||||
implementation(spclibs.logback.classic)
|
||||
}
|
||||
}
|
||||
|
@ -2,29 +2,27 @@ plugins {
|
||||
id("space.kscience.gradle.mpp")
|
||||
}
|
||||
|
||||
kscience{
|
||||
kscience {
|
||||
jvm()
|
||||
js()
|
||||
native()
|
||||
wasm()
|
||||
useCoroutines()
|
||||
useSerialization{
|
||||
useSerialization {
|
||||
protobuf()
|
||||
}
|
||||
commonMain{
|
||||
dependencies {
|
||||
api(projects.dataforgeContext)
|
||||
api(projects.dataforgeData)
|
||||
api(projects.dataforgeIo)
|
||||
}
|
||||
commonMain {
|
||||
api(projects.dataforgeContext)
|
||||
api(projects.dataforgeData)
|
||||
api(projects.dataforgeIo)
|
||||
|
||||
}
|
||||
jvmTest{
|
||||
dependencies {
|
||||
implementation(spclibs.logback.classic)
|
||||
implementation(projects.dataforgeIo.dataforgeIoYaml)
|
||||
}
|
||||
jvmTest {
|
||||
implementation(spclibs.logback.classic)
|
||||
implementation(projects.dataforgeIo.dataforgeIoYaml)
|
||||
}
|
||||
}
|
||||
|
||||
readme{
|
||||
readme {
|
||||
maturity = space.kscience.gradle.Maturity.EXPERIMENTAL
|
||||
}
|
@ -6,5 +6,5 @@ kotlin.mpp.stability.nowarn=true
|
||||
kotlin.incremental.js.ir=true
|
||||
kotlin.native.ignoreDisabledTargets=true
|
||||
|
||||
toolsVersion=0.15.1-kotlin-1.9.21
|
||||
toolsVersion=0.15.2-kotlin-1.9.21
|
||||
#kotlin.experimental.tryK2=true
|
Loading…
Reference in New Issue
Block a user