Add item property listeners and item property binding tests

This commit is contained in:
Alexander Nozik 2021-04-06 17:19:24 +03:00
parent f1f5f7a70c
commit 23f1d4f7fd
9 changed files with 113 additions and 41 deletions

View File

@ -75,6 +75,7 @@ public final class space/kscience/dataforge/context/ContextBuilder {
}
public final class space/kscience/dataforge/context/ContextBuilderKt {
public static final fun withEnv (Lspace/kscience/dataforge/context/Context;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/context/Context;
}
public final class space/kscience/dataforge/context/DefaultLogManager : space/kscience/dataforge/context/AbstractPlugin, space/kscience/dataforge/context/LogManager {
@ -99,15 +100,10 @@ public final class space/kscience/dataforge/context/Factory$DefaultImpls {
public static synthetic fun invoke$default (Lspace/kscience/dataforge/context/Factory;Lspace/kscience/dataforge/meta/Meta;Lspace/kscience/dataforge/context/Context;ILjava/lang/Object;)Ljava/lang/Object;
}
public final class space/kscience/dataforge/context/Global : space/kscience/dataforge/context/Context {
public static final field INSTANCE Lspace/kscience/dataforge/context/Global;
public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
public final fun getDefaultLogger ()Lspace/kscience/dataforge/context/LogManager;
}
public final class space/kscience/dataforge/context/GlobalKt {
public static final fun Context (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/context/Context;
public static synthetic fun Context$default (Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lspace/kscience/dataforge/context/Context;
public static final fun getGlobal ()Lspace/kscience/dataforge/context/Context;
}
public abstract interface class space/kscience/dataforge/context/LogManager : space/kscience/dataforge/context/Logable, space/kscience/dataforge/context/Plugin {
@ -207,9 +203,6 @@ public final class space/kscience/dataforge/context/PluginManager : java/lang/It
public fun iterator ()Ljava/util/Iterator;
public final fun list (Z)Ljava/util/Collection;
public final fun load (Lspace/kscience/dataforge/context/Plugin;)Lspace/kscience/dataforge/context/Plugin;
public final fun load (Lspace/kscience/dataforge/context/PluginFactory;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/context/Plugin;
public final fun load (Lspace/kscience/dataforge/context/PluginFactory;Lspace/kscience/dataforge/meta/Meta;)Lspace/kscience/dataforge/context/Plugin;
public static synthetic fun load$default (Lspace/kscience/dataforge/context/PluginManager;Lspace/kscience/dataforge/context/PluginFactory;Lspace/kscience/dataforge/meta/Meta;ILjava/lang/Object;)Lspace/kscience/dataforge/context/Plugin;
public final fun remove (Lspace/kscience/dataforge/context/Plugin;)V
}
@ -289,6 +282,9 @@ public final class space/kscience/dataforge/properties/Property$DefaultImpls {
public final class space/kscience/dataforge/properties/PropertyKt {
}
public final class space/kscience/dataforge/properties/SchemePropertyKt {
}
public final class space/kscience/dataforge/provider/DfTypeKt {
public static final fun getDfType (Lkotlin/reflect/KClass;)Ljava/lang/String;
}

View File

@ -102,14 +102,9 @@ public class PluginManager(override val context: Context) : ContextAware, Iterab
/**
* Load a plugin using its factory
*/
@Deprecated("Use immutable contexts instead")
public fun <T : Plugin> load(factory: PluginFactory<T>, meta: Meta = Meta.EMPTY): T =
internal fun <T : Plugin> load(factory: PluginFactory<T>, meta: Meta = Meta.EMPTY): T =
load(factory(meta, context))
@Deprecated("Use immutable contexts instead")
public fun <T : Plugin> load(factory: PluginFactory<T>, metaBuilder: MetaBuilder.() -> Unit): T =
load(factory, Meta(metaBuilder))
/**
* Remove a plugin from [PluginManager]
*/

View File

@ -0,0 +1,29 @@
package space.kscience.dataforge.properties
import space.kscience.dataforge.meta.ItemPropertyProvider
import space.kscience.dataforge.misc.DFExperimental
import space.kscience.dataforge.names.toName
import kotlin.reflect.KMutableProperty1
@DFExperimental
public fun <P : ItemPropertyProvider, T : Any> P.property(property: KMutableProperty1<P, T?>): Property<T?> =
object : Property<T?> {
override var value: T?
get() = property.get(this@property)
set(value) {
property.set(this@property, value)
}
override fun onChange(owner: Any?, callback: (T?) -> Unit) {
this@property.onChange(this) { name, oldItem, newItem ->
if (name == property.name.toName() && oldItem != newItem) {
callback(property.get(this@property))
}
}
}
override fun removeChangeListener(owner: Any?) {
this@property.removeListener(this@property)
}
}

View File

@ -0,0 +1,26 @@
package space.kscience.dataforge.properties
import space.kscience.dataforge.meta.Scheme
import space.kscience.dataforge.meta.SchemeSpec
import space.kscience.dataforge.meta.int
import kotlin.test.Test
import kotlin.test.assertEquals
internal class TestScheme : Scheme() {
var a by int()
var b by int()
companion object : SchemeSpec<TestScheme>(::TestScheme)
}
class ItemPropertiesTest {
@Test
fun testBinding() {
val scheme = TestScheme.empty()
val a = scheme.property(TestScheme::a)
val b = scheme.property(TestScheme::b)
a.bind(b)
scheme.a = 2
assertEquals(2, scheme.b)
assertEquals(2, b.value)
}
}

View File

@ -12,7 +12,7 @@ public abstract class space/kscience/dataforge/meta/AbstractTypedMeta : space/ks
public fun getItem (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMetaItem;
}
public final class space/kscience/dataforge/meta/Config : space/kscience/dataforge/meta/AbstractMutableMeta, space/kscience/dataforge/meta/ObservableItemProvider {
public final class space/kscience/dataforge/meta/Config : space/kscience/dataforge/meta/AbstractMutableMeta, space/kscience/dataforge/meta/ItemPropertyProvider {
public static final field ConfigSerializer Lspace/kscience/dataforge/meta/Config$ConfigSerializer;
public fun <init> ()V
public synthetic fun empty$dataforge_meta ()Lspace/kscience/dataforge/meta/MutableMeta;
@ -94,18 +94,7 @@ public final class space/kscience/dataforge/meta/ItemDelegateKt {
public static synthetic fun value$default (Lspace/kscience/dataforge/meta/ItemProvider;Lspace/kscience/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
}
public final class space/kscience/dataforge/meta/ItemListener {
public fun <init> (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)V
public synthetic fun <init> (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/lang/Object;
public final fun component2 ()Lkotlin/jvm/functions/Function3;
public final fun copy (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)Lspace/kscience/dataforge/meta/ItemListener;
public static synthetic fun copy$default (Lspace/kscience/dataforge/meta/ItemListener;Ljava/lang/Object;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lspace/kscience/dataforge/meta/ItemListener;
public fun equals (Ljava/lang/Object;)Z
public final fun getAction ()Lkotlin/jvm/functions/Function3;
public final fun getOwner ()Ljava/lang/Object;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
public abstract interface class space/kscience/dataforge/meta/ItemPropertyProvider : space/kscience/dataforge/meta/MutableItemProvider, space/kscience/dataforge/meta/ObservableItemProvider {
}
public abstract interface class space/kscience/dataforge/meta/ItemProvider {
@ -424,6 +413,11 @@ public abstract interface class space/kscience/dataforge/meta/ObservableItemProv
public abstract fun removeListener (Ljava/lang/Object;)V
}
public final class space/kscience/dataforge/meta/ObservableItemProviderKt {
public static final fun onChange (Lspace/kscience/dataforge/meta/ObservableItemProvider;Lkotlin/reflect/KProperty1;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;)V
public static synthetic fun onChange$default (Lspace/kscience/dataforge/meta/ObservableItemProvider;Lkotlin/reflect/KProperty1;Ljava/lang/Object;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
}
public abstract interface class space/kscience/dataforge/meta/ReadOnlySpecification {
public abstract fun empty ()Lspace/kscience/dataforge/meta/ItemProvider;
public abstract fun invoke (Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/ItemProvider;
@ -434,7 +428,7 @@ public final class space/kscience/dataforge/meta/ReadOnlySpecification$DefaultIm
public static fun invoke (Lspace/kscience/dataforge/meta/ReadOnlySpecification;Lkotlin/jvm/functions/Function1;)Lspace/kscience/dataforge/meta/ItemProvider;
}
public class space/kscience/dataforge/meta/Scheme : space/kscience/dataforge/meta/MetaRepr, space/kscience/dataforge/meta/MutableItemProvider, space/kscience/dataforge/meta/ObservableItemProvider, space/kscience/dataforge/meta/descriptors/Described {
public class space/kscience/dataforge/meta/Scheme : space/kscience/dataforge/meta/ItemPropertyProvider, space/kscience/dataforge/meta/MetaRepr, space/kscience/dataforge/meta/descriptors/Described {
public fun <init> ()V
public fun getDefaultLayer ()Lspace/kscience/dataforge/meta/Meta;
public synthetic fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor;

View File

@ -14,21 +14,11 @@ import kotlin.jvm.Synchronized
//TODO add validator to configuration
public data class ItemListener(
val owner: Any? = null,
val action: (name: Name, oldItem: MetaItem?, newItem: MetaItem?) -> Unit
)
public interface ObservableItemProvider : ItemProvider {
public fun onChange(owner: Any?, action: (name: Name, oldItem: MetaItem?, newItem: MetaItem?) -> Unit)
public fun removeListener(owner: Any?)
}
/**
* Mutable meta representing object state
*/
@Serializable(Config.Companion::class)
public class Config() : AbstractMutableMeta<Config>(), ObservableItemProvider {
public class Config : AbstractMutableMeta<Config>(), ItemPropertyProvider {
private val listeners = HashSet<ItemListener>()

View File

@ -0,0 +1,31 @@
package space.kscience.dataforge.meta
import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.toName
import kotlin.reflect.KProperty1
internal data class ItemListener(
val owner: Any? = null,
val action: (name: Name, oldItem: MetaItem?, newItem: MetaItem?) -> Unit,
)
public interface ObservableItemProvider : ItemProvider {
public fun onChange(owner: Any?, action: (name: Name, oldItem: MetaItem?, newItem: MetaItem?) -> Unit)
public fun removeListener(owner: Any?)
}
public interface ItemPropertyProvider: ObservableItemProvider, MutableItemProvider
public fun <O : ObservableItemProvider, T : Any> O.onChange(
property: KProperty1<O, T?>,
owner: Any? = null,
callBack: O.(T?) -> Unit,
) {
onChange(null) { name, oldItem, newItem ->
if (name == property.name.toName() && oldItem != newItem) {
callBack(property.get(this))
}
}
}

View File

@ -10,7 +10,7 @@ import kotlin.jvm.Synchronized
* A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [Specification].
* Default item provider and [NodeDescriptor] are optional
*/
public open class Scheme() : MutableItemProvider, Described, MetaRepr, ObservableItemProvider {
public open class Scheme() : Described, MetaRepr, ItemPropertyProvider {
private var items: MutableItemProvider = Config()

View File

@ -20,4 +20,15 @@ class SchemeTest {
scheme.retarget(config)
assertEquals(29, scheme.a)
}
@Test
fun testSchemeSubscription(){
val scheme = TestScheme.empty()
var flag: Int? = null
scheme.onChange(TestScheme::a){a->
flag = a
}
scheme.a = 2
assertEquals(2, flag)
}
}