Scheme made observable

This commit is contained in:
Alexander Nozik 2021-04-05 22:01:09 +03:00
parent ddd2bd99be
commit 9fbc482549
7 changed files with 71 additions and 15 deletions

33
.github/workflows/pages.yml vendored Normal file
View File

@ -0,0 +1,33 @@
name: Dokka publication
on:
push:
branches:
- master
jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: Checkout the repo
uses: actions/checkout@v2
- name: Set up JDK 11
uses: actions/setup-java@v1
with:
java-version: 11
- name: Cache gradle
uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ubuntu-20.04-gradle-${{ hashFiles('*.gradle.kts') }}
restore-keys: |
ubuntu-20.04-gradle-
- name: Build
run: |
./gradlew dokkaHtmlMultiModule --no-daemon --no-parallel --stacktrace
mv build/dokka/htmlMultiModule/-modules.html build/dokka/htmlMultiModule/index.html
- name: Deploy to GitHub Pages
uses: JamesIves/github-pages-deploy-action@4.1.0
with:
branch: gh-pages
folder: build/dokka/htmlMultiModule

View File

@ -4,15 +4,11 @@ plugins {
allprojects { allprojects {
group = "space.kscience" group = "space.kscience"
version = "0.4.0-dev-2" version = "0.4.0-dev-5"
} }
subprojects { subprojects {
apply(plugin = "maven-publish") apply(plugin = "maven-publish")
repositories {
maven("https://dl.bintray.com/mipt-npm/kscience")
maven("https://dl.bintray.com/mipt-npm/dev")
}
} }
readme { readme {

View File

@ -28,12 +28,11 @@ public interface DataSet<out T : Any> {
public suspend fun getData(name: Name): Data<T>? public suspend fun getData(name: Name): Data<T>?
/** /**
* Get a snapshot of names of children of given node. Empty if node does not exist or is a leaf. * Get a snapshot of names of top level children of given node. Empty if node does not exist or is a leaf.
*
* By default traverses the whole tree. Could be optimized in descendants
*/ */
public suspend fun listChildren(prefix: Name = Name.EMPTY): List<Name> = public suspend fun listTop(prefix: Name = Name.EMPTY): List<Name> =
flow().map { it.name }.filter { it.startsWith(prefix) && (it.length == prefix.length + 1) }.toList() flow().map { it.name }.filter { it.startsWith(prefix) && (it.length == prefix.length + 1) }.toList()
// By default traverses the whole tree. Could be optimized in descendants
public companion object { public companion object {
public val META_KEY: Name = "@meta".asName() public val META_KEY: Name = "@meta".asName()

View File

@ -43,7 +43,7 @@ public interface DataTree<out T : Any> : DataSet<T> {
} }
} }
override suspend fun listChildren(prefix: Name): List<Name> = override suspend fun listTop(prefix: Name): List<Name> =
getItem(prefix).tree?.items()?.keys?.map { prefix + it } ?: emptyList() getItem(prefix).tree?.items()?.keys?.map { prefix + it } ?: emptyList()
override suspend fun getData(name: Name): Data<T>? = when (name.length) { override suspend fun getData(name: Name): Data<T>? = when (name.length) {

View File

@ -433,12 +433,14 @@ 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 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/descriptors/Described { 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 fun <init> ()V public fun <init> ()V
public fun getDefaultLayer ()Lspace/kscience/dataforge/meta/Meta; public fun getDefaultLayer ()Lspace/kscience/dataforge/meta/Meta;
public synthetic fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor; public synthetic fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/ItemDescriptor;
public final fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor; public final fun getDescriptor ()Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;
public fun getItem (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMetaItem; public fun getItem (Lspace/kscience/dataforge/names/Name;)Lspace/kscience/dataforge/meta/TypedMetaItem;
public fun onChange (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)V
public fun removeListener (Ljava/lang/Object;)V
public final fun setDescriptor (Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;)V public final fun setDescriptor (Lspace/kscience/dataforge/meta/descriptors/NodeDescriptor;)V
public fun setItem (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/TypedMetaItem;)V public fun setItem (Lspace/kscience/dataforge/names/Name;Lspace/kscience/dataforge/meta/TypedMetaItem;)V
public fun toMeta ()Lspace/kscience/dataforge/meta/Laminate; public fun toMeta ()Lspace/kscience/dataforge/meta/Laminate;

View File

@ -4,19 +4,42 @@ import space.kscience.dataforge.meta.descriptors.*
import space.kscience.dataforge.names.Name import space.kscience.dataforge.names.Name
import space.kscience.dataforge.names.NameToken import space.kscience.dataforge.names.NameToken
import space.kscience.dataforge.names.asName import space.kscience.dataforge.names.asName
import kotlin.jvm.Synchronized
/** /**
* A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [Specification]. * 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 * Default item provider and [NodeDescriptor] are optional
*/ */
public open class Scheme() : MutableItemProvider, Described, MetaRepr { public open class Scheme() : MutableItemProvider, Described, MetaRepr, ObservableItemProvider {
private var items: MutableItemProvider = Config() private var items: MutableItemProvider = Config()
private val listeners = HashSet<ItemListener>()
private var default: ItemProvider? = null private var default: ItemProvider? = null
final override var descriptor: NodeDescriptor? = null final override var descriptor: NodeDescriptor? = null
/**
* Add a listener to this scheme changes. If the inner provider is observable, then listening will be delegated to it.
* Otherwise, local listeners will be created.
*/
@Synchronized
override fun onChange(owner: Any?, action: (Name, MetaItem?, MetaItem?) -> Unit) {
(items as? ObservableItemProvider)?.onChange(owner, action)
?: run { listeners.add(ItemListener(owner, action)) }
}
/**
* Remove all listeners belonging to given owner
*/
@Synchronized
override fun removeListener(owner: Any?) {
(items as? ObservableItemProvider)?.removeListener(owner)
?: listeners.removeAll { it.owner === owner }
}
internal fun wrap( internal fun wrap(
items: MutableItemProvider, items: MutableItemProvider,
default: ItemProvider? = null, default: ItemProvider? = null,
@ -50,13 +73,16 @@ public open class Scheme() : MutableItemProvider, Described, MetaRepr {
* Set a configurable property * Set a configurable property
*/ */
override fun setItem(name: Name, item: MetaItem?) { override fun setItem(name: Name, item: MetaItem?) {
val oldItem = items[name]
if (validateItem(name, item)) { if (validateItem(name, item)) {
items[name] = item items[name] = item
listeners.forEach { it.action(name, oldItem, item) }
} else { } else {
error("Validation failed for property $name with value $item") error("Validation failed for property $name with value $item")
} }
} }
/** /**
* Provide a default layer which returns items from [default] and falls back to descriptor * Provide a default layer which returns items from [default] and falls back to descriptor
* values if default value is unavailable. * values if default value is unavailable.
@ -100,7 +126,7 @@ public fun <T : Scheme, S : Specification<T>> S.wrap(
* Relocate scheme target onto given [MutableItemProvider]. Old provider does not get updates anymore. * Relocate scheme target onto given [MutableItemProvider]. Old provider does not get updates anymore.
* Current state of the scheme used as a default. * Current state of the scheme used as a default.
*/ */
public fun <T : Scheme> T.retarget(provider: MutableItemProvider) :T = apply { wrap(provider) } public fun <T : Scheme> T.retarget(provider: MutableItemProvider): T = apply { wrap(provider) }
/** /**
* A shortcut to edit a [Scheme] object in-place * A shortcut to edit a [Scheme] object in-place

View File

@ -7,8 +7,8 @@ pluginManagement {
maven("https://dl.bintray.com/kotlin/kotlin-eap") maven("https://dl.bintray.com/kotlin/kotlin-eap")
} }
val toolsVersion = "0.9.1" val toolsVersion = "0.9.3"
val kotlinVersion = "1.4.31" val kotlinVersion = "1.4.32"
plugins { plugins {
id("ru.mipt.npm.gradle.project") version toolsVersion id("ru.mipt.npm.gradle.project") version toolsVersion