Refactor Scheme and MutableItemProvider.kt

This commit is contained in:
Alexander Nozik 2020-11-10 19:08:53 +03:00
parent 8ef0b2247c
commit d5992c721d
28 changed files with 519 additions and 375 deletions

View File

@ -2,7 +2,7 @@ plugins {
id("ru.mipt.npm.project")
}
val dataforgeVersion by extra("0.2.0-dev-4")
val dataforgeVersion by extra("0.2.0-dev-6")
val bintrayRepo by extra("dataforge")
val githubProject by extra("dataforge-core")

View File

@ -229,6 +229,35 @@ public abstract interface annotation class hep/dataforge/descriptors/ValueDef :
public abstract fun type ()[Lhep/dataforge/values/ValueType;
}
public final class hep/dataforge/properties/ConfigProperty : hep/dataforge/properties/Property {
public fun <init> (Lhep/dataforge/meta/Config;Lhep/dataforge/names/Name;Lhep/dataforge/meta/transformations/MetaConverter;)V
public final fun getConfig ()Lhep/dataforge/meta/Config;
public final fun getConverter ()Lhep/dataforge/meta/transformations/MetaConverter;
public final fun getName ()Lhep/dataforge/names/Name;
public fun getValue ()Ljava/lang/Object;
public fun onChange (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
public fun removeChangeListener (Ljava/lang/Object;)V
public fun setValue (Ljava/lang/Object;)V
}
public abstract interface class hep/dataforge/properties/Property {
public abstract fun getValue ()Ljava/lang/Object;
public abstract fun onChange (Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
public abstract fun removeChangeListener (Ljava/lang/Object;)V
public abstract fun setValue (Ljava/lang/Object;)V
}
public final class hep/dataforge/properties/Property$DefaultImpls {
public static synthetic fun onChange$default (Lhep/dataforge/properties/Property;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
public static synthetic fun removeChangeListener$default (Lhep/dataforge/properties/Property;Ljava/lang/Object;ILjava/lang/Object;)V
}
public final class hep/dataforge/properties/PropertyKt {
public static final fun bind (Lhep/dataforge/properties/Property;Lhep/dataforge/properties/Property;)V
public static final fun mirror (Lhep/dataforge/properties/Property;Lhep/dataforge/properties/Property;Lkotlinx/coroutines/CoroutineScope;)V
public static final fun toFlow (Lhep/dataforge/properties/Property;)Lkotlinx/coroutines/flow/StateFlow;
}
public final class hep/dataforge/provider/DfTypeKt {
public static final fun getDfType (Lkotlin/reflect/KClass;)Ljava/lang/String;
}

View File

@ -0,0 +1,33 @@
package hep.dataforge.properties
import hep.dataforge.meta.Config
import hep.dataforge.meta.DFExperimental
import hep.dataforge.meta.get
import hep.dataforge.meta.transformations.MetaConverter
import hep.dataforge.meta.transformations.nullableItemToObject
import hep.dataforge.meta.transformations.nullableObjectToMetaItem
import hep.dataforge.names.Name
@DFExperimental
public class ConfigProperty<T : Any>(
public val config: Config,
public val name: Name,
public val converter: MetaConverter<T>,
) : Property<T?> {
override var value: T?
get() = converter.nullableItemToObject(config[name])
set(value) {
config.setItem(name,converter.nullableObjectToMetaItem(value))
}
override fun onChange(owner: Any?, callback: (T?) -> Unit) {
config.onChange(owner) { name, oldItem, newItem ->
if (name == this.name && oldItem != newItem) callback(converter.nullableItemToObject(newItem))
}
}
override fun removeChangeListener(owner: Any?) {
config.removeListener(owner)
}
}

View File

@ -0,0 +1,48 @@
package hep.dataforge.properties
import hep.dataforge.meta.DFExperimental
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@DFExperimental
public interface Property<T> {
public var value: T
public fun onChange(owner: Any? = null, callback: (T) -> Unit)
public fun removeChangeListener(owner: Any? = null)
}
@DFExperimental
@OptIn(ExperimentalCoroutinesApi::class)
public fun <T> Property<T>.toFlow(): StateFlow<T> = MutableStateFlow(value).also { stateFlow ->
onChange {
stateFlow.value = it
}
}
/**
* Reflect all changes in the [source] property onto this property
*
* @return a mirroring job
*/
@DFExperimental
public fun <T> Property<T>.mirror(source: Property<T>, scope: CoroutineScope) {
source.onChange(this) {
this.value = it
}
}
/**
* Bi-directional connection between properties
*/
@DFExperimental
public fun <T> Property<T>.bind(other: Property<T>) {
onChange(other) {
other.value = it
}
other.onChange {
this.value = it
}
}

View File

@ -0,0 +1,32 @@
package hep.dataforge.properties
import hep.dataforge.meta.DFExperimental
import org.w3c.dom.HTMLInputElement
@DFExperimental
fun HTMLInputElement.bindValue(property: Property<String>) {
if (this.onchange != null) error("Input element already bound")
this.onchange = {
property.value = this.value
Unit
}
property.onChange(this) {
if (value != it) {
value = it
}
}
}
@DFExperimental
fun HTMLInputElement.bindChecked(property: Property<Boolean>) {
if (this.onchange != null) error("Input element already bound")
this.onchange = {
property.value = this.checked
Unit
}
property.onChange(this) {
if (checked != it) {
checked = it
}
}
}

View File

@ -93,7 +93,6 @@ public final class hep/dataforge/data/DataFilter : hep/dataforge/meta/Scheme {
public final fun getFrom ()Ljava/lang/String;
public final fun getPattern ()Ljava/lang/String;
public final fun getTo ()Ljava/lang/String;
public final fun isEmpty ()Z
public final fun setFrom (Ljava/lang/String;)V
public final fun setPattern (Ljava/lang/String;)V
public final fun setTo (Ljava/lang/String;)V

View File

@ -20,8 +20,6 @@ public class DataFilter : Scheme() {
// val prefix by string()
// val suffix by string()
public fun isEmpty(): Boolean = config.isEmpty()
public companion object : SchemeSpec<DataFilter>(::DataFilter)
}

View File

@ -6,8 +6,8 @@ public abstract class hep/dataforge/meta/AbstractMetaNode : hep/dataforge/meta/M
public abstract class hep/dataforge/meta/AbstractMutableMeta : hep/dataforge/meta/AbstractMetaNode, hep/dataforge/meta/MutableMeta {
public fun <init> ()V
protected final fun getChildren ()Ljava/util/Map;
public fun getItems ()Ljava/util/Map;
protected final fun get_items ()Ljava/util/Map;
protected fun replaceItem (Lhep/dataforge/names/NameToken;Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/MetaItem;)V
public fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
protected final fun wrapItem (Lhep/dataforge/meta/MetaItem;)Lhep/dataforge/meta/MetaItem;
@ -38,21 +38,15 @@ public final class hep/dataforge/meta/ConfigKt {
public static final fun get (Lhep/dataforge/meta/Config;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/MetaItem;
}
public abstract interface class hep/dataforge/meta/Configurable : hep/dataforge/meta/MutableItemProvider, hep/dataforge/meta/descriptors/Described {
public abstract interface class hep/dataforge/meta/Configurable : hep/dataforge/meta/MutableItemProvider {
public abstract fun getConfig ()Lhep/dataforge/meta/Config;
public abstract fun getDefaultItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
public abstract fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
public abstract fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
public abstract fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
public abstract fun validateItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
}
public final class hep/dataforge/meta/Configurable$DefaultImpls {
public static fun getDefaultItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
public static fun getDescriptor (Lhep/dataforge/meta/Configurable;)Lhep/dataforge/meta/descriptors/NodeDescriptor;
public static fun getItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
public static fun setItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
public static fun validateItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
}
public final class hep/dataforge/meta/ConfigurableKt {
@ -60,18 +54,6 @@ public final class hep/dataforge/meta/ConfigurableKt {
public static synthetic fun config$default (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
public static final fun configure (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Configurable;
public static final fun configure (Lhep/dataforge/meta/Configurable;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
public static final fun getItem (Lhep/dataforge/meta/Configurable;Ljava/lang/String;)Lhep/dataforge/meta/MetaItem;
public static final fun node (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
public static synthetic fun node$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
public static final fun setItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
public static final fun setItem (Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;Lhep/dataforge/values/Value;)V
public static final fun setItem (Lhep/dataforge/meta/Configurable;Ljava/lang/String;Lhep/dataforge/meta/Meta;)V
public static final fun setItem (Lhep/dataforge/meta/Configurable;Ljava/lang/String;Lhep/dataforge/meta/MetaItem;)V
public static final fun setItem (Lhep/dataforge/meta/Configurable;Ljava/lang/String;Lhep/dataforge/values/Value;)V
public static final fun spec (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
public static final fun spec (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
public static synthetic fun spec$default (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Configurable;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
public static synthetic fun spec$default (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
}
public abstract interface annotation class hep/dataforge/meta/DFBuilder : java/lang/annotation/Annotation {
@ -196,9 +178,12 @@ public abstract interface class hep/dataforge/meta/Meta : hep/dataforge/meta/Ite
public static final field Companion Lhep/dataforge/meta/Meta$Companion;
public static final field TYPE Ljava/lang/String;
public static final field VALUE_KEY Ljava/lang/String;
public abstract fun equals (Ljava/lang/Object;)Z
public abstract fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
public abstract fun getItems ()Ljava/util/Map;
public abstract fun hashCode ()I
public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
public abstract fun toString ()Ljava/lang/String;
}
public final class hep/dataforge/meta/Meta$Companion {
@ -358,14 +343,6 @@ public abstract interface class hep/dataforge/meta/MetaRepr {
public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
}
public class hep/dataforge/meta/MetaScheme : hep/dataforge/meta/Scheme {
public fun <init> (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;Lhep/dataforge/meta/Config;)V
public synthetic fun <init> (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/descriptors/NodeDescriptor;Lhep/dataforge/meta/Config;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun getDefaultLayer ()Lhep/dataforge/meta/Meta;
public synthetic fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
public fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
}
public final class hep/dataforge/meta/MetaSerializer : kotlinx/serialization/KSerializer {
public static final field INSTANCE Lhep/dataforge/meta/MetaSerializer;
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/meta/Meta;
@ -375,6 +352,18 @@ public final class hep/dataforge/meta/MetaSerializer : kotlinx/serialization/KSe
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
}
public final class hep/dataforge/meta/MetaWithDefault : hep/dataforge/meta/MetaBase {
public fun <init> (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)V
public final fun getDefault ()Lhep/dataforge/meta/ItemProvider;
public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
public fun getItems ()Ljava/util/Map;
public final fun getMeta ()Lhep/dataforge/meta/Meta;
}
public final class hep/dataforge/meta/MetaWithDefaultKt {
public static final fun withDefault (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MetaWithDefault;
}
public final class hep/dataforge/meta/MutableItemDelegateKt {
public static final fun boolean (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
public static final fun boolean (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty;
@ -437,6 +426,29 @@ public abstract interface class hep/dataforge/meta/MutableItemProvider : hep/dat
public abstract fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
}
public final class hep/dataforge/meta/MutableItemProviderKt {
public static final fun getItem (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;)Lhep/dataforge/meta/MetaItem;
public static final fun node (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
public static synthetic fun node$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
public static final fun remove (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)V
public static final fun remove (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;)V
public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Iterable;)V
public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Object;)V
public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/NameToken;Ljava/lang/Object;)V
public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Ljava/lang/Iterable;)V
public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Ljava/lang/Object;)V
public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V
public static final fun setIndexed (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V
public static synthetic fun setIndexed$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
public static final fun setIndexedItems (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V
public static synthetic fun setIndexedItems$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
public static final fun setItem (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lhep/dataforge/meta/MetaItem;)V
public static final fun setNode (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
public static final fun setNode (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lhep/dataforge/meta/Meta;)V
public static final fun setValue (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lhep/dataforge/values/Value;)V
public static final fun setValue (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lhep/dataforge/values/Value;)V
}
public abstract interface class hep/dataforge/meta/MutableMeta : hep/dataforge/meta/MetaNode, hep/dataforge/meta/MutableItemProvider {
public abstract fun getItems ()Ljava/util/Map;
}
@ -450,24 +462,6 @@ public final class hep/dataforge/meta/MutableMetaKt {
public static final fun append (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Object;)V
public static final fun append (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/lang/Object;)V
public static final fun edit (Lhep/dataforge/meta/AbstractMutableMeta;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V
public static final fun remove (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;)V
public static final fun remove (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;)V
public static final fun set (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
public static final fun set (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Iterable;)V
public static final fun set (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Object;)V
public static final fun set (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/NameToken;Ljava/lang/Object;)V
public static final fun set (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/lang/Iterable;)V
public static final fun set (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/lang/Object;)V
public static final fun set (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Ljava/lang/String;Ljava/lang/Object;)V
public static final fun setIndexed (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V
public static synthetic fun setIndexed$default (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
public static final fun setIndexedItems (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V
public static synthetic fun setIndexedItems$default (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILjava/lang/Object;)V
public static final fun setItem (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Lhep/dataforge/meta/MetaItem;)V
public static final fun setNode (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Lhep/dataforge/meta/Meta;)V
public static final fun setNode (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Lhep/dataforge/meta/Meta;)V
public static final fun setValue (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;Lhep/dataforge/values/Value;)V
public static final fun setValue (Lhep/dataforge/meta/MutableMeta;Ljava/lang/String;Lhep/dataforge/values/Value;)V
public static final fun update (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/meta/Meta;)V
}
@ -483,22 +477,23 @@ public final class hep/dataforge/meta/ObservableMeta$DefaultImpls {
public class hep/dataforge/meta/Scheme : hep/dataforge/meta/Configurable, hep/dataforge/meta/MetaRepr, hep/dataforge/meta/descriptors/Described {
public fun <init> ()V
public fun <init> (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)V
public fun <init> (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
public synthetic fun <init> (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun getConfig ()Lhep/dataforge/meta/Config;
public fun getDefaultItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
public final fun getDefaultItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
public fun getDefaultLayer ()Lhep/dataforge/meta/Meta;
public final fun getDefaultProvider ()Lhep/dataforge/meta/ItemProvider;
public synthetic fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
public fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
public final fun isEmpty ()Z
public fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
public fun toMeta ()Lhep/dataforge/meta/Laminate;
public synthetic fun toMeta ()Lhep/dataforge/meta/Meta;
public fun validateItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
public final fun validateItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
}
public final class hep/dataforge/meta/SchemeKt {
public static final fun asScheme (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MetaScheme;
public static final fun asScheme (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Scheme;
public static final fun invoke (Lhep/dataforge/meta/Scheme;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Scheme;
public static final fun toScheme (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
public static synthetic fun toScheme$default (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/meta/Configurable;
@ -507,12 +502,8 @@ public final class hep/dataforge/meta/SchemeKt {
public class hep/dataforge/meta/SchemeSpec : hep/dataforge/meta/Specification {
public fun <init> (Lkotlin/jvm/functions/Function0;)V
public fun <init> (Lkotlin/jvm/functions/Function2;)V
public synthetic fun empty ()Lhep/dataforge/meta/Configurable;
public fun empty ()Lhep/dataforge/meta/Scheme;
public synthetic fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
public final fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Scheme;
public synthetic fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Configurable;
public fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
public synthetic fun wrap (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
public fun wrap (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
}
public final class hep/dataforge/meta/SealedMeta : hep/dataforge/meta/AbstractMetaNode {
@ -520,25 +511,27 @@ public final class hep/dataforge/meta/SealedMeta : hep/dataforge/meta/AbstractMe
}
public abstract interface class hep/dataforge/meta/Specification {
public abstract fun empty ()Lhep/dataforge/meta/Configurable;
public abstract fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
public abstract fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Configurable;
public abstract fun wrap (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
}
public final class hep/dataforge/meta/Specification$DefaultImpls {
public static fun empty (Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/Configurable;
public static fun invoke (Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
public static synthetic fun wrap$default (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;ILjava/lang/Object;)Lhep/dataforge/meta/Configurable;
public static synthetic fun wrap$default (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;ILjava/lang/Object;)Lhep/dataforge/meta/MutableItemProvider;
}
public final class hep/dataforge/meta/SpecificationKt {
public static final fun configSpec (Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/Configurable;
public static final fun configure (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
public static final fun configSpec (Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/MutableItemProvider;
public static final fun configure (Lhep/dataforge/meta/MetaRepr;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MetaRepr;
public static final fun createStyle (Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Meta;
public static final fun spec (Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/Configurable;
public static final fun empty (Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/MutableItemProvider;
public static final fun invoke (Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
public static final fun spec (Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/MutableItemProvider;
public static final fun spec (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Scheme;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
public static final fun spec (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Specification;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
public static synthetic fun spec$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Scheme;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
public static synthetic fun spec$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Specification;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
public static final fun update (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
public static final fun update (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Config;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
public static final fun wrap (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Configurable;
public static final fun update (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
public static final fun wrap (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MutableItemProvider;
}
public abstract interface class hep/dataforge/meta/descriptors/Described {
@ -775,7 +768,6 @@ public final class hep/dataforge/names/NameKt {
public static final fun get (Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;
public static synthetic fun get$default (Ljava/util/Map;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/Object;
public static final fun getLength (Lhep/dataforge/names/Name;)I
public static final fun hasIndex (Lhep/dataforge/names/NameToken;)Z
public static final fun isEmpty (Lhep/dataforge/names/Name;)Z
public static final fun lastOrNull (Lhep/dataforge/names/Name;)Lhep/dataforge/names/NameToken;
public static final fun plus (Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;)Lhep/dataforge/names/Name;
@ -787,7 +779,6 @@ public final class hep/dataforge/names/NameKt {
public static final fun startsWith (Lhep/dataforge/names/Name;Lhep/dataforge/names/NameToken;)Z
public static final fun toName (Ljava/lang/String;)Lhep/dataforge/names/Name;
public static final fun withIndex (Lhep/dataforge/names/Name;Ljava/lang/String;)Lhep/dataforge/names/Name;
public static final fun withIndex (Lhep/dataforge/names/NameToken;Ljava/lang/String;)Lhep/dataforge/names/NameToken;
}
public final class hep/dataforge/names/NameToken {
@ -814,6 +805,11 @@ public final class hep/dataforge/names/NameToken$Companion : kotlinx/serializati
public final fun serializer ()Lkotlinx/serialization/KSerializer;
}
public final class hep/dataforge/names/NameTokenKt {
public static final fun hasIndex (Lhep/dataforge/names/NameToken;)Z
public static final fun withIndex (Lhep/dataforge/names/NameToken;Ljava/lang/String;)Lhep/dataforge/names/NameToken;
}
public final class hep/dataforge/values/DoubleArrayValue : hep/dataforge/values/Value {
public fun <init> ([D)V
public fun equals (Ljava/lang/Object;)Z

View File

@ -1,16 +1,12 @@
import ru.mipt.npm.gradle.KScienceVersions
plugins {
id("ru.mipt.npm.mpp")
id("ru.mipt.npm.native")
}
kscience {
useSerialization()
useSerialization{
json()
}
}
description = "Meta definition and basic operations on meta"
dependencies{
commonMainApi("org.jetbrains.kotlinx:kotlinx-serialization-json:${KScienceVersions.serializationVersion}")
}
description = "Meta definition and basic operations on meta"

View File

@ -4,10 +4,8 @@ import hep.dataforge.names.Name
import hep.dataforge.names.NameToken
import hep.dataforge.names.asName
import hep.dataforge.names.plus
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.Serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@ -53,12 +51,12 @@ public class Config() : AbstractMutableMeta<Config>(), ObservableMeta {
override fun replaceItem(key: NameToken, oldItem: MetaItem<Config>?, newItem: MetaItem<Config>?) {
if (newItem == null) {
_items.remove(key)
children.remove(key)
if (oldItem != null && oldItem is MetaItem.NodeItem<Config>) {
oldItem.node.removeListener(this)
}
} else {
_items[key] = newItem
children[key] = newItem
if (newItem is MetaItem.NodeItem) {
newItem.node.onChange(this) { name, oldChild, newChild ->
itemChanged(key + name, oldChild, newChild)
@ -75,8 +73,6 @@ public class Config() : AbstractMutableMeta<Config>(), ObservableMeta {
override fun empty(): Config = Config()
@OptIn(ExperimentalSerializationApi::class)
@Serializer(Config::class)
public companion object ConfigSerializer : KSerializer<Config> {
public fun empty(): Config = Config()

View File

@ -1,67 +1,30 @@
package hep.dataforge.meta
import hep.dataforge.meta.descriptors.*
import hep.dataforge.names.Name
import hep.dataforge.names.asName
import hep.dataforge.names.toName
import hep.dataforge.values.Value
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
/**
* A container that holds a [Config] and a default item provider.
* Default item provider could be use for example to reference parent configuration.
* It is not possible to know if some property is declared by provider just by looking on [Configurable],
* this information should be provided externally.
* A container that holds a [Config].
*/
public interface Configurable : Described, MutableItemProvider {
public interface Configurable : MutableItemProvider {
/**
* Backing config
*/
public val config: Config
/**
* Default meta item provider
*/
public fun getDefaultItem(name: Name): MetaItem<*>? = null
/**
* Check if property with given [name] could be assigned to [item]
*/
public fun validateItem(name: Name, item: MetaItem<*>?): Boolean {
val descriptor = descriptor?.get(name)
return descriptor?.validateItem(item) ?: true
}
override val descriptor: NodeDescriptor? get() = null
/**
* Get a property with default
*/
override fun getItem(name: Name): MetaItem<*>? =
config[name] ?: getDefaultItem(name) ?: descriptor?.get(name)?.defaultItem()
override fun getItem(name: Name): MetaItem<*>? = config[name]
/**
* Set a configurable property
*/
override fun setItem(name: Name, item: MetaItem<*>?) {
if (validateItem(name, item)) {
config.setItem(name, item)
} else {
error("Validation failed for property $name with value $item")
}
config.setItem(name, item)
}
}
public fun Configurable.getItem(key: String): MetaItem<*>? = getItem(key.toName())
public fun Configurable.setItem(name: Name, value: Value?): Unit = setItem(name, value?.let { MetaItem.ValueItem(value) })
public fun Configurable.setItem(name: Name, meta: Meta?): Unit = setItem(name, meta?.let { MetaItem.NodeItem(meta) })
public fun Configurable.setItem(key: String, item: MetaItem<*>?): Unit = setItem(key.toName(), item)
public fun Configurable.setItem(key: String, value: Value?): Unit = setItem(key, value?.let { MetaItem.ValueItem(value) })
public fun Configurable.setItem(key: String, meta: Meta?): Unit = setItem(key, meta?.let { MetaItem.NodeItem(meta) })
public fun <T : Configurable> T.configure(meta: Meta): T = this.apply { config.update(meta) }
@ -70,39 +33,4 @@ public inline fun <T : Configurable> T.configure(action: Config.() -> Unit): T =
/* Node delegates */
public fun Configurable.config(key: Name? = null): ReadWriteProperty<Any?, Config?> =
config.node(key)
public fun MutableItemProvider.node(key: Name? = null): ReadWriteProperty<Any?, Meta?> = item(key).convert(
reader = { it.node },
writer = { it?.let { MetaItem.NodeItem(it) } }
)
public fun <T : Configurable> Configurable.spec(
spec: Specification<T>, key: Name? = null
): ReadWriteProperty<Any?, T?> = object : ReadWriteProperty<Any?, T?> {
override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
val name = key ?: property.name.asName()
return config[name].node?.let { spec.wrap(it) }
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
val name = key ?: property.name.asName()
config[name] = value?.config
}
}
public fun <T : Configurable> Configurable.spec(
spec: Specification<T>, default: T, key: Name? = null
): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> {
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
val name = key ?: property.name.asName()
return config[name].node?.let { spec.wrap(it) } ?: default
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
val name = key ?: property.name.asName()
config[name] = value.config
}
}
public fun Configurable.config(key: Name? = null): ReadWriteProperty<Any?, Config?> = config.node(key)

View File

@ -66,6 +66,7 @@ public fun <M : Meta> M.asMetaItem(): NodeItem<M> = NodeItem(this)
* The object that could be represented as [Meta]. Meta provided by [toMeta] method should fully represent object state.
* Meaning that two states with the same meta are equal.
*/
@Serializable(MetaSerializer::class)
public interface MetaRepr {
public fun toMeta(): Meta
}
@ -104,12 +105,11 @@ public interface Meta : MetaRepr, ItemProvider {
override fun toMeta(): Meta = seal()
//TODO to be restored on 1.4.30 after https://youtrack.jetbrains.com/issue/KT-41765 si fixed
// override fun equals(other: Any?): Boolean
//
// override fun hashCode(): Int
//
// override fun toString(): String
override fun equals(other: Any?): Boolean
override fun hashCode(): Int
override fun toString(): String
public companion object {
public const val TYPE: String = "meta"

View File

@ -68,7 +68,7 @@ public class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
@JvmName("putMetas")
public infix fun String.put(value: Iterable<Meta>) {
this@MetaBuilder[this] = value.toList()
set(this,value.toList())
}
public infix fun String.put(metaBuilder: MetaBuilder.() -> Unit) {
@ -110,7 +110,7 @@ public class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
@JvmName("putMetas")
public infix fun Name.put(value: Iterable<Meta>) {
this@MetaBuilder[this] = value.toList()
set(this, value.toList())
}
public infix fun Name.put(metaBuilder: MetaBuilder.() -> Unit) {

View File

@ -5,7 +5,6 @@ import hep.dataforge.values.ValueSerializer
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializer
import kotlinx.serialization.builtins.MapSerializer
import kotlinx.serialization.descriptors.*
import kotlinx.serialization.encoding.*
@ -52,8 +51,6 @@ public object MetaItemSerializer : KSerializer<MetaItem<*>> {
/**
* Serialized for meta
*/
@OptIn(ExperimentalSerializationApi::class)
@Serializer(Meta::class)
public object MetaSerializer : KSerializer<Meta> {
private val mapSerializer: KSerializer<Map<NameToken, MetaItem<Meta>>> = MapSerializer(

View File

@ -0,0 +1,18 @@
package hep.dataforge.meta
import hep.dataforge.names.Name
import hep.dataforge.names.NameToken
/**
* Meta object with default provider for items not present in the initial meta.
*/
public class MetaWithDefault(public val meta: Meta, public val default: ItemProvider) : MetaBase() {
override val items: Map<NameToken, MetaItem<*>>
get() = meta.items
override fun getItem(name: Name): MetaItem<*>? {
return meta[name] ?: default.getItem(name)
}
}
public fun Meta.withDefault(default: ItemProvider): MetaWithDefault = MetaWithDefault(this, default)

View File

@ -0,0 +1,88 @@
package hep.dataforge.meta
import hep.dataforge.names.*
import hep.dataforge.values.Value
import kotlin.properties.ReadWriteProperty
public interface MutableItemProvider : ItemProvider {
public fun setItem(name: Name, item: MetaItem<*>?)
}
public fun MutableItemProvider.getItem(key: String): MetaItem<*>? = getItem(key.toName())
public fun MutableItemProvider.setValue(name: Name, value: Value?): Unit =
setItem(name, value?.let { MetaItem.ValueItem(value) })
public fun MutableItemProvider.setNode(name: Name, meta: Meta?): Unit =
setItem(name, meta?.let { MetaItem.NodeItem(meta) })
public fun MutableItemProvider.setItem(key: String, item: MetaItem<*>?): Unit = setItem(key.toName(), item)
public fun MutableItemProvider.setValue(key: String, value: Value?): Unit =
setItem(key, value?.let { MetaItem.ValueItem(value) })
public fun MutableItemProvider.setNode(key: String, meta: Meta?): Unit =
setItem(key, meta?.let { MetaItem.NodeItem(meta) })
public fun MutableItemProvider.node(key: Name? = null): ReadWriteProperty<Any?, Meta?> = item(key).convert(
reader = { it.node },
writer = { it?.let { MetaItem.NodeItem(it) } }
)
@Suppress("NOTHING_TO_INLINE")
public inline fun MutableItemProvider.remove(name: Name): Unit = setItem(name, null)
@Suppress("NOTHING_TO_INLINE")
public inline fun MutableItemProvider.remove(name: String): Unit = remove(name.toName())
/**
* Universal unsafe set method
*/
public operator fun MutableItemProvider.set(name: Name, value: Any?) {
when (value) {
null -> remove(name)
is MetaItem<*> -> setItem(name, value)
is Meta -> setNode(name, value)
is Configurable -> setNode(name, value.config)
else -> setValue(name, Value.of(value))
}
}
public operator fun MutableItemProvider.set(name: NameToken, value: Any?): Unit =
set(name.asName(), value)
public operator fun MutableItemProvider.set(key: String, value: Any?): Unit =
set(key.toName(), value)
public operator fun MutableItemProvider.set(key: String, index: String, value: Any?): Unit =
set(key.toName().withIndex(index), value)
/* Same name siblings generation */
public fun MutableItemProvider.setIndexedItems(
name: Name,
items: Iterable<MetaItem<*>>,
indexFactory: (MetaItem<*>, index: Int) -> String = { _, index -> index.toString() }
) {
val tokens = name.tokens.toMutableList()
val last = tokens.last()
items.forEachIndexed { index, meta ->
val indexedToken = NameToken(last.body, last.index + indexFactory(meta, index))
tokens[tokens.lastIndex] = indexedToken
setItem(Name(tokens), meta)
}
}
public fun MutableItemProvider.setIndexed(
name: Name,
metas: Iterable<Meta>,
indexFactory: (Meta, index: Int) -> String = { _, index -> index.toString() }
) {
setIndexedItems(name, metas.map { MetaItem.NodeItem(it) }) { item, index -> indexFactory(item.node!!, index) }
}
public operator fun MutableItemProvider.set(name: Name, metas: Iterable<Meta>): Unit = setIndexed(name, metas)
public operator fun MutableItemProvider.set(name: String, metas: Iterable<Meta>): Unit = setIndexed(name.toName(), metas)

View File

@ -1,11 +1,6 @@
package hep.dataforge.meta
import hep.dataforge.names.*
import hep.dataforge.values.Value
public interface MutableItemProvider : ItemProvider {
public fun setItem(name: Name, item: MetaItem<*>?)
}
public interface MutableMeta<out M : MutableMeta<M>> : MetaNode<M>, MutableItemProvider {
override val items: Map<NameToken, MetaItem<M>>
@ -19,18 +14,18 @@ public interface MutableMeta<out M : MutableMeta<M>> : MetaNode<M>, MutableItemP
* Changes in Meta are not thread safe.
*/
public abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode<M>(), MutableMeta<M> {
protected val _items: MutableMap<NameToken, MetaItem<M>> = LinkedHashMap()
protected val children: MutableMap<NameToken, MetaItem<M>> = LinkedHashMap()
override val items: Map<NameToken, MetaItem<M>>
get() = _items
get() = children
//protected abstract fun itemChanged(name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?)
protected open fun replaceItem(key: NameToken, oldItem: MetaItem<M>?, newItem: MetaItem<M>?) {
if (newItem == null) {
_items.remove(key)
children.remove(key)
} else {
_items[key] = newItem
children[key] = newItem
}
//itemChanged(key.asName(), oldItem, newItem)
}
@ -72,48 +67,6 @@ public abstract class AbstractMutableMeta<M : MutableMeta<M>> : AbstractMetaNode
}
}
@Suppress("NOTHING_TO_INLINE")
public inline fun MutableMeta<*>.remove(name: Name): Unit = setItem(name, null)
@Suppress("NOTHING_TO_INLINE")
public inline fun MutableMeta<*>.remove(name: String): Unit = remove(name.toName())
public operator fun MutableMeta<*>.set(name: Name, item: MetaItem<*>?): Unit = setItem(name, item)
public fun MutableMeta<*>.setValue(name: Name, value: Value): Unit = setItem(name, MetaItem.ValueItem(value))
public fun MutableMeta<*>.setValue(name: String, value: Value): Unit = set(name.toName(), value)
public fun MutableMeta<*>.setItem(name: String, item: MetaItem<*>?): Unit = setItem(name.toName(), item)
public fun MutableMeta<*>.setNode(name: Name, node: Meta): Unit =
setItem(name, MetaItem.NodeItem(node))
public fun MutableMeta<*>.setNode(name: String, node: Meta): Unit = setNode(name.toName(), node)
/**
* Universal unsafe set method
*/
public operator fun MutableMeta<*>.set(name: Name, value: Any?) {
when (value) {
null -> remove(name)
is MetaItem<*> -> setItem(name, value)
is Meta -> setNode(name, value)
is Configurable -> setNode(name, value.config)
else -> setValue(name, Value.of(value))
}
}
public operator fun MutableMeta<*>.set(name: NameToken, value: Any?): Unit =
set(name.asName(), value)
public operator fun MutableMeta<*>.set(key: String, value: Any?): Unit =
set(key.toName(), value)
public operator fun MutableMeta<*>.set(key: String, index: String, value: Any?): Unit =
set(key.toName().withIndex(index), value)
/**
* Update existing mutable node with another node. The rules are following:
* * value replaces anything
@ -130,33 +83,6 @@ public fun <M : MutableMeta<M>> M.update(meta: Meta) {
}
}
/* Same name siblings generation */
public fun MutableMeta<*>.setIndexedItems(
name: Name,
items: Iterable<MetaItem<*>>,
indexFactory: (MetaItem<*>, index: Int) -> String = { _, index -> index.toString() }
) {
val tokens = name.tokens.toMutableList()
val last = tokens.last()
items.forEachIndexed { index, meta ->
val indexedToken = NameToken(last.body, last.index + indexFactory(meta, index))
tokens[tokens.lastIndex] = indexedToken
setItem(Name(tokens), meta)
}
}
public fun MutableMeta<*>.setIndexed(
name: Name,
metas: Iterable<Meta>,
indexFactory: (Meta, index: Int) -> String = { _, index -> index.toString() }
) {
setIndexedItems(name, metas.map { MetaItem.NodeItem(it) }) { item, index -> indexFactory(item.node!!, index) }
}
public operator fun MutableMeta<*>.set(name: Name, metas: Iterable<Meta>): Unit = setIndexed(name, metas)
public operator fun MutableMeta<*>.set(name: String, metas: Iterable<Meta>): Unit = setIndexed(name.toName(), metas)
/**
* Append the node with a same-name-sibling, automatically generating numerical index
*/

View File

@ -1,31 +1,49 @@
package hep.dataforge.meta
import hep.dataforge.meta.descriptors.Described
import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.meta.descriptors.defaultItem
import hep.dataforge.meta.descriptors.get
import hep.dataforge.meta.descriptors.*
import hep.dataforge.names.Name
import hep.dataforge.names.NameToken
import hep.dataforge.names.asName
/**
* 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(
config: Config,
defaultProvider: ItemProvider,
config: Config = Config(),
internal var default: ItemProvider? = null,
override val descriptor: NodeDescriptor? = null,
) : Configurable, Described, MetaRepr {
override var config: Config = config
internal set
public var defaultProvider: ItemProvider = defaultProvider
internal set
public fun getDefaultItem(name: Name): MetaItem<*>? {
return default?.getItem(name) ?: descriptor?.get(name)?.defaultItem()
}
public constructor() : this(Config(), ItemProvider { null })
/**
* Get a property with default
*/
override fun getItem(name: Name): MetaItem<*>? = config[name] ?: getDefaultItem(name)
override fun getDefaultItem(name: Name): MetaItem<*>? {
return defaultProvider.getItem(name) ?: descriptor?.get(name)?.defaultItem()
/**
* Check if property with given [name] could be assigned to [item]
*/
public fun validateItem(name: Name, item: MetaItem<*>?): Boolean {
val descriptor = descriptor?.get(name)
return descriptor?.validateItem(item) ?: true
}
/**
* Set a configurable property
*/
override fun setItem(name: Name, item: MetaItem<*>?) {
if (validateItem(name, item)) {
super.setItem(name, item)
} else {
error("Validation failed for property $name with value $item")
}
}
/**
@ -33,22 +51,23 @@ public open class Scheme(
* values if default value is unavailable.
* Values from [defaultProvider] completely replace
*/
public open val defaultLayer: Meta get() = DefaultLayer()
override fun toMeta(): Laminate = Laminate(config, defaultLayer)
private inner class DefaultLayer : MetaBase() {
override val items: Map<NameToken, MetaItem<*>> = buildMap {
descriptor?.items?.forEach { (key, itemDescriptor) ->
val token = NameToken(key)
val name = token.asName()
val item = defaultProvider.getItem(name) ?: itemDescriptor.defaultItem()
if (item != null) {
put(token, item)
public open val defaultLayer: Meta
get() = object : MetaBase() {
override val items: Map<NameToken, MetaItem<*>> = buildMap {
descriptor?.items?.forEach { (key, itemDescriptor) ->
val token = NameToken(key)
val name = token.asName()
val item = default?.getItem(name) ?: itemDescriptor.defaultItem()
if (item != null) {
put(token, item)
}
}
}
}
}
override fun toMeta(): Laminate = Laminate(config, defaultLayer)
public fun isEmpty(): Boolean = config.isEmpty()
}
/**
@ -66,30 +85,32 @@ public open class SchemeSpec<T : Scheme>(
public constructor(emptyBuilder: () -> T) : this({ config: Config, defaultProvider: ItemProvider ->
emptyBuilder().apply {
this.config = config
this.defaultProvider = defaultProvider
this.default = defaultProvider
}
})
override fun empty(): T = builder(Config(), ItemProvider.EMPTY)
override fun wrap(config: Config, defaultProvider: ItemProvider): T = builder(config, defaultProvider)
@Suppress("OVERRIDE_BY_INLINE")
final override inline operator fun invoke(action: T.() -> Unit): T = empty().apply(action)
/**
* If the provided [Meta] is a [Config] use it as a scheme base, otherwise use it as default.
*/
override fun wrap(meta: Meta, defaultProvider: ItemProvider): T = if (meta is Config) {
builder(meta, defaultProvider)
} else {
builder(Config(), meta.withDefault(defaultProvider))
}
}
/**
* A scheme that uses [Meta] as a default layer
*/
public open class MetaScheme(
private val meta: Meta,
override val descriptor: NodeDescriptor? = null,
config: Config = Config(),
) : Scheme(config, meta) {
override val defaultLayer: Meta get() = Laminate(meta, descriptor?.defaultItem().node)
}
///**
// * A scheme that uses [Meta] as a default layer
// */
//public open class MetaScheme(
// private val meta: Meta,
// override val descriptor: NodeDescriptor? = null,
// config: Config = Config(),
//) : Scheme(config, meta) {
// override val defaultLayer: Meta get() = Laminate(meta, descriptor?.defaultItem().node)
//}
public fun Meta.asScheme(): MetaScheme = MetaScheme(this)
public fun Meta.asScheme(): Scheme = Scheme(this.asConfig(), null, null)
public fun <T : Configurable> Meta.toScheme(spec: Specification<T>, block: T.() -> Unit = {}): T =
spec.wrap(this).apply(block)

View File

@ -1,32 +1,36 @@
package hep.dataforge.meta
import hep.dataforge.names.Name
import hep.dataforge.names.asName
import kotlin.jvm.JvmName
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
/**
* Allows to apply custom configuration in a type safe way to simple untyped configuration.
* By convention [Scheme] companion should inherit this class
*
*/
public interface Specification<T : Configurable> {
public fun empty(): T = wrap()
public interface Specification<T : MutableItemProvider> {
/**
* Wrap generic configuration producing instance of desired type
*/
public fun wrap(config: Config = Config(), defaultProvider: ItemProvider = ItemProvider{ null }): T
public operator fun invoke(action: T.() -> Unit): T = empty().apply(action)
public fun wrap(meta: Meta, defaultProvider: ItemProvider = ItemProvider.EMPTY): T
}
public operator fun <T : MutableItemProvider> Specification<T>.invoke(action: T.() -> Unit): T = empty().apply(action)
public fun <T : MutableItemProvider> Specification<T>.empty(): T = wrap(Config())
/**
* Update given configuration using given type as a builder
*/
public fun <T : Configurable> Specification<T>.update(config: Config, action: T.() -> Unit): T = wrap(config).apply(action)
public fun <T : MutableItemProvider> Specification<T>.update(meta: Meta, action: T.() -> Unit): T = wrap(meta).apply(action)
/**
* Wrap a configuration using static meta as default
* Create a read-only version of
*/
public fun <T : Configurable> Specification<T>.wrap(source: Meta): T {
public fun <T : MutableItemProvider> Specification<T>.wrap(source: Meta): T {
val default = source.seal()
return wrap(source.asConfig(), default)
}
@ -34,26 +38,56 @@ public fun <T : Configurable> Specification<T>.wrap(source: Meta): T {
/**
* Apply specified configuration to configurable
*/
public fun <T : Configurable, C : Configurable, S : Specification<C>> T.configure(spec: S, action: C.() -> Unit): T =
apply { spec.update(config, action) }
public fun <T : MetaRepr, C : MutableItemProvider, S : Specification<C>> T.configure(spec: S, action: C.() -> Unit): T =
apply { spec.update(toMeta(), action) }
/**
* Update configuration using given specification
*/
public fun <C : Configurable, S : Specification<C>> Configurable.update(spec: S, action: C.() -> Unit): Configurable =
public fun <C : MutableItemProvider, S : Specification<C>> Configurable.update(spec: S, action: C.() -> Unit): Configurable =
apply { spec.update(config, action) }
/**
* Create a style based on given specification
*/
public fun <C : Configurable, S : Specification<C>> S.createStyle(action: C.() -> Unit): Meta =
public fun <C : MutableItemProvider, S : Specification<C>> S.createStyle(action: C.() -> Unit): Meta =
Config().also { update(it, action) }
public fun <T : Configurable> MetaItem<*>.spec(spec: Specification<T>): T? = node?.let {
public fun <T : MutableItemProvider> MetaItem<*>.spec(spec: Specification<T>): T? = node?.let {
spec.wrap(
Config(), it
)
}
@JvmName("configSpec")
public fun <T : Configurable> MetaItem<Config>.spec(spec: Specification<T>): T? = node?.let { spec.wrap(it) }
public fun <T : MutableItemProvider> MetaItem<Config>.spec(spec: Specification<T>): T? = node?.let { spec.wrap(it) }
public fun <T : Scheme> MutableItemProvider.spec(
spec: Specification<T>, key: Name? = null
): ReadWriteProperty<Any?, T?> = object : ReadWriteProperty<Any?, T?> {
override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
val name = key ?: property.name.asName()
return getItem(name).node?.let { spec.wrap(it) }
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
val name = key ?: property.name.asName()
setItem(name, value?.toMeta()?.asMetaItem())
}
}
public fun <T : Scheme> MutableItemProvider.spec(
spec: Specification<T>,
default: T,
key: Name? = null
): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> {
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
val name = key ?: property.name.asName()
return getItem(name).node?.let { spec.wrap(it) } ?: default
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
val name = key ?: property.name.asName()
setItem(name, value.toMeta().asMetaItem())
}
}

View File

@ -1,9 +1,7 @@
package hep.dataforge.names
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.Serializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
@ -16,7 +14,7 @@ import kotlinx.serialization.encoding.Encoder
* The name is a dot separated list of strings like `token1.token2.token3`.
* Each token could contain additional index in square brackets.
*/
@Serializable
@Serializable(Name.Companion::class)
public class Name(public val tokens: List<NameToken>) {
//TODO to be transformed into inline class after they are supported with serialization
@ -38,8 +36,6 @@ public class Name(public val tokens: List<NameToken>) {
}
}
@OptIn(ExperimentalSerializationApi::class)
@Serializer(Name::class)
public companion object : KSerializer<Name> {
public const val NAME_SEPARATOR: String = "."
@ -82,55 +78,6 @@ public fun Name.lastOrNull(): NameToken? = tokens.lastOrNull()
*/
public fun Name.firstOrNull(): NameToken? = tokens.firstOrNull()
/**
* A single name token. Body is not allowed to be empty.
* Following symbols are prohibited in name tokens: `{}.:\`.
* A name token could have appendix in square brackets called *index*
*/
@Serializable
public data class NameToken(val body: String, val index: String? = null) {
init {
if (body.isEmpty()) error("Syntax error: Name token body is empty")
}
private fun String.escape() =
replace("\\", "\\\\")
.replace(".", "\\.")
.replace("[", "\\[")
.replace("]", "\\]")
override fun toString(): String = if (hasIndex()) {
"${body.escape()}[$index]"
} else {
body.escape()
}
@OptIn(ExperimentalSerializationApi::class)
@Serializer(NameToken::class)
public companion object : KSerializer<NameToken> {
override val descriptor: SerialDescriptor =
PrimitiveSerialDescriptor("hep.dataforge.names.NameToken", PrimitiveKind.STRING)
override fun deserialize(decoder: Decoder): NameToken {
return decoder.decodeString().toName().firstOrNull()!!
}
override fun serialize(encoder: Encoder, value: NameToken) {
encoder.encodeString(value.toString())
}
}
}
/**
* Check if index is defined for this token
*/
public fun NameToken.hasIndex(): Boolean = index != null
/**
* Add or replace index part of this token
*/
public fun NameToken.withIndex(newIndex: String): NameToken = NameToken(body, newIndex)
/**
* Convert a [String] to name parsing it and extracting name tokens and index syntax.

View File

@ -0,0 +1,60 @@
package hep.dataforge.names
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
/**
* A single name token. Body is not allowed to be empty.
* Following symbols are prohibited in name tokens: `{}.:\`.
* A name token could have appendix in square brackets called *index*
*/
@Serializable(NameToken.Companion::class)
public data class NameToken(val body: String, val index: String? = null) {
init {
if (body.isEmpty()) error("Syntax error: Name token body is empty")
}
private fun String.escape() =
replace("\\", "\\\\")
.replace(".", "\\.")
.replace("[", "\\[")
.replace("]", "\\]")
override fun toString(): String = if (hasIndex()) {
"${body.escape()}[$index]"
} else {
body.escape()
}
public companion object : KSerializer<NameToken> {
override val descriptor: SerialDescriptor =
PrimitiveSerialDescriptor("hep.dataforge.names.NameToken", PrimitiveKind.STRING)
override fun deserialize(decoder: Decoder): NameToken {
return decoder.decodeString().toName().firstOrNull()!!
}
override fun serialize(
encoder: Encoder,
value: NameToken,
) {
encoder.encodeString(value.toString())
}
}
}
/**
* Check if index is defined for this token
*/
public fun NameToken.hasIndex(): Boolean = index != null
/**
* Add or replace index part of this token
*/
public fun NameToken.withIndex(newIndex: String): NameToken = NameToken(body, newIndex)

View File

@ -19,6 +19,7 @@ public enum class ValueType {
*
* Value can represent a list of value objects.
*/
@Serializable(ValueSerializer::class)
public interface Value {
/**
* Get raw value of this value

View File

@ -1,8 +1,6 @@
package hep.dataforge.values
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializer
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
@ -10,8 +8,6 @@ import kotlinx.serialization.descriptors.element
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
@OptIn(ExperimentalSerializationApi::class)
@Serializer(Value::class)
public object ValueSerializer : KSerializer<Value> {
private val listSerializer by lazy { ListSerializer(ValueSerializer) }

View File

@ -1,5 +1,6 @@
package hep.dataforge.meta
import hep.dataforge.values.asValue
import kotlin.test.Test
import kotlin.test.assertEquals
@ -29,7 +30,7 @@ class MetaDelegateTest {
fun delegateTest() {
val testObject = TestScheme.empty()
testObject.config["myValue"] = "theString"
testObject.setValue("myValue","theString".asValue())
testObject.enumValue = TestEnum.NO
testObject.inner = InnerSpec { innerValue = "ddd" }

View File

@ -9,10 +9,8 @@ class SpecificationTest {
var list by numberList(1, 2, 3)
companion object : Specification<TestStyled> {
override fun wrap(
config: Config,
defaultProvider: ItemProvider
): TestStyled = TestStyled(config, defaultProvider)
override fun wrap(meta: Meta, defaultProvider: ItemProvider): TestStyled =
TestStyled(meta.asConfig(), defaultProvider)
}
}

View File

@ -1,6 +1,7 @@
package hep.dataforge.tables
import hep.dataforge.meta.Meta
import hep.dataforge.meta.invoke
import hep.dataforge.values.Value
import kotlin.reflect.KClass

View File

@ -1,6 +1,7 @@
package hep.dataforge.tables
import hep.dataforge.meta.Meta
import hep.dataforge.meta.invoke
import kotlin.reflect.KClass

View File

@ -29,7 +29,7 @@ public class DataDependency(private val filter: DataFilter, private val placemen
}
override fun toMeta(): Meta = Meta {
"data" put filter.config
"data" put filter.toMeta()
"to" put placement.toString()
}
}