Skip to content

Commit

Permalink
Partially fixed a bug with MutableMeta observable wrappers.
Browse files Browse the repository at this point in the history
  • Loading branch information
altavir committed Dec 5, 2023
1 parent 5461a83 commit 946ac88
Show file tree
Hide file tree
Showing 17 changed files with 125 additions and 44 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## Unreleased

### Added
- Wasm artifacts

### Changed

Expand All @@ -11,6 +12,7 @@
### Removed

### Fixed
- Partially fixed a bug with `MutableMeta` observable wrappers.

### Security

Expand Down
6 changes: 4 additions & 2 deletions dataforge-context/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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")
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
package space.kscience.dataforge.context

internal actual fun getGlobalLoggerFactory(): PluginFactory<out LogManager> = DefaultLogManager
4 changes: 3 additions & 1 deletion dataforge-data/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@ kscience{
jvm()
js()
native()
wasm()
useCoroutines()
dependencies {
api(project(":dataforge-meta"))
api(spclibs.atomicfu)
api(projects.dataforgeMeta)
api(kotlin("reflect"))
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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)
Expand All @@ -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 }
}

Expand Down
3 changes: 2 additions & 1 deletion dataforge-io/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
6 changes: 5 additions & 1 deletion dataforge-meta/api/dataforge-meta.api
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions dataforge-meta/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ kscience {
jvm()
js()
native()
wasm()
useSerialization{
json()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
*/
Expand Down
Original file line number Diff line number Diff line change
@@ -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)
}
}
Original file line number Diff line number Diff line change
@@ -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>()
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
6 changes: 3 additions & 3 deletions dataforge-scripting/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}
Expand Down
26 changes: 12 additions & 14 deletions dataforge-workspace/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 946ac88

Please sign in to comment.