diff --git a/dataforge-context/api/dataforge-context.api b/dataforge-context/api/dataforge-context.api index 1b1a849f..0f518890 100644 --- a/dataforge-context/api/dataforge-context.api +++ b/dataforge-context/api/dataforge-context.api @@ -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; } diff --git a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/PluginManager.kt b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/PluginManager.kt index 540b200d..e738addd 100644 --- a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/PluginManager.kt +++ b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/context/PluginManager.kt @@ -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 load(factory: PluginFactory, meta: Meta = Meta.EMPTY): T = + internal fun load(factory: PluginFactory, meta: Meta = Meta.EMPTY): T = load(factory(meta, context)) - @Deprecated("Use immutable contexts instead") - public fun load(factory: PluginFactory, metaBuilder: MetaBuilder.() -> Unit): T = - load(factory, Meta(metaBuilder)) - /** * Remove a plugin from [PluginManager] */ diff --git a/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/schemeProperty.kt b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/schemeProperty.kt new file mode 100644 index 00000000..a2f39eed --- /dev/null +++ b/dataforge-context/src/commonMain/kotlin/space/kscience/dataforge/properties/schemeProperty.kt @@ -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.property(property: KMutableProperty1): Property = + object : Property { + 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) + } + + } \ No newline at end of file diff --git a/dataforge-context/src/commonTest/kotlin/space/kscience/dataforge/properties/ItemPropertiesTest.kt b/dataforge-context/src/commonTest/kotlin/space/kscience/dataforge/properties/ItemPropertiesTest.kt new file mode 100644 index 00000000..b2d8c2e6 --- /dev/null +++ b/dataforge-context/src/commonTest/kotlin/space/kscience/dataforge/properties/ItemPropertiesTest.kt @@ -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) +} + +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) + } +} \ No newline at end of file diff --git a/dataforge-meta/api/dataforge-meta.api b/dataforge-meta/api/dataforge-meta.api index abec55f4..80b944b5 100644 --- a/dataforge-meta/api/dataforge-meta.api +++ b/dataforge-meta/api/dataforge-meta.api @@ -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 ()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 (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)V - public synthetic fun (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 ()V public fun getDefaultLayer ()Lspace/kscience/dataforge/meta/Meta; public synthetic fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor; diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Config.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Config.kt index a69b9a22..20fb1cb2 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Config.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Config.kt @@ -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(), ObservableItemProvider { +public class Config : AbstractMutableMeta(), ItemPropertyProvider { private val listeners = HashSet() diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableItemProvider.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableItemProvider.kt new file mode 100644 index 00000000..1a11441b --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/ObservableItemProvider.kt @@ -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.onChange( + property: KProperty1, + owner: Any? = null, + callBack: O.(T?) -> Unit, +) { + onChange(null) { name, oldItem, newItem -> + if (name == property.name.toName() && oldItem != newItem) { + callBack(property.get(this)) + } + } +} \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt index 613161e1..07816965 100644 --- a/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt +++ b/dataforge-meta/src/commonMain/kotlin/space/kscience/dataforge/meta/Scheme.kt @@ -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() diff --git a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SchemeTest.kt b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SchemeTest.kt index c9d80119..d2407bb4 100644 --- a/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SchemeTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/space/kscience/dataforge/meta/SchemeTest.kt @@ -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) + } } \ No newline at end of file