Merge pull request #60 from mipt-npm/dev
0.3.0
This commit is contained in:
commit
a7ee2f5922
19
.github/workflows/build.yml
vendored
Normal file
19
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
name: Gradle build
|
||||
|
||||
on: [ push ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build
|
17
.github/workflows/gradle.yml
vendored
17
.github/workflows/gradle.yml
vendored
@ -1,17 +0,0 @@
|
||||
name: Gradle build
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Build with Gradle
|
||||
run: ./gradlew build
|
40
.github/workflows/publish.yml
vendored
Normal file
40
.github/workflows/publish.yml
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
name: Bintray Publish
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- created
|
||||
|
||||
jobs:
|
||||
build-on-windows:
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Gradle clean
|
||||
run: ./gradlew clean
|
||||
- name: Gradle build
|
||||
run: ./gradlew build
|
||||
- name: Run release task
|
||||
run: ./gradlew release -PbintrayUser=${{ secrets.BINTRAY_USER }} -PbintrayApiKey=${{ secrets.BINTRAY_KEY }}
|
||||
build-on-macos:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 11
|
||||
uses: actions/setup-java@v1
|
||||
with:
|
||||
java-version: 11
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
- name: Gradle clean
|
||||
run: ./gradlew clean
|
||||
- name: Gradle build
|
||||
run: ./gradlew build
|
||||
- name: Run release task
|
||||
run: ./gradlew release -PbintrayUser=${{ secrets.BINTRAY_USER }} -PbintrayApiKey=${{ secrets.BINTRAY_KEY }}
|
31
CHANGELOG.md
31
CHANGELOG.md
@ -12,6 +12,37 @@
|
||||
### Fixed
|
||||
|
||||
### Security
|
||||
|
||||
## [0.3.0]
|
||||
### Added
|
||||
- Yaml meta format based on yaml.kt
|
||||
- `Path` builders
|
||||
- Special ValueType for lists
|
||||
- `copy` method to descriptors
|
||||
- Multiplatform yaml meta
|
||||
|
||||
### Changed
|
||||
- `ListValue` and `DoubleArrayValue` implement `Iterable`.
|
||||
- Changed the logic of `Value::isList` to check for type instead of size
|
||||
- `Meta{}` builder made inline
|
||||
- Moved `Envelope` builder to a top level function. Companion invoke is deprecated.
|
||||
- Context logging moved to the extension
|
||||
- `number` and `string` methods on `Value` moved to extensions (breaking change)
|
||||
- \[Major breaking change\] Schemes and configurables us `MutableItemProvider` instead of `Config`
|
||||
- \[Major breaking change\] `MetaItem` renamed to `TypedMetaItem` and `MetaItem` is now an alias for `TypedMetaItem<*>`
|
||||
- \[Major breaking change\] Moved `NodeItem` and `ValueItem` to a top level
|
||||
- Plugins are removed from Context constructor and added lazily in ContextBuilder
|
||||
- \[Major breaking change\] Full refactor of DataTree/DataSource
|
||||
- \[Major Breaking change\] Replace KClass with KType in data. Remove direct access to constructors with types.
|
||||
|
||||
### Deprecated
|
||||
|
||||
### Removed
|
||||
|
||||
### Fixed
|
||||
|
||||
### Security
|
||||
|
||||
## [0.2.0]
|
||||
### Added
|
||||
|
||||
|
127
README.md
127
README.md
@ -5,98 +5,53 @@
|
||||
|
||||
[ ![Download](https://api.bintray.com/packages/mipt-npm/dataforge/dataforge-meta/images/download.svg) ](https://bintray.com/mipt-npm/dataforge/dataforge-meta/_latestVersion)
|
||||
|
||||
<hr/>
|
||||
|
||||
* ### [dataforge-context](dataforge-context)
|
||||
>
|
||||
>
|
||||
> **Maturity**: DEVELOPMENT
|
||||
<hr/>
|
||||
|
||||
# Questions and Answers #
|
||||
* ### [dataforge-data](dataforge-data)
|
||||
>
|
||||
>
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
<hr/>
|
||||
|
||||
In this section we will try to cover DataForge main ideas in the form of questions and answers.
|
||||
* ### [dataforge-io](dataforge-io)
|
||||
>
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
<hr/>
|
||||
|
||||
## General ##
|
||||
* ### [dataforge-meta](dataforge-meta)
|
||||
>
|
||||
>
|
||||
> **Maturity**: DEVELOPMENT
|
||||
<hr/>
|
||||
|
||||
**Q:** I have a lot of data to analyze. The analysis process is complicated, requires a lot of stages and data flow is not always obvious. To top it the data size is huge, so I don't want to perform operation I don't need (calculate something I won't need or calculate something twice). And yes, I need it to be performed in parallel and probably on remote computer. By the way, I am sick and tired of scripts that modify other scripts that control scripts. Could you help me?
|
||||
* ### [dataforge-scripting](dataforge-scripting)
|
||||
>
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
<hr/>
|
||||
|
||||
**A:** Yes, that is the precisely the problem DataForge was made to solve. It allows to perform some automated data manipulations with automatic optimization and parallelization. The important thing that data processing recipes are made in the declarative way, so it is quite easy to perform computations on a remote station. Also DataForge guarantees reproducibility of analysis results.
|
||||
<hr>
|
||||
* ### [dataforge-tables](dataforge-tables)
|
||||
>
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
<hr/>
|
||||
|
||||
**Q:** How does it work?
|
||||
* ### [dataforge-workspace](dataforge-workspace)
|
||||
>
|
||||
>
|
||||
> **Maturity**: EXPERIMENTAL
|
||||
<hr/>
|
||||
|
||||
**A:** At the core of DataForge lies the idea of **metadata processor**. It utilizes the statement that in order to analyze something you need data itself and some additional information about what does that data represent and what does user want as a result. This additional information is called metadata and could be organized in a regular structure (a tree of values not unlike XML or JSON). The important thing is that this distinction leaves no place for user instructions (or scripts). Indeed, the idea of DataForge logic is that one do not need imperative commands. The framework configures itself according to input meta-data and decides what operations should be performed in the most efficient way.
|
||||
<hr>
|
||||
* ### [dataforge-io-yaml](dataforge-io-yaml)
|
||||
> YAML meta converters and Front Matter envelope format
|
||||
>
|
||||
> **Maturity**: PROTOTYPE
|
||||
<hr/>
|
||||
|
||||
**Q:** But where does it take algorithms to use?
|
||||
|
||||
**A:** Of course algorithms must be written somewhere. No magic here. The logic is written in specialized modules. Some modules are provided out of the box at the system core, some need to be developed for specific problem.
|
||||
<hr>
|
||||
|
||||
**Q:** So I still need to write the code? What is the difference then?
|
||||
|
||||
**A:** Yes, someone still need to write the code. But not necessary you. Simple operations could be performed using provided core logic. Also your group can have one programmer writing the logic and all other using it without any real programming expertise. Also the framework organized in a such way that one writes some additional logic, he do not need to thing about complicated thing like parallel computing, resource handling, logging, caching etc. Most of the things are done by the DataForge.
|
||||
<hr>
|
||||
|
||||
## Platform ##
|
||||
|
||||
**Q:** Which platform does DataForge use? Which operation system is it working on?
|
||||
|
||||
**A:** The DataForge is mostly written in Java and utilizes JVM as a platform. It works on any system that supports JVM (meaning almost any modern system excluding some mobile platforms).
|
||||
<hr>
|
||||
|
||||
**Q:** But Java... it is slow!
|
||||
|
||||
**A:** [It is not](https://stackoverflow.com/questions/2163411/is-java-really-slow/2163570#2163570). It lacks some hardware specific optimizations and requires some additional time to start (due to JIT nature), but otherwise it is at least as fast as other languages traditionally used in science. More importantly, the memory safety, tooling support and vast ecosystem makes it №1 candidate for data analysis framework.
|
||||
|
||||
<hr>
|
||||
|
||||
**Q:** Can I use my C++/Fortran/Python code in DataForge?
|
||||
|
||||
**A:** Yes, as long as the code could be called from Java. Most of common languages have a bridge for Java access. There are completely no problems with compiled C/Fortran libraries. Python code could be called via one of existing python-java interfaces. It is also planned to implement remote method invocation for common languages, so your Python, or, say, Julia, code could run in its native environment. The metadata processor paradigm makes it much easier to do so.
|
||||
|
||||
<hr>
|
||||
|
||||
## Features ##
|
||||
|
||||
**Q:** What other features does DataForge provide?
|
||||
|
||||
**A:** Alongside metadata processing (and a lot of tools for metadata manipulation and layering), DataForge has two additional important concepts:
|
||||
|
||||
* **Modularisation**. Contrary to lot other frameworks, DataForge is intrinsically modular. The mandatory part is a rather tiny core module. Everything else could be customized.
|
||||
|
||||
* **Context encapsulation**. Every DataForge task is executed in some context. The context isolates environment for the task and also works as dependency injection base and specifies interaction of the task with the external world.
|
||||
|
||||
|
||||
<!--<hr>
|
||||
|
||||
**Q:** OK, but now I want to work directly with my measuring devices. How can I do that?
|
||||
|
||||
**A:** The [dataforge-control](${site.url}/docs.html#control) module provides interfaces to interact with the hardware. Out of the box it supports safe communication with TCP/IP or COM/tty based devices. Specific device declaration could be done via additional modules. It is also possible to maintain data storage with [datforge-storage](${site.url}/docs.htm#storage) module.-->
|
||||
|
||||
<hr>
|
||||
|
||||
<!--**Q:** Declarations and metadata are good, but I want my scripts back!
|
||||
|
||||
**A:** We can do that. [GRIND](${site.url}/docs.html#grind) provides a shell-like environment called GrindShell. It allows to run imperative scripts with full access to all of the DataForge functionality. Grind scripts are basically context-encapsulated. Also there are convenient feature wrappers called helpers that could be loaded into the shell when new features modules are added.-->
|
||||
|
||||
<hr>
|
||||
|
||||
## Misc ##
|
||||
|
||||
**Q:** So everything looks great, can I replace my ROOT / other data analysis framework with DataForge?
|
||||
|
||||
**A:** One must note, that DataForge is made for analysis, not for visualisation. The visualisation and user interaction capabilities of DataForge are rather limited compared to frameworks like ROOT, JAS3 or DataMelt. The idea is to provide reliable API and core functionality. In fact JAS3 and DataMelt could be used as a frontend for DataForge mechanics. It is planned to add an interface to ROOT via JFreeHep AIDA.
|
||||
|
||||
<hr>
|
||||
|
||||
**Q:** How does DataForge compare to cluster computation frameworks like Hadoop or Spark?
|
||||
|
||||
**A:** Again, it is not the purpose of DataForge to replace cluster software. DataForge has some internal parallelism mechanics and implementations, but they are most certainly worse then specially developed programs. Still, DataForge is not fixed on one single implementation. Your favourite parallel processing tool could be still used as a back-end for the DataForge. With full benefit of configuration tools, integrations and no performance overhead.
|
||||
<!--
|
||||
<hr>
|
||||
|
||||
**Q:** Is it possible to use DataForge in notebook mode?
|
||||
|
||||
**A:** Yes, it is. DataForge can be used as is from [beaker/beakerx](http://beakernotebook.com/) groovy kernel with minor additional adjustments. It is planned to provide separate DataForge kernel to `beakerx` which will automatically call a specific GRIND shell.-->
|
||||
|
||||
<hr>
|
||||
|
||||
**Q:** Can I use DataForge on a mobile platform?
|
||||
|
||||
**A:** DataForge is modular. Core and the most of api are pretty compact, so it could be used in Android applications. Some modules are designed for PC and could not be used on other platforms. IPhone does not support Java and therefore could use only client-side DataForge applications.
|
||||
|
@ -2,23 +2,27 @@ plugins {
|
||||
id("ru.mipt.npm.project")
|
||||
}
|
||||
|
||||
val dataforgeVersion by extra("0.2.0")
|
||||
val dataforgeVersion by extra("0.3.0")
|
||||
|
||||
|
||||
val bintrayRepo by extra("dataforge")
|
||||
val githubProject by extra("dataforge-core")
|
||||
val spaceRepo by extra("https://maven.jetbrains.space/mipt-npm/p/df/maven")
|
||||
|
||||
allprojects {
|
||||
group = "hep.dataforge"
|
||||
version = dataforgeVersion
|
||||
|
||||
apply<org.jetbrains.dokka.gradle.DokkaPlugin>()
|
||||
|
||||
repositories {
|
||||
mavenLocal()
|
||||
}
|
||||
}
|
||||
|
||||
subprojects {
|
||||
apply(plugin = "ru.mipt.npm.publish")
|
||||
}
|
||||
|
||||
readme {
|
||||
readmeTemplate = file("docs/templates/README-TEMPLATE.md")
|
||||
}
|
||||
|
||||
ksciencePublish {
|
||||
bintrayRepo = "dataforge"
|
||||
githubProject = "dataforge-core"
|
||||
spaceRepo = "https://maven.jetbrains.space/mipt-npm/p/df/maven"
|
||||
}
|
@ -4,16 +4,15 @@ public abstract class hep/dataforge/context/AbstractPlugin : hep/dataforge/conte
|
||||
public synthetic fun <init> (Lhep/dataforge/meta/Meta;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun attach (Lhep/dataforge/context/Context;)V
|
||||
public fun content (Ljava/lang/String;)Ljava/util/Map;
|
||||
public synthetic fun dependsOn ()Ljava/util/Collection;
|
||||
public final fun dependsOn ()Ljava/util/List;
|
||||
public final fun dependsOn ()Ljava/util/Map;
|
||||
public fun detach ()V
|
||||
public fun getContext ()Lhep/dataforge/context/Context;
|
||||
public fun getDefaultChainTarget ()Ljava/lang/String;
|
||||
public fun getDefaultTarget ()Ljava/lang/String;
|
||||
public fun getLogger ()Lmu/KLogger;
|
||||
public fun getMeta ()Lhep/dataforge/meta/Meta;
|
||||
public fun getName ()Lhep/dataforge/names/Name;
|
||||
protected final fun require (Lhep/dataforge/context/PluginFactory;)Lkotlin/properties/ReadOnlyProperty;
|
||||
protected final fun require (Lhep/dataforge/context/PluginFactory;Lhep/dataforge/meta/Meta;)Lkotlin/properties/ReadOnlyProperty;
|
||||
public static synthetic fun require$default (Lhep/dataforge/context/AbstractPlugin;Lhep/dataforge/context/PluginFactory;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
|
||||
public fun toMeta ()Lhep/dataforge/meta/Meta;
|
||||
}
|
||||
|
||||
@ -36,18 +35,15 @@ public final class hep/dataforge/context/ClassLoaderPluginKt {
|
||||
public static final fun getClassLoaderPlugin (Lhep/dataforge/context/Context;)Lhep/dataforge/context/ClassLoaderPlugin;
|
||||
}
|
||||
|
||||
public class hep/dataforge/context/Context : hep/dataforge/context/Named, hep/dataforge/meta/MetaRepr, hep/dataforge/provider/Provider, kotlinx/coroutines/CoroutineScope {
|
||||
public class hep/dataforge/context/Context : hep/dataforge/meta/MetaRepr, hep/dataforge/misc/Named, hep/dataforge/provider/Provider, kotlinx/coroutines/CoroutineScope {
|
||||
public static final field Companion Lhep/dataforge/context/Context$Companion;
|
||||
public static final field PROPERTY_TARGET Ljava/lang/String;
|
||||
public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/context/Context;Lhep/dataforge/meta/Meta;Ljava/util/Set;)V
|
||||
public synthetic fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/context/Context;Lhep/dataforge/meta/Meta;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun close ()V
|
||||
public fun content (Ljava/lang/String;)Ljava/util/Map;
|
||||
public final fun content (Ljava/lang/String;Z)Ljava/util/Map;
|
||||
public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
|
||||
public fun getDefaultChainTarget ()Ljava/lang/String;
|
||||
public fun getDefaultTarget ()Ljava/lang/String;
|
||||
public final fun getLogger ()Lmu/KLogger;
|
||||
public final fun getName ()Lhep/dataforge/names/Name;
|
||||
public final fun getParent ()Lhep/dataforge/context/Context;
|
||||
public final fun getPlugins ()Lhep/dataforge/context/PluginManager;
|
||||
@ -59,11 +55,6 @@ public final class hep/dataforge/context/Context$Companion {
|
||||
|
||||
public abstract interface class hep/dataforge/context/ContextAware {
|
||||
public abstract fun getContext ()Lhep/dataforge/context/Context;
|
||||
public abstract fun getLogger ()Lmu/KLogger;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/context/ContextAware$DefaultImpls {
|
||||
public static fun getLogger (Lhep/dataforge/context/ContextAware;)Lmu/KLogger;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/context/ContextBuilder {
|
||||
@ -72,7 +63,6 @@ public final class hep/dataforge/context/ContextBuilder {
|
||||
public synthetic fun <init> (Lhep/dataforge/context/Context;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun build ()Lhep/dataforge/context/Context;
|
||||
public final fun getName ()Ljava/lang/String;
|
||||
public final fun plugin (Lhep/dataforge/context/Plugin;)V
|
||||
public final fun plugin (Lhep/dataforge/context/PluginFactory;Lkotlin/jvm/functions/Function1;)V
|
||||
public final fun plugin (Lhep/dataforge/context/PluginTag;Lkotlin/jvm/functions/Function1;)V
|
||||
public final fun plugin (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lkotlin/jvm/functions/Function1;)V
|
||||
@ -83,6 +73,11 @@ public final class hep/dataforge/context/ContextBuilder {
|
||||
public final fun setName (Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
public final class hep/dataforge/context/ContextKt {
|
||||
public static final fun Context (Ljava/lang/String;Lhep/dataforge/context/Context;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/context/Context;
|
||||
public static synthetic fun Context$default (Ljava/lang/String;Lhep/dataforge/context/Context;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/context/Context;
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/context/Factory {
|
||||
public abstract fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
|
||||
}
|
||||
@ -100,24 +95,16 @@ public final class hep/dataforge/context/Global : hep/dataforge/context/Context
|
||||
public fun getCoroutineContext ()Lkotlin/coroutines/CoroutineContext;
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/context/Named {
|
||||
public static final field Companion Lhep/dataforge/context/Named$Companion;
|
||||
public abstract fun getName ()Lhep/dataforge/names/Name;
|
||||
public final class hep/dataforge/context/LoggingKt {
|
||||
public static final fun getLogger (Lhep/dataforge/context/Context;)Lmu/KLogger;
|
||||
public static final fun getLogger (Lhep/dataforge/context/ContextAware;)Lmu/KLogger;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/context/Named$Companion {
|
||||
public final fun nameOf (Ljava/lang/Object;)Lhep/dataforge/names/Name;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/context/NamedKt {
|
||||
public static final fun isAnonymous (Lhep/dataforge/context/Named;)Z
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/context/Plugin : hep/dataforge/context/ContextAware, hep/dataforge/context/Named, hep/dataforge/meta/MetaRepr, hep/dataforge/provider/Provider {
|
||||
public abstract interface class hep/dataforge/context/Plugin : hep/dataforge/context/ContextAware, hep/dataforge/meta/MetaRepr, hep/dataforge/misc/Named, hep/dataforge/provider/Provider {
|
||||
public static final field Companion Lhep/dataforge/context/Plugin$Companion;
|
||||
public static final field TARGET Ljava/lang/String;
|
||||
public abstract fun attach (Lhep/dataforge/context/Context;)V
|
||||
public abstract fun dependsOn ()Ljava/util/Collection;
|
||||
public abstract fun dependsOn ()Ljava/util/Map;
|
||||
public abstract fun detach ()V
|
||||
public abstract fun getMeta ()Lhep/dataforge/meta/Meta;
|
||||
public abstract fun getName ()Lhep/dataforge/names/Name;
|
||||
@ -133,7 +120,6 @@ public final class hep/dataforge/context/Plugin$DefaultImpls {
|
||||
public static fun content (Lhep/dataforge/context/Plugin;Ljava/lang/String;)Ljava/util/Map;
|
||||
public static fun getDefaultChainTarget (Lhep/dataforge/context/Plugin;)Ljava/lang/String;
|
||||
public static fun getDefaultTarget (Lhep/dataforge/context/Plugin;)Ljava/lang/String;
|
||||
public static fun getLogger (Lhep/dataforge/context/Plugin;)Lmu/KLogger;
|
||||
public static fun getName (Lhep/dataforge/context/Plugin;)Lhep/dataforge/names/Name;
|
||||
public static fun toMeta (Lhep/dataforge/context/Plugin;)Lhep/dataforge/meta/Meta;
|
||||
}
|
||||
@ -150,10 +136,10 @@ public final class hep/dataforge/context/PluginFactory$Companion {
|
||||
}
|
||||
|
||||
public final class hep/dataforge/context/PluginManager : hep/dataforge/context/ContextAware, java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker {
|
||||
public fun <init> (Lhep/dataforge/context/Context;Ljava/util/Set;)V
|
||||
public final fun fetch (Lhep/dataforge/context/PluginFactory;ZLhep/dataforge/meta/Meta;)Lhep/dataforge/context/Plugin;
|
||||
public fun <init> (Lhep/dataforge/context/Context;)V
|
||||
public final fun fetch (Lhep/dataforge/context/PluginFactory;Lhep/dataforge/meta/Meta;Z)Lhep/dataforge/context/Plugin;
|
||||
public final fun fetch (Lhep/dataforge/context/PluginFactory;ZLkotlin/jvm/functions/Function1;)Lhep/dataforge/context/Plugin;
|
||||
public static synthetic fun fetch$default (Lhep/dataforge/context/PluginManager;Lhep/dataforge/context/PluginFactory;ZLhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/context/Plugin;
|
||||
public static synthetic fun fetch$default (Lhep/dataforge/context/PluginManager;Lhep/dataforge/context/PluginFactory;Lhep/dataforge/meta/Meta;ZILjava/lang/Object;)Lhep/dataforge/context/Plugin;
|
||||
public static synthetic fun fetch$default (Lhep/dataforge/context/PluginManager;Lhep/dataforge/context/PluginFactory;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/context/Plugin;
|
||||
public final fun find (ZLkotlin/jvm/functions/Function1;)Lhep/dataforge/context/Plugin;
|
||||
public static synthetic fun find$default (Lhep/dataforge/context/PluginManager;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/context/Plugin;
|
||||
@ -162,7 +148,6 @@ public final class hep/dataforge/context/PluginManager : hep/dataforge/context/C
|
||||
public static synthetic fun get$default (Lhep/dataforge/context/PluginManager;Lhep/dataforge/context/PluginTag;ZILjava/lang/Object;)Lhep/dataforge/context/Plugin;
|
||||
public static synthetic fun get$default (Lhep/dataforge/context/PluginManager;Lkotlin/reflect/KClass;Lhep/dataforge/context/PluginTag;ZILjava/lang/Object;)Ljava/lang/Object;
|
||||
public fun getContext ()Lhep/dataforge/context/Context;
|
||||
public fun getLogger ()Lmu/KLogger;
|
||||
public fun iterator ()Ljava/util/Iterator;
|
||||
public final fun list (Z)Ljava/util/Collection;
|
||||
public final fun load (Lhep/dataforge/context/Plugin;)Lhep/dataforge/context/Plugin;
|
||||
@ -268,9 +253,6 @@ public final class hep/dataforge/provider/Path : java/lang/Iterable, kotlin/jvm/
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public static fun equals-impl (Ljava/util/List;Ljava/lang/Object;)Z
|
||||
public static final fun equals-impl0 (Ljava/util/List;Ljava/util/List;)Z
|
||||
public static final fun getHead-impl (Ljava/util/List;)Lhep/dataforge/provider/PathToken;
|
||||
public static final fun getLength-impl (Ljava/util/List;)I
|
||||
public static final fun getTail-e2ET3QM (Ljava/util/List;)Ljava/util/List;
|
||||
public final fun getTokens ()Ljava/util/List;
|
||||
public fun hashCode ()I
|
||||
public static fun hashCode-impl (Ljava/util/List;)I
|
||||
@ -282,12 +264,19 @@ public final class hep/dataforge/provider/Path : java/lang/Iterable, kotlin/jvm/
|
||||
}
|
||||
|
||||
public final class hep/dataforge/provider/Path$Companion {
|
||||
public final fun parse-IN54j3k (Ljava/lang/String;)Ljava/util/List;
|
||||
public final fun parse-AnEnhig (Ljava/lang/String;)Ljava/util/List;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/provider/PathKt {
|
||||
public static final fun plus-MQiGgVU (Ljava/util/List;Ljava/util/List;)Ljava/util/List;
|
||||
public static final fun toPath (Lhep/dataforge/provider/PathToken;)Ljava/util/List;
|
||||
public static final fun Path ([Lhep/dataforge/names/Name;)Ljava/util/List;
|
||||
public static final fun Path ([Lkotlin/Pair;)Ljava/util/List;
|
||||
public static final fun asPath (Lhep/dataforge/names/Name;Ljava/lang/String;)Ljava/util/List;
|
||||
public static final fun asPath (Lhep/dataforge/provider/PathToken;)Ljava/util/List;
|
||||
public static synthetic fun asPath$default (Lhep/dataforge/names/Name;Ljava/lang/String;ILjava/lang/Object;)Ljava/util/List;
|
||||
public static final fun getHead-Ipm_iiw (Ljava/util/List;)Lhep/dataforge/provider/PathToken;
|
||||
public static final fun getLength-Ipm_iiw (Ljava/util/List;)I
|
||||
public static final fun getTail-Ipm_iiw (Ljava/util/List;)Ljava/util/List;
|
||||
public static final fun plus-BlTXZnM (Ljava/util/List;Ljava/util/List;)Ljava/util/List;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/provider/PathToken {
|
||||
@ -323,12 +312,8 @@ public final class hep/dataforge/provider/Provider$DefaultImpls {
|
||||
}
|
||||
|
||||
public final class hep/dataforge/provider/ProviderKt {
|
||||
public static final fun provide-0Dbucg0 (Lhep/dataforge/provider/Provider;Ljava/util/List;Ljava/lang/String;)Ljava/lang/Object;
|
||||
public static synthetic fun provide-0Dbucg0$default (Lhep/dataforge/provider/Provider;Ljava/util/List;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/Object;
|
||||
public static final fun provide-mzxrFLw (Lhep/dataforge/provider/Provider;Ljava/util/List;Ljava/lang/String;)Ljava/lang/Object;
|
||||
public static synthetic fun provide-mzxrFLw$default (Lhep/dataforge/provider/Provider;Ljava/util/List;Ljava/lang/String;ILjava/lang/Object;)Ljava/lang/Object;
|
||||
public static final fun top (Lhep/dataforge/provider/Provider;Ljava/lang/String;Lkotlin/reflect/KClass;)Ljava/util/Map;
|
||||
}
|
||||
|
||||
public abstract interface annotation class hep/dataforge/provider/Type : java/lang/annotation/Annotation {
|
||||
public abstract fun id ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
|
@ -29,3 +29,7 @@ kotlin {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readme{
|
||||
maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package hep.dataforge.context
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.misc.Named
|
||||
import hep.dataforge.names.Name
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
import kotlin.reflect.KClass
|
||||
@ -8,7 +9,7 @@ import kotlin.reflect.KProperty
|
||||
|
||||
public abstract class AbstractPlugin(override val meta: Meta = Meta.EMPTY) : Plugin {
|
||||
private var _context: Context? = null
|
||||
private val dependencies = ArrayList<PluginFactory<*>>()
|
||||
private val dependencies = HashMap<PluginFactory<*>, Meta>()
|
||||
|
||||
override val context: Context
|
||||
get() = _context ?: error("Plugin $tag is not attached")
|
||||
@ -21,13 +22,13 @@ public abstract class AbstractPlugin(override val meta: Meta = Meta.EMPTY) : Plu
|
||||
this._context = null
|
||||
}
|
||||
|
||||
final override fun dependsOn(): List<PluginFactory<*>> = dependencies
|
||||
final override fun dependsOn(): Map<PluginFactory<*>, Meta> = dependencies
|
||||
|
||||
/**
|
||||
* Register plugin dependency and return a delegate which provides lazily initialized reference to dependent plugin
|
||||
*/
|
||||
protected fun <P : Plugin> require(factory: PluginFactory<P>): ReadOnlyProperty<AbstractPlugin, P> {
|
||||
dependencies.add(factory)
|
||||
protected fun <P : Plugin> require(factory: PluginFactory<P>, meta: Meta = Meta.EMPTY): ReadOnlyProperty<AbstractPlugin, P> {
|
||||
dependencies[factory] = meta
|
||||
return PluginDependencyDelegate(factory.type)
|
||||
}
|
||||
}
|
||||
|
@ -3,15 +3,13 @@ package hep.dataforge.context
|
||||
import hep.dataforge.meta.Laminate
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaRepr
|
||||
import hep.dataforge.meta.sequence
|
||||
import hep.dataforge.meta.itemSequence
|
||||
import hep.dataforge.misc.Named
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.plus
|
||||
import hep.dataforge.provider.Provider
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
import mu.KLogger
|
||||
import mu.KotlinLogging
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
/**
|
||||
@ -24,11 +22,10 @@ import kotlin.coroutines.CoroutineContext
|
||||
* be overridden by plugin implementation.
|
||||
*
|
||||
*/
|
||||
public open class Context(
|
||||
public open class Context internal constructor(
|
||||
final override val name: Name,
|
||||
public val parent: Context?,
|
||||
meta: Meta,
|
||||
plugins: Set<Plugin> = emptySet(),
|
||||
) : Named, MetaRepr, Provider, CoroutineScope {
|
||||
|
||||
/**
|
||||
@ -40,28 +37,23 @@ public open class Context(
|
||||
Laminate(meta, parent.properties)
|
||||
}
|
||||
|
||||
/**
|
||||
* Context logger
|
||||
*/
|
||||
public val logger: KLogger = KotlinLogging.logger(name.toString())
|
||||
|
||||
/**
|
||||
* A [PluginManager] for current context
|
||||
*/
|
||||
public val plugins: PluginManager by lazy { PluginManager(this, plugins)}
|
||||
public val plugins: PluginManager by lazy { PluginManager(this) }
|
||||
|
||||
override val defaultTarget: String get() = Plugin.TARGET
|
||||
|
||||
public fun content(target: String, inherit: Boolean): Map<Name, Any> {
|
||||
return if (inherit) {
|
||||
when (target) {
|
||||
PROPERTY_TARGET -> properties.sequence().toMap()
|
||||
PROPERTY_TARGET -> properties.itemSequence().toMap()
|
||||
Plugin.TARGET -> plugins.list(true).associateBy { it.name }
|
||||
else -> emptyMap()
|
||||
}
|
||||
} else {
|
||||
when (target) {
|
||||
PROPERTY_TARGET -> properties.layers.firstOrNull()?.sequence()?.toMap() ?: emptyMap()
|
||||
PROPERTY_TARGET -> properties.layers.firstOrNull()?.itemSequence()?.toMap() ?: emptyMap()
|
||||
Plugin.TARGET -> plugins.list(false).associateBy { it.name }
|
||||
else -> emptyMap()
|
||||
}
|
||||
@ -95,6 +87,9 @@ public open class Context(
|
||||
}
|
||||
}
|
||||
|
||||
public fun Context(name: String, parent: Context = Global, block: ContextBuilder.() -> Unit = {}): Context =
|
||||
Global.context(name, parent, block)
|
||||
|
||||
/**
|
||||
* The interface for something that encapsulated in context
|
||||
*
|
||||
@ -106,12 +101,4 @@ public interface ContextAware {
|
||||
* @return
|
||||
*/
|
||||
public val context: Context
|
||||
|
||||
public val logger: KLogger
|
||||
get() = if (this is Named) {
|
||||
KotlinLogging.logger((context.name + this.name).toString())
|
||||
} else {
|
||||
context.logger
|
||||
}
|
||||
|
||||
}
|
@ -1,24 +1,29 @@
|
||||
package hep.dataforge.context
|
||||
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
import hep.dataforge.meta.seal
|
||||
import hep.dataforge.misc.DFBuilder
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import hep.dataforge.names.toName
|
||||
import kotlin.collections.HashMap
|
||||
import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
import kotlin.collections.forEach
|
||||
import kotlin.collections.set
|
||||
|
||||
/**
|
||||
* A convenience builder for context
|
||||
*/
|
||||
@DFBuilder
|
||||
public class ContextBuilder(private val parent: Context = Global, public var name: String = "@anonymous") {
|
||||
private val plugins = HashSet<Plugin>()
|
||||
private val factories = HashMap<PluginFactory<*>, Meta>()
|
||||
private var meta = MetaBuilder()
|
||||
|
||||
public fun properties(action: MetaBuilder.() -> Unit) {
|
||||
meta.action()
|
||||
}
|
||||
|
||||
public fun plugin(plugin: Plugin) {
|
||||
plugins.add(plugin)
|
||||
}
|
||||
|
||||
@OptIn(DFExperimental::class)
|
||||
private fun findPluginFactory(tag: PluginTag): PluginFactory<*> =
|
||||
parent.gatherInSequence<PluginFactory<*>>(PluginFactory.TYPE).values
|
||||
@ -26,12 +31,11 @@ public class ContextBuilder(private val parent: Context = Global, public var nam
|
||||
|
||||
public fun plugin(tag: PluginTag, metaBuilder: MetaBuilder.() -> Unit = {}) {
|
||||
val factory = findPluginFactory(tag)
|
||||
val plugin = factory.invoke(Meta(metaBuilder), parent)
|
||||
plugins.add(plugin)
|
||||
factories[factory] = Meta(metaBuilder)
|
||||
}
|
||||
|
||||
public fun plugin(builder: PluginFactory<*>, action: MetaBuilder.() -> Unit = {}) {
|
||||
plugins.add(builder.invoke(Meta(action)))
|
||||
public fun plugin(factory: PluginFactory<*>, metaBuilder: MetaBuilder.() -> Unit = {}) {
|
||||
factories[factory] = Meta(metaBuilder)
|
||||
}
|
||||
|
||||
public fun plugin(name: String, group: String = "", version: String = "", action: MetaBuilder.() -> Unit = {}) {
|
||||
@ -39,6 +43,10 @@ public class ContextBuilder(private val parent: Context = Global, public var nam
|
||||
}
|
||||
|
||||
public fun build(): Context {
|
||||
return Context(name.toName(), parent, meta.seal(), plugins)
|
||||
return Context(name.toName(), parent, meta.seal()).apply {
|
||||
factories.forEach { (factory, meta) ->
|
||||
plugins.load(factory, meta)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -3,10 +3,11 @@ package hep.dataforge.context
|
||||
import hep.dataforge.context.Plugin.Companion.TARGET
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaRepr
|
||||
import hep.dataforge.misc.Named
|
||||
import hep.dataforge.misc.Type
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.toName
|
||||
import hep.dataforge.provider.Provider
|
||||
import hep.dataforge.provider.Type
|
||||
|
||||
/**
|
||||
* The interface to define a Context plugin. A plugin stores all runtime features of a context.
|
||||
@ -37,7 +38,7 @@ public interface Plugin : Named, ContextAware, Provider, MetaRepr {
|
||||
* dependencies must be initialized and enabled in the Context before this
|
||||
* plugin is enabled.
|
||||
*/
|
||||
public fun dependsOn(): Collection<PluginFactory<*>>
|
||||
public fun dependsOn(): Map<PluginFactory<*>, Meta>
|
||||
|
||||
/**
|
||||
* Start this plugin and attach registration info to the context. This method
|
||||
|
@ -0,0 +1,14 @@
|
||||
package hep.dataforge.context
|
||||
|
||||
import hep.dataforge.misc.Type
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
@Type(PluginFactory.TYPE)
|
||||
public interface PluginFactory<T : Plugin> : Factory<T> {
|
||||
public val tag: PluginTag
|
||||
public val type: KClass<out T>
|
||||
|
||||
public companion object {
|
||||
public const val TYPE: String = "pluginFactory"
|
||||
}
|
||||
}
|
@ -2,34 +2,23 @@ package hep.dataforge.context
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
import hep.dataforge.provider.Type
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
|
||||
@Type(PluginFactory.TYPE)
|
||||
public interface PluginFactory<T : Plugin> : Factory<T> {
|
||||
public val tag: PluginTag
|
||||
public val type: KClass<out T>
|
||||
|
||||
public companion object {
|
||||
public const val TYPE: String = "pluginFactory"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The manager for plugin system. Should monitor plugin dependencies and locks.
|
||||
*
|
||||
* @property context A context for this plugin manager
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
public class PluginManager(override val context: Context, plugins: Set<Plugin>) : ContextAware, Iterable<Plugin> {
|
||||
public class PluginManager(override val context: Context) : ContextAware, Iterable<Plugin> {
|
||||
|
||||
//TODO refactor to read-only container
|
||||
|
||||
/**
|
||||
* A set of loaded plugins
|
||||
*/
|
||||
private val plugins: HashSet<Plugin> = HashSet(plugins)
|
||||
private val plugins: HashSet<Plugin> = HashSet()
|
||||
|
||||
init {
|
||||
plugins.forEach { it.attach(context) }
|
||||
@ -100,8 +89,8 @@ public class PluginManager(override val context: Context, plugins: Set<Plugin>)
|
||||
if (get(plugin::class, plugin.tag, recursive = false) != null) {
|
||||
error("Plugin with tag ${plugin.tag} already exists in ${context.name}")
|
||||
} else {
|
||||
for (tag in plugin.dependsOn()) {
|
||||
fetch(tag, true)
|
||||
for ((factory, meta) in plugin.dependsOn()) {
|
||||
fetch(factory, meta, true)
|
||||
}
|
||||
|
||||
logger.info { "Loading plugin ${plugin.name} into ${context.name}" }
|
||||
@ -134,7 +123,7 @@ public class PluginManager(override val context: Context, plugins: Set<Plugin>)
|
||||
/**
|
||||
* Get an existing plugin with given meta or load new one using provided factory
|
||||
*/
|
||||
public fun <T : Plugin> fetch(factory: PluginFactory<T>, recursive: Boolean = true, meta: Meta = Meta.EMPTY): T {
|
||||
public fun <T : Plugin> fetch(factory: PluginFactory<T>, meta: Meta = Meta.EMPTY, recursive: Boolean = true): T {
|
||||
val loaded = get(factory.type, factory.tag, recursive)
|
||||
return when {
|
||||
loaded == null -> load(factory(meta, context))
|
||||
@ -147,7 +136,7 @@ public class PluginManager(override val context: Context, plugins: Set<Plugin>)
|
||||
factory: PluginFactory<T>,
|
||||
recursive: Boolean = true,
|
||||
metaBuilder: MetaBuilder.() -> Unit,
|
||||
): T = fetch(factory, recursive, Meta(metaBuilder))
|
||||
): T = fetch(factory, Meta(metaBuilder), recursive)
|
||||
|
||||
override fun iterator(): Iterator<Plugin> = plugins.iterator()
|
||||
|
||||
|
@ -0,0 +1,22 @@
|
||||
package hep.dataforge.context
|
||||
|
||||
import hep.dataforge.misc.Named
|
||||
import hep.dataforge.provider.Path
|
||||
import mu.KLogger
|
||||
import mu.KotlinLogging
|
||||
|
||||
/**
|
||||
* The logger specific to this context
|
||||
*/
|
||||
public val Context.logger: KLogger get() = KotlinLogging.logger(name.toString())
|
||||
|
||||
/**
|
||||
* The logger
|
||||
*/
|
||||
public val ContextAware.logger: KLogger
|
||||
get() = if (this is Named) {
|
||||
KotlinLogging.logger(Path(context.name, this.name).toString())
|
||||
} else {
|
||||
context.logger
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package hep.dataforge.context
|
||||
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.plus
|
||||
import hep.dataforge.provider.Provider
|
||||
@ -48,8 +48,9 @@ public fun <T : Any> Context.gather(
|
||||
putAll(top(target, type))
|
||||
plugins.forEach { plugin ->
|
||||
plugin.top(target, type).forEach { (name, value) ->
|
||||
if (containsKey(name)) error("Name conflict during gather. An item with name $name could not be gathered from $plugin because key is already present.")
|
||||
put(plugin.name + name, value)
|
||||
val itemName = plugin.name + name
|
||||
if (containsKey(itemName)) error("Name conflict during gather. An item with name $name could not be gathered from $plugin because key is already present.")
|
||||
put(itemName, value)
|
||||
}
|
||||
}
|
||||
if (inherit) {
|
||||
|
@ -1,11 +1,12 @@
|
||||
package hep.dataforge.properties
|
||||
|
||||
import hep.dataforge.meta.Config
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.meta.get
|
||||
import hep.dataforge.meta.set
|
||||
import hep.dataforge.meta.transformations.MetaConverter
|
||||
import hep.dataforge.meta.transformations.nullableItemToObject
|
||||
import hep.dataforge.meta.transformations.nullableObjectToMetaItem
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import hep.dataforge.names.Name
|
||||
|
||||
@DFExperimental
|
||||
@ -18,7 +19,7 @@ public class ConfigProperty<T : Any>(
|
||||
override var value: T?
|
||||
get() = converter.nullableItemToObject(config[name])
|
||||
set(value) {
|
||||
config.setItem(name,converter.nullableObjectToMetaItem(value))
|
||||
config[name] = converter.nullableObjectToMetaItem(value)
|
||||
}
|
||||
|
||||
override fun onChange(owner: Any?, callback: (T?) -> Unit) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
package hep.dataforge.properties
|
||||
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
@ -19,39 +19,39 @@ import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.toName
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* Path interface.
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
* @version $Id: $Id
|
||||
*/
|
||||
public inline class Path(public val tokens: List<PathToken>) : Iterable<PathToken> {
|
||||
|
||||
public val head: PathToken? get() = tokens.firstOrNull()
|
||||
|
||||
public val length: Int get() = tokens.size
|
||||
|
||||
/**
|
||||
* Returns non-empty optional containing the chain without first segment in case of chain path.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public val tail: Path? get() = if (tokens.isEmpty()) null else Path(tokens.drop(1))
|
||||
|
||||
override fun iterator(): Iterator<PathToken> = tokens.iterator()
|
||||
|
||||
override fun toString(): String = tokens.joinToString(separator = PATH_SEGMENT_SEPARATOR)
|
||||
|
||||
public companion object {
|
||||
public const val PATH_SEGMENT_SEPARATOR: String = "/"
|
||||
|
||||
public fun parse(path: String): Path {
|
||||
val head = path.substringBefore(PATH_SEGMENT_SEPARATOR)
|
||||
val tail = path.substringAfter(PATH_SEGMENT_SEPARATOR)
|
||||
return PathToken.parse(head).toPath() + parse(tail)
|
||||
return PathToken.parse(head).asPath() + parse(tail)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public val Path.length: Int get() = tokens.size
|
||||
|
||||
public val Path.head: PathToken? get() = tokens.firstOrNull()
|
||||
|
||||
|
||||
/**
|
||||
* Returns non-empty optional containing the chain without first segment in case of chain path.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public val Path.tail: Path? get() = if (tokens.isEmpty()) null else Path(tokens.drop(1))
|
||||
|
||||
|
||||
public operator fun Path.plus(path: Path): Path = Path(this.tokens + path.tokens)
|
||||
|
||||
public data class PathToken(val name: Name, val target: String? = null) {
|
||||
@ -72,4 +72,22 @@ public data class PathToken(val name: Name, val target: String? = null) {
|
||||
}
|
||||
}
|
||||
|
||||
public fun PathToken.toPath(): Path = Path(listOf(this))
|
||||
/**
|
||||
* Represent this path token as full path
|
||||
*/
|
||||
public fun PathToken.asPath(): Path = Path(listOf(this))
|
||||
|
||||
/**
|
||||
* Represent a name with optional [target] as a [Path]
|
||||
*/
|
||||
public fun Name.asPath(target: String? = null): Path = PathToken(this, target).asPath()
|
||||
|
||||
/**
|
||||
* Build a path from given names using default targets
|
||||
*/
|
||||
public fun Path(vararg names: Name): Path = Path(names.map { PathToken(it) })
|
||||
|
||||
/**
|
||||
* Use an array of [Name]-target pairs to construct segmented [Path]
|
||||
*/
|
||||
public fun Path(vararg tokens: Pair<Name, String?>): Path = Path(tokens.map { PathToken(it.first, it.second) })
|
@ -17,13 +17,13 @@ class ContextTest {
|
||||
else -> emptyMap()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPluginManager() {
|
||||
val context = Global.context("test"){
|
||||
plugin(DummyPlugin())
|
||||
}
|
||||
val context = Global.context("test")
|
||||
context.plugins.load(DummyPlugin())
|
||||
//Global.plugins.load(DummyPlugin())
|
||||
val members = context.gather<Name>("test")
|
||||
assertEquals(3, members.count())
|
||||
|
@ -1,10 +1,10 @@
|
||||
package hep.dataforge.properties
|
||||
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import org.w3c.dom.HTMLInputElement
|
||||
|
||||
@DFExperimental
|
||||
fun HTMLInputElement.bindValue(property: Property<String>) {
|
||||
public fun HTMLInputElement.bindValue(property: Property<String>) {
|
||||
if (this.onchange != null) error("Input element already bound")
|
||||
this.onchange = {
|
||||
property.value = this.value
|
||||
@ -18,7 +18,7 @@ fun HTMLInputElement.bindValue(property: Property<String>) {
|
||||
}
|
||||
|
||||
@DFExperimental
|
||||
fun HTMLInputElement.bindChecked(property: Property<Boolean>) {
|
||||
public fun HTMLInputElement.bindChecked(property: Property<Boolean>) {
|
||||
if (this.onchange != null) error("Input element already bound")
|
||||
this.onchange = {
|
||||
property.value = this.checked
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
package hep.dataforge.descriptors
|
||||
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.values.ValueType
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
|
@ -2,7 +2,8 @@ package hep.dataforge.provider
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.context.gather
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import hep.dataforge.misc.Type
|
||||
import hep.dataforge.names.Name
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.full.findAnnotation
|
||||
|
@ -26,6 +26,24 @@ public final class hep/dataforge/data/ActionKt {
|
||||
public static final fun then (Lhep/dataforge/data/Action;Lhep/dataforge/data/Action;)Lhep/dataforge/data/Action;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/ComputationData : hep/dataforge/data/ComputationGoal, hep/dataforge/data/Data {
|
||||
public fun <init> (Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)V
|
||||
public synthetic fun <init> (Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun getMeta ()Lhep/dataforge/meta/Meta;
|
||||
public fun getType ()Lkotlin/reflect/KClass;
|
||||
public fun toMeta ()Lhep/dataforge/meta/Meta;
|
||||
}
|
||||
|
||||
public class hep/dataforge/data/ComputationGoal : hep/dataforge/data/Goal {
|
||||
public fun <init> (Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)V
|
||||
public synthetic fun <init> (Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getBlock ()Lkotlin/jvm/functions/Function2;
|
||||
public fun getDependencies ()Ljava/util/Collection;
|
||||
public final fun getResult ()Lkotlinx/coroutines/Deferred;
|
||||
public fun reset ()V
|
||||
public fun startAsync (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Deferred;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/CoroutineMonitor : kotlin/coroutines/CoroutineContext$Element {
|
||||
public static final field Companion Lhep/dataforge/data/CoroutineMonitor$Companion;
|
||||
public fun <init> ()V
|
||||
@ -79,14 +97,6 @@ public final class hep/dataforge/data/Data$DefaultImpls {
|
||||
public static fun toMeta (Lhep/dataforge/data/Data;)Lhep/dataforge/meta/Meta;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/DataCastKt {
|
||||
public static final fun canCast (Lhep/dataforge/data/DataItem;Lkotlin/reflect/KClass;)Z
|
||||
public static final fun cast (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;)Lhep/dataforge/data/Data;
|
||||
public static final fun cast (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataNode;
|
||||
public static final fun ensureType (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)V
|
||||
public static final fun upcast (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;)Lhep/dataforge/data/Data;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/DataFilter : hep/dataforge/meta/Scheme {
|
||||
public static final field Companion Lhep/dataforge/data/DataFilter$Companion;
|
||||
public fun <init> ()V
|
||||
@ -129,17 +139,22 @@ public final class hep/dataforge/data/DataItem$Node : hep/dataforge/data/DataIte
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/DataJVMKt {
|
||||
public static final fun canCast (Lhep/dataforge/data/DataItem;Lkotlin/reflect/KClass;)Z
|
||||
public static final fun cast (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;)Lhep/dataforge/data/Data;
|
||||
public static final fun cast (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataNode;
|
||||
public static final fun ensureType (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)V
|
||||
public static final fun filterIsInstance (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;)Lhep/dataforge/data/Data;
|
||||
public static final fun filterIsInstance (Lhep/dataforge/data/DataItem;Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataItem;
|
||||
public static final fun filterIsInstance (Lhep/dataforge/data/DataNode;Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataNode;
|
||||
public static final fun get (Lhep/dataforge/data/Data;)Ljava/lang/Object;
|
||||
public static final fun upcast (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;)Lhep/dataforge/data/Data;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/DataKt {
|
||||
public static final fun map (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/data/Data;
|
||||
public static synthetic fun map$default (Lhep/dataforge/data/Data;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/data/Data;
|
||||
public static final fun reduce (Ljava/util/Map;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/data/DynamicData;
|
||||
public static synthetic fun reduce$default (Ljava/util/Map;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/data/DynamicData;
|
||||
public static final fun reduce (Ljava/util/Map;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;)Lhep/dataforge/data/ComputationData;
|
||||
public static synthetic fun reduce$default (Ljava/util/Map;Lkotlin/reflect/KClass;Lkotlin/coroutines/CoroutineContext;Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/data/ComputationData;
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/data/DataNode : hep/dataforge/meta/MetaRepr {
|
||||
@ -148,50 +163,36 @@ public abstract interface class hep/dataforge/data/DataNode : hep/dataforge/meta
|
||||
public abstract fun getItems ()Ljava/util/Map;
|
||||
public abstract fun getMeta ()Lhep/dataforge/meta/Meta;
|
||||
public abstract fun getType ()Lkotlin/reflect/KClass;
|
||||
public abstract fun startAll (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Job;
|
||||
public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/DataNode$Companion {
|
||||
public static final field TYPE Ljava/lang/String;
|
||||
public final fun builder (Lkotlin/reflect/KClass;)Lhep/dataforge/data/DataTreeBuilder;
|
||||
public final fun invoke (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/data/DataTree;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/DataNode$DefaultImpls {
|
||||
public static fun startAll (Lhep/dataforge/data/DataNode;Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Job;
|
||||
public static fun toMeta (Lhep/dataforge/data/DataNode;)Lhep/dataforge/meta/Meta;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/DataNodeKt {
|
||||
public static final fun asSequence (Lhep/dataforge/data/DataNode;)Lkotlin/sequences/Sequence;
|
||||
public static final fun builder (Lhep/dataforge/data/DataNode;)Lhep/dataforge/data/DataTreeBuilder;
|
||||
public static final fun dataSequence (Lhep/dataforge/data/DataNode;)Lkotlin/sequences/Sequence;
|
||||
public static final fun datum (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Lhep/dataforge/data/Data;)V
|
||||
public static final fun datum (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Lhep/dataforge/data/Data;)V
|
||||
public static final fun filter (Lhep/dataforge/data/DataNode;Lkotlin/jvm/functions/Function2;)Lhep/dataforge/data/DataNode;
|
||||
public static final fun first (Lhep/dataforge/data/DataNode;)Lhep/dataforge/data/Data;
|
||||
public static final fun get (Lhep/dataforge/data/DataNode;Lhep/dataforge/names/Name;)Lhep/dataforge/data/DataItem;
|
||||
public static final fun get (Lhep/dataforge/data/DataNode;Ljava/lang/String;)Lhep/dataforge/data/DataItem;
|
||||
public static final fun getData (Lhep/dataforge/data/DataItem;)Lhep/dataforge/data/Data;
|
||||
public static final fun getNode (Lhep/dataforge/data/DataItem;)Lhep/dataforge/data/DataNode;
|
||||
public static final fun itemSequence (Lhep/dataforge/data/DataNode;)Lkotlin/sequences/Sequence;
|
||||
public static final fun iterator (Lhep/dataforge/data/DataNode;)Ljava/util/Iterator;
|
||||
public static final fun join (Lhep/dataforge/data/DataNode;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
|
||||
public static final fun node (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Lhep/dataforge/data/DataNode;)V
|
||||
public static final fun node (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Lhep/dataforge/data/DataNode;)V
|
||||
public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lhep/dataforge/meta/Meta;)V
|
||||
public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
|
||||
public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
|
||||
public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)V
|
||||
public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
|
||||
public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
|
||||
public static final fun startAll (Lhep/dataforge/data/DataNode;Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Job;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/DataTree : hep/dataforge/data/DataNode {
|
||||
public fun getItems ()Ljava/util/Map;
|
||||
public fun getMeta ()Lhep/dataforge/meta/Meta;
|
||||
public fun getType ()Lkotlin/reflect/KClass;
|
||||
public fun startAll (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Job;
|
||||
public fun toMeta ()Lhep/dataforge/meta/Meta;
|
||||
}
|
||||
|
||||
@ -214,6 +215,21 @@ public final class hep/dataforge/data/DataTreeBuilder {
|
||||
public final fun update (Lhep/dataforge/data/DataNode;)V
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/DataTreeBuilderKt {
|
||||
public static final fun DataTree (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/data/DataTree;
|
||||
public static final fun builder (Lhep/dataforge/data/DataNode;)Lhep/dataforge/data/DataTreeBuilder;
|
||||
public static final fun datum (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Lhep/dataforge/data/Data;)V
|
||||
public static final fun datum (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Lhep/dataforge/data/Data;)V
|
||||
public static final fun node (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Lhep/dataforge/data/DataNode;)V
|
||||
public static final fun node (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Lhep/dataforge/data/DataNode;)V
|
||||
public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lhep/dataforge/meta/Meta;)V
|
||||
public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
|
||||
public static final fun static (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;)V
|
||||
public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)V
|
||||
public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Lhep/dataforge/names/Name;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
|
||||
public static synthetic fun static$default (Lhep/dataforge/data/DataTreeBuilder;Ljava/lang/String;Ljava/lang/Object;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)V
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/Dependencies : kotlin/coroutines/CoroutineContext$Element {
|
||||
public static final field Companion Lhep/dataforge/data/Dependencies$Companion;
|
||||
public fun <init> (Ljava/util/Collection;)V
|
||||
@ -228,24 +244,6 @@ public final class hep/dataforge/data/Dependencies : kotlin/coroutines/Coroutine
|
||||
public final class hep/dataforge/data/Dependencies$Companion : kotlin/coroutines/CoroutineContext$Key {
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/DynamicData : hep/dataforge/data/DynamicGoal, hep/dataforge/data/Data {
|
||||
public fun <init> (Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)V
|
||||
public synthetic fun <init> (Lkotlin/reflect/KClass;Lhep/dataforge/meta/Meta;Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public fun getMeta ()Lhep/dataforge/meta/Meta;
|
||||
public fun getType ()Lkotlin/reflect/KClass;
|
||||
public fun toMeta ()Lhep/dataforge/meta/Meta;
|
||||
}
|
||||
|
||||
public class hep/dataforge/data/DynamicGoal : hep/dataforge/data/Goal {
|
||||
public fun <init> (Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;)V
|
||||
public synthetic fun <init> (Lkotlin/coroutines/CoroutineContext;Ljava/util/Collection;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun getBlock ()Lkotlin/jvm/functions/Function2;
|
||||
public fun getDependencies ()Ljava/util/Collection;
|
||||
public final fun getResult ()Lkotlinx/coroutines/Deferred;
|
||||
public fun reset ()V
|
||||
public fun startAsync (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Deferred;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/FragmentRule {
|
||||
public field result Lkotlin/jvm/functions/Function2;
|
||||
public fun <init> (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaBuilder;)V
|
||||
@ -302,9 +300,7 @@ public final class hep/dataforge/data/JoinGroup {
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/MapAction : hep/dataforge/data/Action {
|
||||
public fun <init> (Lkotlin/reflect/KClass;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
|
||||
public final fun getInputType ()Lkotlin/reflect/KClass;
|
||||
public final fun getOutputType ()Lkotlin/reflect/KClass;
|
||||
public fun <init> (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
|
||||
public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
|
||||
public fun isTerminal ()Z
|
||||
}
|
||||
@ -335,9 +331,7 @@ public final class hep/dataforge/data/NamedData : hep/dataforge/data/Data {
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/ReduceAction : hep/dataforge/data/Action {
|
||||
public fun <init> (Lkotlin/reflect/KClass;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
|
||||
public final fun getInputType ()Lkotlin/reflect/KClass;
|
||||
public final fun getOutputType ()Lkotlin/reflect/KClass;
|
||||
public fun <init> (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
|
||||
public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
|
||||
public fun isTerminal ()Z
|
||||
}
|
||||
@ -357,9 +351,7 @@ public final class hep/dataforge/data/ReduceGroupBuilder {
|
||||
}
|
||||
|
||||
public final class hep/dataforge/data/SplitAction : hep/dataforge/data/Action {
|
||||
public fun <init> (Lkotlin/reflect/KClass;Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
|
||||
public final fun getInputType ()Lkotlin/reflect/KClass;
|
||||
public final fun getOutputType ()Lkotlin/reflect/KClass;
|
||||
public fun <init> (Lkotlin/reflect/KClass;Lkotlin/jvm/functions/Function1;)V
|
||||
public fun invoke (Lhep/dataforge/data/DataNode;Lhep/dataforge/meta/Meta;)Lhep/dataforge/data/DataNode;
|
||||
public fun isTerminal ()Z
|
||||
}
|
||||
@ -394,7 +386,6 @@ public final class hep/dataforge/data/TypeFilteredDataNode : hep/dataforge/data/
|
||||
public fun getMeta ()Lhep/dataforge/meta/Meta;
|
||||
public final fun getOrigin ()Lhep/dataforge/data/DataNode;
|
||||
public fun getType ()Lkotlin/reflect/KClass;
|
||||
public fun startAll (Lkotlinx/coroutines/CoroutineScope;)Lkotlinx/coroutines/Job;
|
||||
public fun toMeta ()Lhep/dataforge/meta/Meta;
|
||||
}
|
||||
|
||||
|
@ -12,12 +12,12 @@ kotlin {
|
||||
commonMain{
|
||||
dependencies {
|
||||
api(project(":dataforge-meta"))
|
||||
}
|
||||
}
|
||||
jvmMain{
|
||||
dependencies{
|
||||
api(kotlin("reflect"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readme{
|
||||
maturity = ru.mipt.npm.gradle.Maturity.EXPERIMENTAL
|
||||
}
|
||||
|
@ -0,0 +1,41 @@
|
||||
package hep.dataforge.actions
|
||||
|
||||
import hep.dataforge.data.DataSet
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
|
||||
/**
|
||||
* A simple data transformation on a data node. Actions should avoid doing actual dependency evaluation in [execute].
|
||||
*/
|
||||
public interface Action<in T : Any, out R : Any> {
|
||||
/**
|
||||
* Transform the data in the node, producing a new node. By default it is assumed that all calculations are lazy
|
||||
* so not actual computation is started at this moment.
|
||||
*
|
||||
* [scope] context used to compute the initial result, also it is used for updates propagation
|
||||
*/
|
||||
public suspend fun execute(dataSet: DataSet<T>, meta: Meta = Meta.EMPTY, scope: CoroutineScope? = null): DataSet<R>
|
||||
|
||||
public companion object
|
||||
}
|
||||
|
||||
/**
|
||||
* Action composition. The result is terminal if one of its parts is terminal
|
||||
*/
|
||||
public infix fun <T : Any, I : Any, R : Any> Action<T, I>.then(action: Action<I, R>): Action<T, R> {
|
||||
// TODO introduce composite action and add optimize by adding action to the list
|
||||
return object : Action<T, R> {
|
||||
override suspend fun execute(dataSet: DataSet<T>, meta: Meta, scope: CoroutineScope?): DataSet<R> {
|
||||
return action.execute(this@then.execute(dataSet, meta, scope), meta, scope)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@DFExperimental
|
||||
public suspend fun <T : Any, R : Any> DataSet<T>.transformWith(
|
||||
action: Action<T, R>,
|
||||
meta: Meta = Meta.EMPTY,
|
||||
scope: CoroutineScope? = null,
|
||||
): DataSet<R> = action.execute(this, meta, scope)
|
||||
|
@ -0,0 +1,104 @@
|
||||
package hep.dataforge.actions
|
||||
|
||||
import hep.dataforge.data.*
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
import hep.dataforge.meta.seal
|
||||
import hep.dataforge.meta.toMutableMeta
|
||||
import hep.dataforge.misc.DFBuilder
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import hep.dataforge.misc.DFInternal
|
||||
import hep.dataforge.names.Name
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
/**
|
||||
* Action environment includes data name, data meta and action configuration meta
|
||||
*/
|
||||
public data class ActionEnv(
|
||||
val name: Name,
|
||||
val meta: Meta,
|
||||
val actionMeta: Meta,
|
||||
)
|
||||
|
||||
/**
|
||||
* Action environment
|
||||
*/
|
||||
@DFBuilder
|
||||
public class MapActionBuilder<T, R>(public var name: Name, public var meta: MetaBuilder, public val actionMeta: Meta) {
|
||||
public lateinit var result: suspend ActionEnv.(T) -> R
|
||||
|
||||
/**
|
||||
* Calculate the result of goal
|
||||
*/
|
||||
public fun result(f: suspend ActionEnv.(T) -> R) {
|
||||
result = f;
|
||||
}
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal class MapAction<in T : Any, out R : Any>(
|
||||
private val outputType: KType,
|
||||
private val block: MapActionBuilder<T, R>.() -> Unit,
|
||||
) : Action<T, R> {
|
||||
|
||||
override suspend fun execute(
|
||||
dataSet: DataSet<T>,
|
||||
meta: Meta,
|
||||
scope: CoroutineScope?,
|
||||
): DataSet<R> {
|
||||
suspend fun mapOne(data: NamedData<T>): NamedData<R> {
|
||||
// Creating a new environment for action using **old** name, old meta and task meta
|
||||
val env = ActionEnv(data.name, data.meta, meta)
|
||||
|
||||
//applying transformation from builder
|
||||
val builder = MapActionBuilder<T, R>(
|
||||
data.name,
|
||||
data.meta.toMutableMeta(), // using data meta
|
||||
meta
|
||||
).apply(block)
|
||||
|
||||
//getting new name
|
||||
val newName = builder.name
|
||||
|
||||
//getting new meta
|
||||
val newMeta = builder.meta.seal()
|
||||
|
||||
@OptIn(DFInternal::class) val newData = Data(outputType, newMeta, dependencies = listOf(data)) {
|
||||
builder.result(env, data.await())
|
||||
}
|
||||
//setting the data node
|
||||
return newData.named(newName)
|
||||
}
|
||||
|
||||
val flow = dataSet.flow().map(::mapOne)
|
||||
|
||||
return ActiveDataTree(outputType) {
|
||||
populate(flow)
|
||||
scope?.launch {
|
||||
dataSet.updates.collect { name ->
|
||||
//clear old nodes
|
||||
remove(name)
|
||||
//collect new items
|
||||
populate(dataSet.flowChildren(name).map(::mapOne))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A one-to-one mapping action
|
||||
*/
|
||||
@DFExperimental
|
||||
@Suppress("FunctionName")
|
||||
public inline fun <T : Any, reified R : Any> Action.Companion.map(
|
||||
noinline builder: MapActionBuilder<T, R>.() -> Unit,
|
||||
): Action<T, R> = MapAction(typeOf<R>(), builder)
|
||||
|
||||
|
@ -0,0 +1,116 @@
|
||||
package hep.dataforge.actions
|
||||
|
||||
import hep.dataforge.data.*
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
import hep.dataforge.misc.DFBuilder
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import hep.dataforge.misc.DFInternal
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.toName
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.fold
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
|
||||
public class JoinGroup<T : Any, R : Any>(public var name: String, internal val set: DataSet<T>) {
|
||||
|
||||
public var meta: MetaBuilder = MetaBuilder()
|
||||
|
||||
public lateinit var result: suspend ActionEnv.(Map<Name, T>) -> R
|
||||
|
||||
public fun result(f: suspend ActionEnv.(Map<Name, T>) -> R) {
|
||||
this.result = f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@DFBuilder
|
||||
public class ReduceGroupBuilder<T : Any, R : Any>(
|
||||
private val inputType: KType,
|
||||
private val scope: CoroutineScope,
|
||||
public val actionMeta: Meta,
|
||||
) {
|
||||
private val groupRules: MutableList<suspend (DataSet<T>) -> List<JoinGroup<T, R>>> = ArrayList();
|
||||
|
||||
/**
|
||||
* introduce grouping by meta value
|
||||
*/
|
||||
public fun byValue(tag: String, defaultTag: String = "@default", action: JoinGroup<T, R>.() -> Unit) {
|
||||
groupRules += { node ->
|
||||
GroupRule.byMetaValue(scope, tag, defaultTag).gather(node).map {
|
||||
JoinGroup<T, R>(it.key, it.value).apply(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun group(
|
||||
groupName: String,
|
||||
filter: suspend (Name, Data<T>) -> Boolean,
|
||||
action: JoinGroup<T, R>.() -> Unit,
|
||||
) {
|
||||
groupRules += { source ->
|
||||
listOf(
|
||||
JoinGroup<T, R>(groupName, source.filter(filter)).apply(action)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply transformation to the whole node
|
||||
*/
|
||||
public fun result(resultName: String, f: suspend ActionEnv.(Map<Name, T>) -> R) {
|
||||
groupRules += { node ->
|
||||
listOf(JoinGroup<T, R>(resultName, node).apply { result(f) })
|
||||
}
|
||||
}
|
||||
|
||||
internal suspend fun buildGroups(input: DataSet<T>): List<JoinGroup<T, R>> {
|
||||
return groupRules.flatMap { it.invoke(input) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@PublishedApi
|
||||
internal class ReduceAction<T : Any, R : Any>(
|
||||
private val inputType: KType,
|
||||
outputType: KType,
|
||||
private val action: ReduceGroupBuilder<T, R>.() -> Unit,
|
||||
) : CachingAction<T, R>(outputType) {
|
||||
//TODO optimize reduction. Currently the whole action recalculates on push
|
||||
|
||||
|
||||
override fun CoroutineScope.transform(set: DataSet<T>, meta: Meta, key: Name): Flow<NamedData<R>> = flow {
|
||||
ReduceGroupBuilder<T, R>(inputType, this@transform, meta).apply(action).buildGroups(set).forEach { group ->
|
||||
val dataFlow: Map<Name, Data<T>> = group.set.flow().fold(HashMap()) { acc, value ->
|
||||
acc.apply {
|
||||
acc[value.name] = value.data
|
||||
}
|
||||
}
|
||||
|
||||
val groupName: String = group.name
|
||||
|
||||
val groupMeta = group.meta
|
||||
|
||||
val env = ActionEnv(groupName.toName(), groupMeta, meta)
|
||||
@OptIn(DFInternal::class) val res: Data<R> = dataFlow.reduceToData(
|
||||
outputType,
|
||||
meta = groupMeta
|
||||
) { group.result.invoke(env, it) }
|
||||
|
||||
emit(res.named(env.name))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A one-to-one mapping action
|
||||
*/
|
||||
@DFExperimental
|
||||
@Suppress("FunctionName")
|
||||
public inline fun <reified T : Any, reified R : Any> Action.Companion.reduce(
|
||||
noinline builder: ReduceGroupBuilder<T, R>.() -> Unit,
|
||||
): Action<T, R> = ReduceAction(typeOf<T>(), typeOf<R>(), builder)
|
@ -0,0 +1,96 @@
|
||||
package hep.dataforge.actions
|
||||
|
||||
import hep.dataforge.data.*
|
||||
import hep.dataforge.meta.Laminate
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
import hep.dataforge.meta.toMutableMeta
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import hep.dataforge.misc.DFInternal
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.toName
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.collections.set
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
|
||||
public class SplitBuilder<T : Any, R : Any>(public val name: Name, public val meta: Meta) {
|
||||
|
||||
public class FragmentRule<T : Any, R : Any>(public val name: Name, public var meta: MetaBuilder) {
|
||||
public lateinit var result: suspend (T) -> R
|
||||
|
||||
public fun result(f: suspend (T) -> R) {
|
||||
result = f;
|
||||
}
|
||||
}
|
||||
|
||||
internal val fragments: MutableMap<Name, FragmentRule<T, R>.() -> Unit> = HashMap()
|
||||
|
||||
/**
|
||||
* Add new fragment building rule. If the framgent not defined, result won't be available even if it is present in the map
|
||||
* @param name the name of a fragment
|
||||
* @param rule the rule to transform fragment name and meta using
|
||||
*/
|
||||
public fun fragment(name: String, rule: FragmentRule<T, R>.() -> Unit) {
|
||||
fragments[name.toName()] = rule
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Action that splits each incoming element into a number of fragments defined in builder
|
||||
*/
|
||||
@PublishedApi
|
||||
internal class SplitAction<T : Any, R : Any>(
|
||||
private val outputType: KType,
|
||||
private val action: SplitBuilder<T, R>.() -> Unit,
|
||||
) : Action<T, R> {
|
||||
|
||||
@OptIn(FlowPreview::class)
|
||||
override suspend fun execute(
|
||||
dataSet: DataSet<T>,
|
||||
meta: Meta,
|
||||
scope: CoroutineScope?,
|
||||
): DataSet<R> {
|
||||
|
||||
suspend fun splitOne(data: NamedData<T>): Flow<NamedData<R>> {
|
||||
val laminate = Laminate(data.meta, meta)
|
||||
|
||||
val split = SplitBuilder<T, R>(data.name, data.meta).apply(action)
|
||||
|
||||
|
||||
// apply individual fragment rules to result
|
||||
return split.fragments.entries.asFlow().map { (fragmentName, rule) ->
|
||||
val env = SplitBuilder.FragmentRule<T, R>(fragmentName, laminate.toMutableMeta()).apply(rule)
|
||||
//data.map<R>(outputType, meta = env.meta) { env.result(it) }.named(fragmentName)
|
||||
@OptIn(DFInternal::class) Data(outputType, meta = env.meta, dependencies = listOf(data)) {
|
||||
env.result(data.await())
|
||||
}.named(fragmentName)
|
||||
}
|
||||
}
|
||||
|
||||
return ActiveDataTree<R>(outputType) {
|
||||
populate(dataSet.flow().flatMapConcat(transform = ::splitOne))
|
||||
scope?.launch {
|
||||
dataSet.updates.collect { name ->
|
||||
//clear old nodes
|
||||
remove(name)
|
||||
//collect new items
|
||||
populate(dataSet.flowChildren(name).flatMapConcat(transform = ::splitOne))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Action that splits each incoming element into a number of fragments defined in builder
|
||||
*/
|
||||
@DFExperimental
|
||||
@Suppress("FunctionName")
|
||||
public inline fun <T : Any, reified R : Any> Action.Companion.split(
|
||||
noinline builder: SplitBuilder<T, R>.() -> Unit,
|
||||
): Action<T, R> = SplitAction(typeOf<R>(), builder)
|
@ -1,35 +0,0 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
|
||||
/**
|
||||
* A simple data transformation on a data node
|
||||
*/
|
||||
public interface Action<in T : Any, out R : Any> {
|
||||
/**
|
||||
* Transform the data in the node, producing a new node. By default it is assumed that all calculations are lazy
|
||||
* so not actual computation is started at this moment
|
||||
*/
|
||||
public operator fun invoke(node: DataNode<T>, meta: Meta): DataNode<R>
|
||||
|
||||
/**
|
||||
* Terminal action is the one that could not be invoked lazily and requires some kind of blocking computation to invoke
|
||||
*/
|
||||
public val isTerminal: Boolean get() = false
|
||||
}
|
||||
|
||||
/**
|
||||
* Action composition. The result is terminal if one of its parts is terminal
|
||||
*/
|
||||
public infix fun <T : Any, I : Any, R : Any> Action<T, I>.then(action: Action<I, R>): Action<T, R> {
|
||||
// TODO introduce composite action and add optimize by adding action to the list
|
||||
return object : Action<T, R> {
|
||||
override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> {
|
||||
return action(this@then.invoke(node, meta), meta)
|
||||
}
|
||||
|
||||
override val isTerminal: Boolean
|
||||
get() = this@then.isTerminal || action.isTerminal
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,118 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
/**
|
||||
* A mutable [DataTree.Companion.active]. It
|
||||
*/
|
||||
public class ActiveDataTree<T : Any>(
|
||||
override val dataType: KType,
|
||||
) : DataTree<T>, DataSetBuilder<T>, ActiveDataSet<T> {
|
||||
private val mutex = Mutex()
|
||||
private val treeItems = HashMap<NameToken, DataTreeItem<T>>()
|
||||
|
||||
override suspend fun items(): Map<NameToken, DataTreeItem<T>> = mutex.withLock {
|
||||
treeItems.filter { !it.key.body.startsWith("@") }
|
||||
}
|
||||
|
||||
private val _updates = MutableSharedFlow<Name>()
|
||||
|
||||
override val updates: Flow<Name>
|
||||
get() = _updates
|
||||
|
||||
private suspend fun remove(token: NameToken) {
|
||||
mutex.withLock {
|
||||
if (treeItems.remove(token) != null) {
|
||||
_updates.emit(token.asName())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun remove(name: Name) {
|
||||
if (name.isEmpty()) error("Can't remove the root node")
|
||||
(getItem(name.cutLast()).tree as? ActiveDataTree)?.remove(name.lastOrNull()!!)
|
||||
}
|
||||
|
||||
private suspend fun set(token: NameToken, data: Data<T>) {
|
||||
mutex.withLock {
|
||||
treeItems[token] = DataTreeItem.Leaf(data)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getOrCreateNode(token: NameToken): ActiveDataTree<T> =
|
||||
(treeItems[token] as? DataTreeItem.Node<T>)?.tree as? ActiveDataTree<T>
|
||||
?: ActiveDataTree<T>(dataType).also {
|
||||
mutex.withLock {
|
||||
treeItems[token] = DataTreeItem.Node(it)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getOrCreateNode(name: Name): ActiveDataTree<T> {
|
||||
return when (name.length) {
|
||||
0 -> this
|
||||
1 -> getOrCreateNode(name.firstOrNull()!!)
|
||||
else -> getOrCreateNode(name.firstOrNull()!!).getOrCreateNode(name.cutFirst())
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun emit(name: Name, data: Data<T>?) {
|
||||
if (data == null) {
|
||||
remove(name)
|
||||
} else {
|
||||
when (name.length) {
|
||||
0 -> error("Can't add data with empty name")
|
||||
1 -> set(name.firstOrNull()!!, data)
|
||||
2 -> getOrCreateNode(name.cutLast()).set(name.lastOrNull()!!, data)
|
||||
}
|
||||
}
|
||||
_updates.emit(name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy given data set and mirror its changes to this [ActiveDataTree] in [this@setAndObserve]. Returns an update [Job]
|
||||
*/
|
||||
public fun CoroutineScope.setAndObserve(name: Name, dataSet: DataSet<T>): Job = launch {
|
||||
emit(name, dataSet)
|
||||
dataSet.updates.collect { nameInBranch ->
|
||||
emit(name + nameInBranch, dataSet.getData(nameInBranch))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a dynamic tree. Initial data is placed synchronously. Updates are propagated via [updatesScope]
|
||||
*/
|
||||
@Suppress("FunctionName")
|
||||
public suspend fun <T : Any> ActiveDataTree(
|
||||
type: KType,
|
||||
block: suspend ActiveDataTree<T>.() -> Unit,
|
||||
): ActiveDataTree<T> {
|
||||
val tree = ActiveDataTree<T>(type)
|
||||
tree.block()
|
||||
return tree
|
||||
}
|
||||
|
||||
@Suppress("FunctionName")
|
||||
public suspend inline fun <reified T : Any> ActiveDataTree(
|
||||
crossinline block: suspend ActiveDataTree<T>.() -> Unit,
|
||||
): ActiveDataTree<T> = ActiveDataTree<T>(typeOf<T>()).apply { block() }
|
||||
|
||||
|
||||
public suspend inline fun <reified T : Any> ActiveDataTree<T>.emit(
|
||||
name: Name,
|
||||
noinline block: suspend ActiveDataTree<T>.() -> Unit,
|
||||
): Unit = emit(name, ActiveDataTree(typeOf<T>(), block))
|
||||
|
||||
public suspend inline fun <reified T : Any> ActiveDataTree<T>.emit(
|
||||
name: String,
|
||||
noinline block: suspend ActiveDataTree<T>.() -> Unit,
|
||||
): Unit = emit(name.toName(), ActiveDataTree(typeOf<T>(), block))
|
@ -0,0 +1,52 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.actions.Action
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.startsWith
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlin.reflect.KType
|
||||
|
||||
/**
|
||||
* Remove all values with keys starting with [name]
|
||||
*/
|
||||
internal fun MutableMap<Name, *>.removeWhatStartsWith(name: Name) {
|
||||
val toRemove = keys.filter { it.startsWith(name) }
|
||||
toRemove.forEach(::remove)
|
||||
}
|
||||
|
||||
/**
|
||||
* An action that caches results on-demand and recalculates them on source push
|
||||
*/
|
||||
public abstract class CachingAction<in T : Any, out R : Any>(
|
||||
public val outputType: KType,
|
||||
) : Action<T, R> {
|
||||
|
||||
protected abstract fun CoroutineScope.transform(
|
||||
set: DataSet<T>,
|
||||
meta: Meta,
|
||||
key: Name = Name.EMPTY,
|
||||
): Flow<NamedData<R>>
|
||||
|
||||
override suspend fun execute(
|
||||
dataSet: DataSet<T>,
|
||||
meta: Meta,
|
||||
scope: CoroutineScope?,
|
||||
): DataSet<R> = ActiveDataTree<R>(outputType) {
|
||||
coroutineScope {
|
||||
populate(transform(dataSet, meta))
|
||||
}
|
||||
scope?.let {
|
||||
dataSet.updates.collect {
|
||||
//clear old nodes
|
||||
remove(it)
|
||||
//collect new items
|
||||
populate(scope.transform(dataSet, meta, it))
|
||||
//FIXME if the target is data, updates are fired twice
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
@ -3,19 +3,23 @@ package hep.dataforge.data
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaRepr
|
||||
import hep.dataforge.meta.isEmpty
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import hep.dataforge.misc.DFInternal
|
||||
import hep.dataforge.misc.Type
|
||||
import kotlinx.coroutines.*
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
/**
|
||||
* A data element characterized by its meta
|
||||
*/
|
||||
@Type(Data.TYPE)
|
||||
public interface Data<out T : Any> : Goal<T>, MetaRepr {
|
||||
/**
|
||||
* Type marker for the data. The type is known before the calculation takes place so it could be checked.
|
||||
*/
|
||||
public val type: KClass<out T>
|
||||
public val type: KType
|
||||
|
||||
/**
|
||||
* Meta for the data
|
||||
@ -23,7 +27,7 @@ public interface Data<out T : Any> : Goal<T>, MetaRepr{
|
||||
public val meta: Meta
|
||||
|
||||
override fun toMeta(): Meta = Meta {
|
||||
"type" put (type.simpleName?:"undefined")
|
||||
"type" put (type.toString())
|
||||
if (!meta.isEmpty()) {
|
||||
"meta" put meta
|
||||
}
|
||||
@ -32,131 +36,67 @@ public interface Data<out T : Any> : Goal<T>, MetaRepr{
|
||||
public companion object {
|
||||
public const val TYPE: String = "data"
|
||||
|
||||
public operator fun <T : Any> invoke(
|
||||
type: KClass<out T>,
|
||||
meta: Meta = Meta.EMPTY,
|
||||
context: CoroutineContext = EmptyCoroutineContext,
|
||||
dependencies: Collection<Data<*>> = emptyList(),
|
||||
block: suspend CoroutineScope.() -> T
|
||||
): Data<T> = DynamicData(type, meta, context, dependencies, block)
|
||||
/**
|
||||
* The type that can't have any subtypes
|
||||
*/
|
||||
internal val TYPE_OF_NOTHING: KType = typeOf<Unit>()
|
||||
|
||||
public inline operator fun <reified T : Any> invoke(
|
||||
public inline fun <reified T : Any> static(
|
||||
value: T,
|
||||
meta: Meta = Meta.EMPTY,
|
||||
context: CoroutineContext = EmptyCoroutineContext,
|
||||
dependencies: Collection<Data<*>> = emptyList(),
|
||||
noinline block: suspend CoroutineScope.() -> T
|
||||
): Data<T> = invoke(T::class, meta, context, dependencies, block)
|
||||
): Data<T> = StaticData(typeOf<T>(), value, meta)
|
||||
|
||||
public operator fun <T : Any> invoke(
|
||||
name: String,
|
||||
type: KClass<out T>,
|
||||
meta: Meta = Meta.EMPTY,
|
||||
context: CoroutineContext = EmptyCoroutineContext,
|
||||
dependencies: Collection<Data<*>> = emptyList(),
|
||||
block: suspend CoroutineScope.() -> T
|
||||
): Data<T> = NamedData(name, invoke(type, meta, context, dependencies, block))
|
||||
/**
|
||||
* An empty data containing only meta
|
||||
*/
|
||||
public fun empty(meta: Meta): Data<Nothing> = object : Data<Nothing> {
|
||||
override val type: KType = TYPE_OF_NOTHING
|
||||
override val meta: Meta = meta
|
||||
override val dependencies: Collection<Goal<*>> = emptyList()
|
||||
override val deferred: Deferred<Nothing>
|
||||
get() = GlobalScope.async(start = CoroutineStart.LAZY) {
|
||||
error("The Data is empty and could not be computed")
|
||||
}
|
||||
|
||||
public inline operator fun <reified T : Any> invoke(
|
||||
name: String,
|
||||
meta: Meta = Meta.EMPTY,
|
||||
context: CoroutineContext = EmptyCoroutineContext,
|
||||
dependencies: Collection<Data<*>> = emptyList(),
|
||||
noinline block: suspend CoroutineScope.() -> T
|
||||
): Data<T> =
|
||||
invoke(name, T::class, meta, context, dependencies, block)
|
||||
|
||||
public fun <T : Any> static(value: T, meta: Meta = Meta.EMPTY): Data<T> =
|
||||
StaticData(value, meta)
|
||||
override fun async(coroutineScope: CoroutineScope): Deferred<Nothing> = deferred
|
||||
override fun reset() {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class DynamicData<T : Any>(
|
||||
override val type: KClass<out T>,
|
||||
/**
|
||||
* A lazily computed variant of [Data] based on [LazyGoal]
|
||||
* One must ensure that proper [type] is used so this method should not be used
|
||||
*/
|
||||
private class LazyData<T : Any>(
|
||||
override val type: KType,
|
||||
override val meta: Meta = Meta.EMPTY,
|
||||
context: CoroutineContext = EmptyCoroutineContext,
|
||||
additionalContext: CoroutineContext = EmptyCoroutineContext,
|
||||
dependencies: Collection<Data<*>> = emptyList(),
|
||||
block: suspend CoroutineScope.() -> T
|
||||
) : Data<T>, DynamicGoal<T>(context, dependencies, block)
|
||||
block: suspend () -> T,
|
||||
) : Data<T>, LazyGoal<T>(additionalContext, dependencies, block)
|
||||
|
||||
public class StaticData<T : Any>(
|
||||
override val type: KType,
|
||||
value: T,
|
||||
override val meta: Meta = Meta.EMPTY
|
||||
) : Data<T>, StaticGoal<T>(value) {
|
||||
override val type: KClass<out T> get() = value::class
|
||||
}
|
||||
|
||||
public class NamedData<out T : Any>(public val name: String, data: Data<T>) : Data<T> by data
|
||||
|
||||
public fun <T : Any, R : Any> Data<T>.map(
|
||||
outputType: KClass<out R>,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
meta: Meta = this.meta,
|
||||
block: suspend CoroutineScope.(T) -> R
|
||||
): Data<R> = DynamicData(outputType, meta, coroutineContext, listOf(this)) {
|
||||
block(await())
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a data pipe
|
||||
*/
|
||||
public inline fun <T : Any, reified R : Any> Data<T>.map(
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
meta: Meta = this.meta,
|
||||
noinline block: suspend CoroutineScope.(T) -> R
|
||||
): Data<R> = DynamicData(R::class, meta, coroutineContext, listOf(this)) {
|
||||
block(await())
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a joined data.
|
||||
*/
|
||||
public inline fun <T : Any, reified R : Any> Collection<Data<T>>.reduce(
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
meta: Meta,
|
||||
noinline block: suspend CoroutineScope.(Collection<T>) -> R
|
||||
): Data<R> = DynamicData(
|
||||
R::class,
|
||||
meta,
|
||||
coroutineContext,
|
||||
this
|
||||
) {
|
||||
block(map { run { it.await() } })
|
||||
}
|
||||
|
||||
public fun <K, T : Any, R : Any> Map<K, Data<T>>.reduce(
|
||||
outputType: KClass<out R>,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
meta: Meta,
|
||||
block: suspend CoroutineScope.(Map<K, T>) -> R
|
||||
): DynamicData<R> = DynamicData(
|
||||
outputType,
|
||||
meta,
|
||||
coroutineContext,
|
||||
this.values
|
||||
) {
|
||||
block(mapValues { it.value.await() })
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A joining of multiple data into a single one
|
||||
* @param K type of the map key
|
||||
* @param T type of the input goal
|
||||
* @param R type of the result goal
|
||||
*/
|
||||
public inline fun <K, T : Any, reified R : Any> Map<K, Data<T>>.reduce(
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
meta: Meta,
|
||||
noinline block: suspend CoroutineScope.(Map<K, T>) -> R
|
||||
): DynamicData<R> = DynamicData(
|
||||
R::class,
|
||||
meta,
|
||||
coroutineContext,
|
||||
this.values
|
||||
) {
|
||||
block(mapValues { it.value.await() })
|
||||
}
|
||||
override val meta: Meta = Meta.EMPTY,
|
||||
) : Data<T>, StaticGoal<T>(value)
|
||||
|
||||
@Suppress("FunctionName")
|
||||
@DFInternal
|
||||
public fun <T : Any> Data(
|
||||
type: KType,
|
||||
meta: Meta = Meta.EMPTY,
|
||||
context: CoroutineContext = EmptyCoroutineContext,
|
||||
dependencies: Collection<Data<*>> = emptyList(),
|
||||
block: suspend () -> T,
|
||||
): Data<T> = LazyData(type, meta, context, dependencies, block)
|
||||
|
||||
@OptIn(DFInternal::class)
|
||||
@Suppress("FunctionName")
|
||||
public inline fun <reified T : Any> Data(
|
||||
meta: Meta = Meta.EMPTY,
|
||||
context: CoroutineContext = EmptyCoroutineContext,
|
||||
dependencies: Collection<Data<*>> = emptyList(),
|
||||
noinline block: suspend () -> T,
|
||||
): Data<T> = Data(typeOf<T>(), meta, context, dependencies, block)
|
||||
|
@ -1,53 +0,0 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.toName
|
||||
|
||||
|
||||
public class DataFilter : Scheme() {
|
||||
/**
|
||||
* A source node for the filter
|
||||
*/
|
||||
public var from: String? by string()
|
||||
/**
|
||||
* A target placement for the filtered node
|
||||
*/
|
||||
public var to: String? by string()
|
||||
/**
|
||||
* A regular expression pattern for the filter
|
||||
*/
|
||||
public var pattern: String by string(".*")
|
||||
// val prefix by string()
|
||||
// val suffix by string()
|
||||
|
||||
public companion object : SchemeSpec<DataFilter>(::DataFilter)
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply meta-based filter to given data node
|
||||
*/
|
||||
public fun <T : Any> DataNode<T>.filter(filter: DataFilter): DataNode<T> {
|
||||
val sourceNode = filter.from?.let { get(it.toName()).node } ?: this@filter
|
||||
val regex = filter.pattern.toRegex()
|
||||
val targetNode = DataTreeBuilder(type).apply {
|
||||
sourceNode.dataSequence().forEach { (name, data) ->
|
||||
if (name.toString().matches(regex)) {
|
||||
this[name] = data
|
||||
}
|
||||
}
|
||||
}
|
||||
return filter.to?.let {
|
||||
DataTreeBuilder(type).apply { this[it.toName()] = targetNode }.build()
|
||||
} ?: targetNode.build()
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter data using [DataFilter] specification
|
||||
*/
|
||||
public fun <T : Any> DataNode<T>.filter(filter: Meta): DataNode<T> = filter(DataFilter.read(filter))
|
||||
|
||||
/**
|
||||
* Filter data using [DataFilter] builder
|
||||
*/
|
||||
public fun <T : Any> DataNode<T>.filter(filterBuilder: DataFilter.() -> Unit): DataNode<T> =
|
||||
filter(DataFilter(filterBuilder))
|
@ -1,296 +0,0 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
import kotlin.collections.set
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
public sealed class DataItem<out T : Any> : MetaRepr {
|
||||
public abstract val type: KClass<out T>
|
||||
|
||||
public abstract val meta: Meta
|
||||
|
||||
public class Node<out T : Any>(public val node: DataNode<T>) : DataItem<T>() {
|
||||
override val type: KClass<out T> get() = node.type
|
||||
|
||||
override fun toMeta(): Meta = node.toMeta()
|
||||
|
||||
override val meta: Meta get() = node.meta
|
||||
}
|
||||
|
||||
public class Leaf<out T : Any>(public val data: Data<T>) : DataItem<T>() {
|
||||
override val type: KClass<out T> get() = data.type
|
||||
|
||||
override fun toMeta(): Meta = data.toMeta()
|
||||
|
||||
override val meta: Meta get() = data.meta
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A tree-like data structure grouped into the node. All data inside the node must inherit its type
|
||||
*/
|
||||
public interface DataNode<out T : Any> : MetaRepr {
|
||||
|
||||
/**
|
||||
* The minimal common ancestor to all data in the node
|
||||
*/
|
||||
public val type: KClass<out T>
|
||||
|
||||
public val items: Map<NameToken, DataItem<T>>
|
||||
|
||||
public val meta: Meta
|
||||
|
||||
override fun toMeta(): Meta = Meta {
|
||||
"type" put (type.simpleName ?: "undefined")
|
||||
"items" put {
|
||||
this@DataNode.items.forEach {
|
||||
it.key.toString() put it.value.toMeta()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Start computation for all goals in data node and return a job for the whole node
|
||||
*/
|
||||
@Suppress("DeferredResultUnused")
|
||||
public fun CoroutineScope.startAll(): Job = launch {
|
||||
items.values.forEach {
|
||||
when (it) {
|
||||
is DataItem.Node<*> -> it.node.run { startAll() }
|
||||
is DataItem.Leaf<*> -> it.data.run { startAsync() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val TYPE: String = "dataNode"
|
||||
|
||||
public operator fun <T : Any> invoke(type: KClass<out T>, block: DataTreeBuilder<T>.() -> Unit): DataTree<T> =
|
||||
DataTreeBuilder(type).apply(block).build()
|
||||
|
||||
public inline operator fun <reified T : Any> invoke(noinline block: DataTreeBuilder<T>.() -> Unit): DataTree<T> =
|
||||
DataTreeBuilder(T::class).apply(block).build()
|
||||
|
||||
public fun <T : Any> builder(type: KClass<out T>): DataTreeBuilder<T> = DataTreeBuilder(type)
|
||||
}
|
||||
}
|
||||
|
||||
public suspend fun <T: Any> DataNode<T>.join(): Unit = coroutineScope { startAll().join() }
|
||||
|
||||
public val <T : Any> DataItem<T>?.node: DataNode<T>? get() = (this as? DataItem.Node<T>)?.node
|
||||
public val <T : Any> DataItem<T>?.data: Data<T>? get() = (this as? DataItem.Leaf<T>)?.data
|
||||
|
||||
public operator fun <T : Any> DataNode<T>.get(name: Name): DataItem<T>? = when (name.length) {
|
||||
0 -> error("Empty name")
|
||||
1 -> items[name.firstOrNull()]
|
||||
else -> get(name.firstOrNull()!!.asName()).node?.get(name.cutFirst())
|
||||
}
|
||||
|
||||
public operator fun <T : Any> DataNode<T>.get(name: String): DataItem<T>? = get(name.toName())
|
||||
|
||||
/**
|
||||
* Sequence of all children including nodes
|
||||
*/
|
||||
public fun <T : Any> DataNode<T>.asSequence(): Sequence<Pair<Name, DataItem<T>>> = sequence {
|
||||
items.forEach { (head, item) ->
|
||||
yield(head.asName() to item)
|
||||
if (item is DataItem.Node) {
|
||||
val subSequence = item.node.asSequence()
|
||||
.map { (name, data) -> (head.asName() + name) to data }
|
||||
yieldAll(subSequence)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sequence of data entries
|
||||
*/
|
||||
public fun <T : Any> DataNode<T>.dataSequence(): Sequence<Pair<Name, Data<T>>> = sequence {
|
||||
items.forEach { (head, item) ->
|
||||
when (item) {
|
||||
is DataItem.Leaf -> yield(head.asName() to item.data)
|
||||
is DataItem.Node -> {
|
||||
val subSequence = item.node.dataSequence()
|
||||
.map { (name, data) -> (head.asName() + name) to data }
|
||||
yieldAll(subSequence)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public operator fun <T : Any> DataNode<T>.iterator(): Iterator<Pair<Name, DataItem<T>>> = asSequence().iterator()
|
||||
|
||||
public class DataTree<out T : Any> internal constructor(
|
||||
override val type: KClass<out T>,
|
||||
override val items: Map<NameToken, DataItem<T>>,
|
||||
override val meta: Meta
|
||||
) : DataNode<T>
|
||||
|
||||
private sealed class DataTreeBuilderItem<out T : Any> {
|
||||
class Node<T : Any>(val tree: DataTreeBuilder<T>) : DataTreeBuilderItem<T>()
|
||||
class Leaf<T : Any>(val value: Data<T>) : DataTreeBuilderItem<T>()
|
||||
}
|
||||
|
||||
/**
|
||||
* A builder for a DataTree.
|
||||
*/
|
||||
@DFBuilder
|
||||
public class DataTreeBuilder<T : Any>(public val type: KClass<out T>) {
|
||||
private val map = HashMap<NameToken, DataTreeBuilderItem<T>>()
|
||||
|
||||
private var meta = MetaBuilder()
|
||||
|
||||
public operator fun set(token: NameToken, node: DataTreeBuilder<out T>) {
|
||||
if (map.containsKey(token)) error("Tree entry with name $token is not empty")
|
||||
map[token] = DataTreeBuilderItem.Node(node)
|
||||
}
|
||||
|
||||
public operator fun set(token: NameToken, data: Data<T>) {
|
||||
if (map.containsKey(token)) error("Tree entry with name $token is not empty")
|
||||
map[token] = DataTreeBuilderItem.Leaf(data)
|
||||
}
|
||||
|
||||
private fun buildNode(token: NameToken): DataTreeBuilder<T> {
|
||||
return if (!map.containsKey(token)) {
|
||||
DataTreeBuilder(type).also { map[token] = DataTreeBuilderItem.Node(it) }
|
||||
} else {
|
||||
(map[token] as? DataTreeBuilderItem.Node<T> ?: error("The node with name $token is occupied by leaf")).tree
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildNode(name: Name): DataTreeBuilder<T> {
|
||||
return when (name.length) {
|
||||
0 -> this
|
||||
1 -> buildNode(name.firstOrNull()!!)
|
||||
else -> buildNode(name.firstOrNull()!!).buildNode(name.cutFirst())
|
||||
}
|
||||
}
|
||||
|
||||
public operator fun set(name: Name, data: Data<T>) {
|
||||
when (name.length) {
|
||||
0 -> error("Can't add data with empty name")
|
||||
1 -> set(name.firstOrNull()!!, data)
|
||||
2 -> buildNode(name.cutLast())[name.lastOrNull()!!] = data
|
||||
}
|
||||
}
|
||||
|
||||
public operator fun set(name: Name, node: DataTreeBuilder<out T>) {
|
||||
when (name.length) {
|
||||
0 -> error("Can't add data with empty name")
|
||||
1 -> set(name.firstOrNull()!!, node)
|
||||
2 -> buildNode(name.cutLast())[name.lastOrNull()!!] = node
|
||||
}
|
||||
}
|
||||
|
||||
public operator fun set(name: Name, node: DataNode<T>): Unit = set(name, node.builder())
|
||||
|
||||
public operator fun set(name: Name, item: DataItem<T>): Unit = when (item) {
|
||||
is DataItem.Node<T> -> set(name, item.node.builder())
|
||||
is DataItem.Leaf<T> -> set(name, item.data)
|
||||
}
|
||||
|
||||
/**
|
||||
* Append data to node
|
||||
*/
|
||||
public infix fun String.put(data: Data<T>): Unit = set(toName(), data)
|
||||
|
||||
/**
|
||||
* Append node
|
||||
*/
|
||||
public infix fun String.put(node: DataNode<T>): Unit = set(toName(), node)
|
||||
|
||||
public infix fun String.put(item: DataItem<T>): Unit = set(toName(), item)
|
||||
|
||||
/**
|
||||
* Build and append node
|
||||
*/
|
||||
public infix fun String.put(block: DataTreeBuilder<T>.() -> Unit): Unit = set(toName(), DataTreeBuilder(type).apply(block))
|
||||
|
||||
|
||||
/**
|
||||
* Update data with given node data and meta with node meta.
|
||||
*/
|
||||
public fun update(node: DataNode<T>) {
|
||||
node.dataSequence().forEach {
|
||||
//TODO check if the place is occupied
|
||||
this[it.first] = it.second
|
||||
}
|
||||
meta.update(node.meta)
|
||||
}
|
||||
|
||||
public fun meta(block: MetaBuilder.() -> Unit): MetaBuilder = meta.apply(block)
|
||||
|
||||
public fun meta(meta: Meta) {
|
||||
this.meta = meta.builder()
|
||||
}
|
||||
|
||||
public fun build(): DataTree<T> {
|
||||
val resMap = map.mapValues { (_, value) ->
|
||||
when (value) {
|
||||
is DataTreeBuilderItem.Leaf -> DataItem.Leaf(value.value)
|
||||
is DataTreeBuilderItem.Node -> DataItem.Node(value.tree.build())
|
||||
}
|
||||
}
|
||||
return DataTree(type, resMap, meta.seal())
|
||||
}
|
||||
}
|
||||
|
||||
public fun <T : Any> DataTreeBuilder<T>.datum(name: Name, data: Data<T>) {
|
||||
this[name] = data
|
||||
}
|
||||
|
||||
public fun <T : Any> DataTreeBuilder<T>.datum(name: String, data: Data<T>) {
|
||||
this[name.toName()] = data
|
||||
}
|
||||
|
||||
public fun <T : Any> DataTreeBuilder<T>.static(name: Name, data: T, meta: Meta = Meta.EMPTY) {
|
||||
this[name] = Data.static(data, meta)
|
||||
}
|
||||
|
||||
public fun <T : Any> DataTreeBuilder<T>.static(name: Name, data: T, block: MetaBuilder.() -> Unit = {}) {
|
||||
this[name] = Data.static(data, Meta(block))
|
||||
}
|
||||
|
||||
public fun <T : Any> DataTreeBuilder<T>.static(name: String, data: T, block: MetaBuilder.() -> Unit = {}) {
|
||||
this[name.toName()] = Data.static(data, Meta(block))
|
||||
}
|
||||
|
||||
public fun <T : Any> DataTreeBuilder<T>.node(name: Name, node: DataNode<T>) {
|
||||
this[name] = node
|
||||
}
|
||||
|
||||
public fun <T : Any> DataTreeBuilder<T>.node(name: String, node: DataNode<T>) {
|
||||
this[name.toName()] = node
|
||||
}
|
||||
|
||||
public inline fun <reified T : Any> DataTreeBuilder<T>.node(name: Name, noinline block: DataTreeBuilder<T>.() -> Unit) {
|
||||
this[name] = DataNode(T::class, block)
|
||||
}
|
||||
|
||||
public inline fun <reified T : Any> DataTreeBuilder<T>.node(name: String, noinline block: DataTreeBuilder<T>.() -> Unit) {
|
||||
this[name.toName()] = DataNode(T::class, block)
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a mutable builder from this node. Node content is not changed
|
||||
*/
|
||||
public fun <T : Any> DataNode<T>.builder(): DataTreeBuilder<T> = DataTreeBuilder(type).apply {
|
||||
dataSequence().forEach { (name, data) -> this[name] = data }
|
||||
}
|
||||
|
||||
public fun <T : Any> DataNode<T>.filter(predicate: (Name, Data<T>) -> Boolean): DataNode<T> = DataNode.invoke(type) {
|
||||
dataSequence().forEach { (name, data) ->
|
||||
if (predicate(name, data)) {
|
||||
this[name] = data
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun <T : Any> DataNode<T>.first(): Data<T>? = dataSequence().first().second
|
@ -0,0 +1,99 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.data.Data.Companion.TYPE_OF_NOTHING
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.set
|
||||
import hep.dataforge.names.*
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlin.reflect.KType
|
||||
|
||||
public interface DataSet<out T : Any> {
|
||||
|
||||
/**
|
||||
* The minimal common ancestor to all data in the node
|
||||
*/
|
||||
public val dataType: KType
|
||||
|
||||
/**
|
||||
* Traverse this provider or its child. The order is not guaranteed.
|
||||
* [root] points to a root name for traversal. If it is empty, traverse this source, if it points to a [Data],
|
||||
* return flow, that contains single [Data], if it points to a node with children, return children.
|
||||
*/
|
||||
public fun flow(): Flow<NamedData<T>>
|
||||
|
||||
/**
|
||||
* Get data with given name.
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* By default traverses the whole tree. Could be optimized in descendants
|
||||
*/
|
||||
public suspend fun listChildren(prefix: Name = Name.EMPTY): List<Name> =
|
||||
flow().map { it.name }.filter { it.startsWith(prefix) && (it.length == prefix.length + 1) }.toList()
|
||||
|
||||
public companion object {
|
||||
public val META_KEY: Name = "@meta".asName()
|
||||
|
||||
/**
|
||||
* An empty [DataSet] that suits all types
|
||||
*/
|
||||
public val EMPTY: DataSet<Nothing> = object : DataSet<Nothing> {
|
||||
override val dataType: KType = TYPE_OF_NOTHING
|
||||
|
||||
private val nothing: Nothing get() = error("this is nothing")
|
||||
|
||||
override fun flow(): Flow<NamedData<Nothing>> = emptyFlow()
|
||||
|
||||
override suspend fun getData(name: Name): Data<Nothing>? = null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public interface ActiveDataSet<T : Any> : DataSet<T> {
|
||||
/**
|
||||
* A flow of updated item names. Updates are propagated in a form of [Flow] of names of updated nodes.
|
||||
* Those can include new data items and replacement of existing ones. The replaced items could update existing data content
|
||||
* and replace it completely, so they should be pulled again.
|
||||
*
|
||||
*/
|
||||
public val updates: Flow<Name>
|
||||
}
|
||||
|
||||
public val <T : Any> DataSet<T>.updates: Flow<Name> get() = if (this is ActiveDataSet) updates else emptyFlow()
|
||||
|
||||
/**
|
||||
* Flow all data nodes with names starting with [branchName]
|
||||
*/
|
||||
public fun <T : Any> DataSet<T>.flowChildren(branchName: Name): Flow<NamedData<T>> = this@flowChildren.flow().filter {
|
||||
it.name.startsWith(branchName)
|
||||
}
|
||||
|
||||
/**
|
||||
* Start computation for all goals in data node and return a job for the whole node
|
||||
*/
|
||||
public fun <T : Any> DataSet<T>.startAll(coroutineScope: CoroutineScope): Job = coroutineScope.launch {
|
||||
flow().map {
|
||||
it.launch(this@launch)
|
||||
}.toList().joinAll()
|
||||
}
|
||||
|
||||
public suspend fun <T : Any> DataSet<T>.join(): Unit = coroutineScope { startAll(this).join() }
|
||||
|
||||
public suspend fun DataSet<*>.toMeta(): Meta = Meta {
|
||||
flow().collect {
|
||||
if (it.name.endsWith(DataSet.META_KEY)) {
|
||||
set(it.name, it.meta)
|
||||
} else {
|
||||
it.name put {
|
||||
"type" put it.type.toString()
|
||||
"meta" put it.meta
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public val <T : Any> DataSet<T>.updatesWithData: Flow<NamedData<T>> get() = updates.mapNotNull { getData(it)?.named(it) }
|
@ -0,0 +1,145 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.plus
|
||||
import hep.dataforge.names.toName
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlin.reflect.KType
|
||||
|
||||
public interface DataSetBuilder<in T : Any> {
|
||||
public val dataType: KType
|
||||
|
||||
/**
|
||||
* Remove all data items starting with [name]
|
||||
*/
|
||||
public suspend fun remove(name: Name)
|
||||
|
||||
public suspend fun emit(name: Name, data: Data<T>?)
|
||||
|
||||
/**
|
||||
* Set a current state of given [dataSet] into a branch [name]. Does not propagate updates
|
||||
*/
|
||||
public suspend fun emit(name: Name, dataSet: DataSet<T>) {
|
||||
//remove previous items
|
||||
if (name != Name.EMPTY) {
|
||||
remove(name)
|
||||
}
|
||||
|
||||
//Set new items
|
||||
dataSet.flow().collect {
|
||||
emit(name + it.name, it.data)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append data to node
|
||||
*/
|
||||
public suspend infix fun String.put(data: Data<T>): Unit = emit(toName(), data)
|
||||
|
||||
/**
|
||||
* Append node
|
||||
*/
|
||||
public suspend infix fun String.put(dataSet: DataSet<T>): Unit = emit(toName(), dataSet)
|
||||
|
||||
/**
|
||||
* Build and append node
|
||||
*/
|
||||
public suspend infix fun String.put(block: suspend DataSetBuilder<T>.() -> Unit): Unit = emit(toName(), block)
|
||||
}
|
||||
|
||||
private class SubSetBuilder<in T : Any>(
|
||||
private val parent: DataSetBuilder<T>,
|
||||
private val branch: Name,
|
||||
) : DataSetBuilder<T> {
|
||||
override val dataType: KType get() = parent.dataType
|
||||
|
||||
override suspend fun remove(name: Name) {
|
||||
parent.remove(branch + name)
|
||||
}
|
||||
|
||||
override suspend fun emit(name: Name, data: Data<T>?) {
|
||||
parent.emit(branch + name, data)
|
||||
}
|
||||
|
||||
override suspend fun emit(name: Name, dataSet: DataSet<T>) {
|
||||
parent.emit(branch + name, dataSet)
|
||||
}
|
||||
}
|
||||
|
||||
public suspend fun <T : Any> DataSetBuilder<T>.emit(name: Name, block: suspend DataSetBuilder<T>.() -> Unit) {
|
||||
SubSetBuilder(this, name).apply { block() }
|
||||
}
|
||||
|
||||
|
||||
public suspend fun <T : Any> DataSetBuilder<T>.emit(name: String, data: Data<T>) {
|
||||
emit(name.toName(), data)
|
||||
}
|
||||
|
||||
public suspend fun <T : Any> DataSetBuilder<T>.emit(name: String, set: DataSet<T>) {
|
||||
this.emit(name.toName(), set)
|
||||
}
|
||||
|
||||
public suspend fun <T : Any> DataSetBuilder<T>.emit(name: String, block: suspend DataSetBuilder<T>.() -> Unit): Unit =
|
||||
this@emit.emit(name.toName(), block)
|
||||
|
||||
public suspend fun <T : Any> DataSetBuilder<T>.emit(data: NamedData<T>) {
|
||||
emit(data.name, data.data)
|
||||
}
|
||||
|
||||
/**
|
||||
* Produce lazy [Data] and emit it into the [DataSetBuilder]
|
||||
*/
|
||||
public suspend inline fun <reified T : Any> DataSetBuilder<T>.produce(
|
||||
name: String,
|
||||
meta: Meta = Meta.EMPTY,
|
||||
noinline producer: suspend () -> T,
|
||||
) {
|
||||
val data = Data(meta, block = producer)
|
||||
emit(name, data)
|
||||
}
|
||||
|
||||
public suspend inline fun <reified T : Any> DataSetBuilder<T>.produce(
|
||||
name: Name,
|
||||
meta: Meta = Meta.EMPTY,
|
||||
noinline producer: suspend () -> T,
|
||||
) {
|
||||
val data = Data(meta, block = producer)
|
||||
emit(name, data)
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a static data with the fixed value
|
||||
*/
|
||||
public suspend inline fun <reified T : Any> DataSetBuilder<T>.static(name: String, data: T, meta: Meta = Meta.EMPTY): Unit =
|
||||
emit(name, Data.static(data, meta))
|
||||
|
||||
public suspend inline fun <reified T : Any> DataSetBuilder<T>.static(name: Name, data: T, meta: Meta = Meta.EMPTY): Unit =
|
||||
emit(name, Data.static(data, meta))
|
||||
|
||||
public suspend inline fun <reified T : Any> DataSetBuilder<T>.static(
|
||||
name: String,
|
||||
data: T,
|
||||
metaBuilder: MetaBuilder.() -> Unit,
|
||||
): Unit = emit(name.toName(), Data.static(data, Meta(metaBuilder)))
|
||||
|
||||
/**
|
||||
* Update data with given node data and meta with node meta.
|
||||
*/
|
||||
@DFExperimental
|
||||
public suspend fun <T : Any> DataSetBuilder<T>.populate(tree: DataSet<T>): Unit = coroutineScope {
|
||||
tree.flow().collect {
|
||||
//TODO check if the place is occupied
|
||||
emit(it.name, it.data)
|
||||
}
|
||||
}
|
||||
|
||||
public suspend fun <T : Any> DataSetBuilder<T>.populate(flow: Flow<NamedData<T>>) {
|
||||
flow.collect {
|
||||
emit(it.name, it.data)
|
||||
}
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.misc.Type
|
||||
import hep.dataforge.names.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.emitAll
|
||||
import kotlinx.coroutines.flow.flow
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
import kotlin.reflect.KType
|
||||
|
||||
public sealed class DataTreeItem<out T : Any> {
|
||||
public class Node<out T : Any>(public val tree: DataTree<T>) : DataTreeItem<T>()
|
||||
public class Leaf<out T : Any>(public val data: Data<T>) : DataTreeItem<T>()
|
||||
}
|
||||
|
||||
public val <T : Any> DataTreeItem<T>.type: KType
|
||||
get() = when (this) {
|
||||
is DataTreeItem.Node -> tree.dataType
|
||||
is DataTreeItem.Leaf -> data.type
|
||||
}
|
||||
|
||||
/**
|
||||
* A tree-like [DataSet] grouped into the node. All data inside the node must inherit its type
|
||||
*/
|
||||
@Type(DataTree.TYPE)
|
||||
public interface DataTree<out T : Any> : DataSet<T> {
|
||||
|
||||
/**
|
||||
* Children items of this [DataTree] provided asynchronously
|
||||
*/
|
||||
public suspend fun items(): Map<NameToken, DataTreeItem<T>>
|
||||
|
||||
override fun flow(): Flow<NamedData<T>> = flow {
|
||||
items().forEach { (token, childItem: DataTreeItem<T>) ->
|
||||
if(!token.body.startsWith("@")) {
|
||||
when (childItem) {
|
||||
is DataTreeItem.Leaf -> emit(childItem.data.named(token.asName()))
|
||||
is DataTreeItem.Node -> emitAll(childItem.tree.flow().map { it.named(token + it.name) })
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun listChildren(prefix: Name): List<Name> =
|
||||
getItem(prefix).tree?.items()?.keys?.map { prefix + it } ?: emptyList()
|
||||
|
||||
override suspend fun getData(name: Name): Data<T>? = when (name.length) {
|
||||
0 -> null
|
||||
1 -> items()[name.firstOrNull()!!].data
|
||||
else -> items()[name.firstOrNull()!!].tree?.getData(name.cutFirst())
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public const val TYPE: String = "dataTree"
|
||||
}
|
||||
}
|
||||
|
||||
public suspend fun <T: Any> DataSet<T>.getData(name: String): Data<T>? = getData(name.toName())
|
||||
|
||||
/**
|
||||
* Get a [DataTreeItem] with given [name] or null if the item does not exist
|
||||
*/
|
||||
public tailrec suspend fun <T : Any> DataTree<T>.getItem(name: Name): DataTreeItem<T>? = when (name.length) {
|
||||
0 -> DataTreeItem.Node(this)
|
||||
1 -> items()[name.firstOrNull()]
|
||||
else -> items()[name.firstOrNull()!!].tree?.getItem(name.cutFirst())
|
||||
}
|
||||
|
||||
public val <T : Any> DataTreeItem<T>?.tree: DataTree<T>? get() = (this as? DataTreeItem.Node<T>)?.tree
|
||||
public val <T : Any> DataTreeItem<T>?.data: Data<T>? get() = (this as? DataTreeItem.Leaf<T>)?.data
|
||||
|
||||
/**
|
||||
* Flow of all children including nodes
|
||||
*/
|
||||
public fun <T : Any> DataTree<T>.itemFlow(): Flow<Pair<Name, DataTreeItem<T>>> = flow {
|
||||
items().forEach { (head, item) ->
|
||||
emit(head.asName() to item)
|
||||
if (item is DataTreeItem.Node) {
|
||||
val subSequence = item.tree.itemFlow()
|
||||
.map { (name, data) -> (head.asName() + name) to data }
|
||||
emitAll(subSequence)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a branch of this [DataTree] with a given [branchName].
|
||||
* The difference from similar method for [DataSet] is that internal logic is more simple and the return value is a [DataTree]
|
||||
*/
|
||||
public fun <T : Any> DataTree<T>.branch(branchName: Name): DataTree<T> = object : DataTree<T> {
|
||||
override val dataType: KType get() = this@branch.dataType
|
||||
|
||||
override suspend fun items(): Map<NameToken, DataTreeItem<T>> = getItem(branchName).tree?.items() ?: emptyMap()
|
||||
}
|
@ -1,22 +1,28 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import kotlinx.coroutines.*
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
|
||||
/**
|
||||
* Lazy computation result with its dependencies to allowing to stat computing dependencies ahead of time
|
||||
*/
|
||||
public interface Goal<out T> {
|
||||
public val dependencies: Collection<Goal<*>>
|
||||
|
||||
/**
|
||||
* Returns current running coroutine if the goal is started
|
||||
* Returns current running coroutine if the goal is started. Null if the computation is not started.
|
||||
*/
|
||||
public val result: Deferred<T>?
|
||||
public val deferred: Deferred<T>?
|
||||
|
||||
/**
|
||||
* Get ongoing computation or start a new one.
|
||||
* Does not guarantee thread safety. In case of multi-thread access, could create orphan computations.
|
||||
*
|
||||
* If the computation is already running, the scope is not used.
|
||||
*/
|
||||
public fun CoroutineScope.startAsync(): Deferred<T>
|
||||
public fun async(coroutineScope: CoroutineScope): Deferred<T>
|
||||
|
||||
/**
|
||||
* Reset the computation
|
||||
@ -26,89 +32,81 @@ public interface Goal<out T> {
|
||||
public companion object
|
||||
}
|
||||
|
||||
public suspend fun <T> Goal<T>.await(): T = coroutineScope { startAsync().await() }
|
||||
public fun Goal<*>.launch(coroutineScope: CoroutineScope): Job = async(coroutineScope)
|
||||
|
||||
public val Goal<*>.isComplete: Boolean get() = result?.isCompleted ?: false
|
||||
public suspend fun <T> Goal<T>.await(): T = coroutineScope { async(this).await() }
|
||||
|
||||
public val Goal<*>.isComplete: Boolean get() = deferred?.isCompleted ?: false
|
||||
|
||||
public open class StaticGoal<T>(public val value: T) : Goal<T> {
|
||||
override val dependencies: Collection<Goal<*>> get() = emptyList()
|
||||
override val result: Deferred<T> = CompletableDeferred(value)
|
||||
override val deferred: Deferred<T> = CompletableDeferred(value)
|
||||
|
||||
override fun CoroutineScope.startAsync(): Deferred<T> = result
|
||||
override fun async(coroutineScope: CoroutineScope): Deferred<T> = deferred
|
||||
|
||||
override fun reset() {
|
||||
//doNothing
|
||||
}
|
||||
}
|
||||
|
||||
public open class DynamicGoal<T>(
|
||||
/**
|
||||
* @param coroutineContext additional context information
|
||||
*/
|
||||
public open class LazyGoal<T>(
|
||||
private val coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
override val dependencies: Collection<Goal<*>> = emptyList(),
|
||||
public val block: suspend CoroutineScope.() -> T
|
||||
public val block: suspend () -> T,
|
||||
) : Goal<T> {
|
||||
|
||||
final override var result: Deferred<T>? = null
|
||||
final override var deferred: Deferred<T>? = null
|
||||
private set
|
||||
|
||||
/**
|
||||
* Get ongoing computation or start a new one.
|
||||
* Does not guarantee thread safety. In case of multi-thread access, could create orphan computations.
|
||||
* If [GoalExecutionRestriction] is present in the [coroutineScope] context, the call could produce a error a warning
|
||||
* depending on the settings.
|
||||
*/
|
||||
@DFExperimental
|
||||
override fun CoroutineScope.startAsync(): Deferred<T> {
|
||||
val startedDependencies = this@DynamicGoal.dependencies.map { goal ->
|
||||
goal.run { startAsync() }
|
||||
override fun async(coroutineScope: CoroutineScope): Deferred<T> {
|
||||
val log = coroutineScope.coroutineContext[GoalLogger]
|
||||
// Check if context restricts goal computation
|
||||
coroutineScope.coroutineContext[GoalExecutionRestriction]?.let { restriction ->
|
||||
when (restriction.policy) {
|
||||
GoalExecutionRestrictionPolicy.WARNING -> log?.emit(GoalLogger.WARNING_TAG) { "Goal eager execution is prohibited by the coroutine scope policy" }
|
||||
GoalExecutionRestrictionPolicy.ERROR -> error("Goal eager execution is prohibited by the coroutine scope policy")
|
||||
else -> {
|
||||
/*do nothing*/
|
||||
}
|
||||
return result
|
||||
?: async(this@DynamicGoal.coroutineContext + CoroutineMonitor() + Dependencies(startedDependencies)) {
|
||||
}
|
||||
}
|
||||
|
||||
log?.emit { "Starting dependencies computation for ${this@LazyGoal}" }
|
||||
val startedDependencies = this.dependencies.map { goal ->
|
||||
goal.run { async(coroutineScope) }
|
||||
}
|
||||
return deferred ?: coroutineScope.async(
|
||||
coroutineContext
|
||||
+ CoroutineMonitor()
|
||||
+ Dependencies(startedDependencies)
|
||||
+ GoalExecutionRestriction(GoalExecutionRestrictionPolicy.NONE) // Remove restrictions on goal execution
|
||||
) {
|
||||
//cancel execution if error encountered in one of dependencies
|
||||
startedDependencies.forEach { deferred ->
|
||||
deferred.invokeOnCompletion { error ->
|
||||
if (error != null) cancel(CancellationException("Dependency $deferred failed with error: ${error.message}"))
|
||||
if (error != null) this.cancel(CancellationException("Dependency $deferred failed with error: ${error.message}"))
|
||||
}
|
||||
}
|
||||
coroutineContext[GoalLogger]?.emit { "Starting computation of ${this@LazyGoal}" }
|
||||
block()
|
||||
}.also { result = it }
|
||||
}.also { deferred = it }
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the computation
|
||||
*/
|
||||
override fun reset() {
|
||||
result?.cancel()
|
||||
result = null
|
||||
deferred?.cancel()
|
||||
deferred = null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a one-to-one goal based on existing goal
|
||||
*/
|
||||
public fun <T, R> Goal<T>.map(
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
block: suspend CoroutineScope.(T) -> R
|
||||
): Goal<R> = DynamicGoal(coroutineContext, listOf(this)) {
|
||||
block(await())
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a joining goal.
|
||||
*/
|
||||
public fun <T, R> Collection<Goal<T>>.reduce(
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
block: suspend CoroutineScope.(Collection<T>) -> R
|
||||
): Goal<R> = DynamicGoal(coroutineContext, this) {
|
||||
block(map { run { it.await() } })
|
||||
}
|
||||
|
||||
/**
|
||||
* A joining goal for a map
|
||||
* @param K type of the map key
|
||||
* @param T type of the input goal
|
||||
* @param R type of the result goal
|
||||
*/
|
||||
public fun <K, T, R> Map<K, Goal<T>>.reduce(
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
block: suspend CoroutineScope.(Map<K, T>) -> R
|
||||
): Goal<R> = DynamicGoal(coroutineContext, this.values) {
|
||||
block(mapValues { it.value.await() })
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,17 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
public enum class GoalExecutionRestrictionPolicy {
|
||||
NONE,
|
||||
WARNING,
|
||||
ERROR
|
||||
}
|
||||
|
||||
public class GoalExecutionRestriction(
|
||||
public val policy: GoalExecutionRestrictionPolicy = GoalExecutionRestrictionPolicy.ERROR,
|
||||
) : CoroutineContext.Element {
|
||||
override val key: CoroutineContext.Key<*> get() = Companion
|
||||
|
||||
public companion object : CoroutineContext.Key<GoalExecutionRestriction>
|
||||
}
|
@ -0,0 +1,13 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
public interface GoalLogger : CoroutineContext.Element {
|
||||
override val key: CoroutineContext.Key<*> get() = GoalLogger
|
||||
|
||||
public fun emit(vararg tags: String, message: suspend () -> String)
|
||||
|
||||
public companion object : CoroutineContext.Key<GoalLogger>{
|
||||
public const val WARNING_TAG: String = "WARNING"
|
||||
}
|
||||
}
|
@ -15,12 +15,14 @@
|
||||
*/
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.get
|
||||
import hep.dataforge.meta.string
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
public interface GroupRule {
|
||||
public operator fun <T : Any> invoke(node: DataNode<T>): Map<String, DataNode<T>>
|
||||
public suspend fun <T : Any> gather(set: DataSet<T>): Map<String, DataSet<T>>
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
@ -31,37 +33,31 @@ public interface GroupRule {
|
||||
* @param defaultTagValue
|
||||
* @return
|
||||
*/
|
||||
public fun byValue(key: String, defaultTagValue: String): GroupRule = object :
|
||||
GroupRule {
|
||||
override fun <T : Any> invoke(node: DataNode<T>): Map<String, DataNode<T>> {
|
||||
val map = HashMap<String, DataTreeBuilder<T>>()
|
||||
public fun byMetaValue(
|
||||
scope: CoroutineScope,
|
||||
key: String,
|
||||
defaultTagValue: String,
|
||||
): GroupRule = object : GroupRule {
|
||||
|
||||
node.dataSequence().forEach { (name, data) ->
|
||||
override suspend fun <T : Any> gather(
|
||||
set: DataSet<T>,
|
||||
): Map<String, DataSet<T>> {
|
||||
val map = HashMap<String, ActiveDataTree<T>>()
|
||||
|
||||
set.flow().collect { data ->
|
||||
val tagValue = data.meta[key]?.string ?: defaultTagValue
|
||||
map.getOrPut(tagValue) { DataNode.builder(node.type) }[name] = data
|
||||
map.getOrPut(tagValue) { ActiveDataTree(set.dataType) }.emit(data.name, data.data)
|
||||
}
|
||||
|
||||
return map.mapValues { it.value.build() }
|
||||
scope.launch {
|
||||
set.updates.collect { name ->
|
||||
val data = set.getData(name)
|
||||
val tagValue = data?.meta[key]?.string ?: defaultTagValue
|
||||
map.getOrPut(tagValue) { ActiveDataTree(set.dataType) }.emit(name, data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// @ValueDef(key = "byValue", required = true, info = "The name of annotation value by which grouping should be made")
|
||||
// @ValueDef(
|
||||
// key = "defaultValue",
|
||||
// def = "default",
|
||||
// info = "Default value which should be used for content in which the grouping value is not presented"
|
||||
// )
|
||||
public fun byMeta(config: Meta): GroupRule {
|
||||
//TODO expand grouping options
|
||||
return config["byValue"]?.string?.let {
|
||||
byValue(
|
||||
it,
|
||||
config["defaultValue"]?.string ?: "default"
|
||||
)
|
||||
}
|
||||
?: object : GroupRule {
|
||||
override fun <T : Any> invoke(node: DataNode<T>): Map<String, DataNode<T>> = mapOf("" to node)
|
||||
return map
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,75 +0,0 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.Name
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* Action environment includes data name, data meta and action configuration meta
|
||||
*/
|
||||
public data class ActionEnv(
|
||||
val name: Name,
|
||||
val meta: Meta,
|
||||
val actionMeta: Meta
|
||||
)
|
||||
|
||||
/**
|
||||
* Action environment
|
||||
*/
|
||||
@DFBuilder
|
||||
public class MapActionBuilder<T, R>(public var name: Name, public var meta: MetaBuilder, public val actionMeta: Meta) {
|
||||
public lateinit var result: suspend ActionEnv.(T) -> R
|
||||
|
||||
/**
|
||||
* Calculate the result of goal
|
||||
*/
|
||||
public fun result(f: suspend ActionEnv.(T) -> R) {
|
||||
result = f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class MapAction<T : Any, out R : Any>(
|
||||
public val inputType: KClass<T>,
|
||||
public val outputType: KClass<out R>,
|
||||
private val block: MapActionBuilder<T, R>.() -> Unit
|
||||
) : Action<T, R> {
|
||||
|
||||
override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> {
|
||||
node.ensureType(inputType)
|
||||
|
||||
return DataNode.invoke(outputType) {
|
||||
node.dataSequence().forEach { (name, data) ->
|
||||
/*
|
||||
* Creating a new environment for action using **old** name, old meta and task meta
|
||||
*/
|
||||
val env = ActionEnv(name, data.meta, meta)
|
||||
|
||||
//applying transformation from builder
|
||||
val builder = MapActionBuilder<T, R>(
|
||||
name,
|
||||
data.meta.builder(), // using data meta
|
||||
meta
|
||||
).apply(block)
|
||||
|
||||
//getting new name
|
||||
val newName = builder.name
|
||||
|
||||
//getting new meta
|
||||
val newMeta = builder.meta.seal()
|
||||
|
||||
val newData = data.map(outputType, meta = newMeta) { builder.result(env, it) }
|
||||
//setting the data node
|
||||
this[newName] = newData
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public inline fun <reified T : Any, reified R : Any> DataNode<T>.map(
|
||||
meta: Meta,
|
||||
noinline action: MapActionBuilder<in T, out R>.() -> Unit
|
||||
): DataNode<R> = MapAction(T::class, R::class, action).invoke(this, meta)
|
||||
|
||||
|
||||
|
@ -0,0 +1,32 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.isEmpty
|
||||
import hep.dataforge.misc.Named
|
||||
import hep.dataforge.names.Name
|
||||
|
||||
public interface NamedData<out T : Any> : Named, Data<T> {
|
||||
override val name: Name
|
||||
public val data: Data<T>
|
||||
}
|
||||
|
||||
private class NamedDataImpl<out T : Any>(
|
||||
override val name: Name,
|
||||
override val data: Data<T>,
|
||||
) : Data<T> by data, NamedData<T> {
|
||||
override fun toString(): String = buildString {
|
||||
append("NamedData(name=\"$name\"")
|
||||
if (data is StaticData) {
|
||||
append(", value=${data.value}")
|
||||
}
|
||||
if (!data.meta.isEmpty()) {
|
||||
append(", meta=${data.meta}")
|
||||
}
|
||||
append(")")
|
||||
}
|
||||
}
|
||||
|
||||
public fun <T : Any> Data<T>.named(name: Name): NamedData<T> = if (this is NamedData) {
|
||||
NamedDataImpl(name, this.data)
|
||||
} else {
|
||||
NamedDataImpl(name, this)
|
||||
}
|
@ -1,107 +0,0 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.toName
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
|
||||
public class JoinGroup<T : Any, R : Any>(public var name: String, internal val node: DataNode<T>) {
|
||||
|
||||
public var meta: MetaBuilder = MetaBuilder()
|
||||
|
||||
public lateinit var result: suspend ActionEnv.(Map<Name, T>) -> R
|
||||
|
||||
public fun result(f: suspend ActionEnv.(Map<Name, T>) -> R) {
|
||||
this.result = f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class ReduceGroupBuilder<T : Any, R : Any>(public val actionMeta: Meta) {
|
||||
private val groupRules: MutableList<(DataNode<T>) -> List<JoinGroup<T, R>>> = ArrayList();
|
||||
|
||||
/**
|
||||
* introduce grouping by value name
|
||||
*/
|
||||
public fun byValue(tag: String, defaultTag: String = "@default", action: JoinGroup<T, R>.() -> Unit) {
|
||||
groupRules += { node ->
|
||||
GroupRule.byValue(tag, defaultTag).invoke(node).map {
|
||||
JoinGroup<T, R>(it.key, it.value).apply(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single fixed group to grouping rules
|
||||
*/
|
||||
public fun group(groupName: String, filter: DataFilter, action: JoinGroup<T, R>.() -> Unit) {
|
||||
groupRules += { node ->
|
||||
listOf(
|
||||
JoinGroup<T, R>(groupName, node.filter(filter)).apply(action)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public fun group(groupName: String, filter: (Name, Data<T>) -> Boolean, action: JoinGroup<T, R>.() -> Unit) {
|
||||
groupRules += { node ->
|
||||
listOf(
|
||||
JoinGroup<T, R>(groupName, node.filter(filter)).apply(action)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply transformation to the whole node
|
||||
*/
|
||||
public fun result(resultName: String, f: suspend ActionEnv.(Map<Name, T>) -> R) {
|
||||
groupRules += { node ->
|
||||
listOf(JoinGroup<T, R>(resultName, node).apply { result(f) })
|
||||
}
|
||||
}
|
||||
|
||||
internal fun buildGroups(input: DataNode<T>): List<JoinGroup<T, R>> {
|
||||
return groupRules.flatMap { it.invoke(input) }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The same rules as for KPipe
|
||||
*/
|
||||
public class ReduceAction<T : Any, R : Any>(
|
||||
public val inputType: KClass<T>,
|
||||
public val outputType: KClass<out R>,
|
||||
private val action: ReduceGroupBuilder<T, R>.() -> Unit
|
||||
) : Action<T, R> {
|
||||
|
||||
override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> {
|
||||
node.ensureType(inputType)
|
||||
return DataNode.invoke(outputType) {
|
||||
ReduceGroupBuilder<T, R>(meta).apply(action).buildGroups(node).forEach { group ->
|
||||
|
||||
//val laminate = Laminate(group.meta, meta)
|
||||
|
||||
val dataMap = group.node.dataSequence().associate { it }
|
||||
|
||||
val groupName: String = group.name
|
||||
|
||||
val groupMeta = group.meta
|
||||
|
||||
val env = ActionEnv(groupName.toName(), groupMeta, meta)
|
||||
|
||||
val res: DynamicData<R> = dataMap.reduce(
|
||||
outputType,
|
||||
meta = groupMeta
|
||||
) { group.result.invoke(env, it) }
|
||||
|
||||
set(env.name, res)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public operator fun <T> Map<Name, T>.get(name: String): T? = get(name.toName())
|
@ -1,64 +0,0 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.Laminate
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
import hep.dataforge.meta.builder
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.toName
|
||||
import kotlin.collections.set
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
|
||||
public class FragmentRule<T : Any, R : Any>(public val name: Name, public var meta: MetaBuilder) {
|
||||
public lateinit var result: suspend (T) -> R
|
||||
|
||||
public fun result(f: suspend (T) -> R) {
|
||||
result = f;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public class SplitBuilder<T : Any, R : Any>(public val name: Name, public val meta: Meta) {
|
||||
internal val fragments: MutableMap<Name, FragmentRule<T, R>.() -> Unit> = HashMap()
|
||||
|
||||
/**
|
||||
* Add new fragment building rule. If the framgent not defined, result won't be available even if it is present in the map
|
||||
* @param name the name of a fragment
|
||||
* @param rule the rule to transform fragment name and meta using
|
||||
*/
|
||||
public fun fragment(name: String, rule: FragmentRule<T, R>.() -> Unit) {
|
||||
fragments[name.toName()] = rule
|
||||
}
|
||||
}
|
||||
|
||||
public class SplitAction<T : Any, R : Any>(
|
||||
public val inputType: KClass<T>,
|
||||
public val outputType: KClass<out R>,
|
||||
private val action: SplitBuilder<T, R>.() -> Unit
|
||||
) : Action<T, R> {
|
||||
|
||||
override fun invoke(node: DataNode<T>, meta: Meta): DataNode<R> {
|
||||
node.ensureType(inputType)
|
||||
|
||||
return DataNode.invoke(outputType) {
|
||||
node.dataSequence().forEach { (name, data) ->
|
||||
|
||||
val laminate = Laminate(data.meta, meta)
|
||||
|
||||
val split = SplitBuilder<T, R>(name, data.meta).apply(action)
|
||||
|
||||
|
||||
// apply individual fragment rules to result
|
||||
split.fragments.forEach { (fragmentName, rule) ->
|
||||
val env = FragmentRule<T, R>(fragmentName, laminate.builder())
|
||||
|
||||
rule(env)
|
||||
|
||||
val res = data.map(outputType, meta = env.meta) { env.result(it) }
|
||||
set(env.name, res)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.names.*
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
@PublishedApi
|
||||
internal class StaticDataTree<T : Any>(
|
||||
override val dataType: KType,
|
||||
) : DataSetBuilder<T>, DataTree<T> {
|
||||
|
||||
private val items: MutableMap<NameToken, DataTreeItem<T>> = HashMap()
|
||||
|
||||
override suspend fun items(): Map<NameToken, DataTreeItem<T>> = items.filter { !it.key.body.startsWith("@") }
|
||||
|
||||
override suspend fun remove(name: Name) {
|
||||
when (name.length) {
|
||||
0 -> error("Can't remove root tree node")
|
||||
1 -> items.remove(name.firstOrNull()!!)
|
||||
else -> (items[name.firstOrNull()!!].tree as? StaticDataTree<T>)?.remove(name.cutFirst())
|
||||
}
|
||||
}
|
||||
|
||||
private fun getOrCreateNode(name: Name): StaticDataTree<T> = when (name.length) {
|
||||
0 -> this
|
||||
1 -> {
|
||||
val itemName = name.firstOrNull()!!
|
||||
(items[itemName].tree as? StaticDataTree<T>) ?: StaticDataTree<T>(dataType).also {
|
||||
items[itemName] = DataTreeItem.Node(it)
|
||||
}
|
||||
}
|
||||
else -> getOrCreateNode(name.cutLast()).getOrCreateNode(name.lastOrNull()!!.asName())
|
||||
}
|
||||
|
||||
private suspend fun set(name: Name, item: DataTreeItem<T>?) {
|
||||
if (name.isEmpty()) error("Can't set top level tree node")
|
||||
if (item == null) {
|
||||
remove(name)
|
||||
} else {
|
||||
getOrCreateNode(name.cutLast()).items[name.lastOrNull()!!] = item
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun emit(name: Name, data: Data<T>?) {
|
||||
set(name, data?.let { DataTreeItem.Leaf(it) })
|
||||
}
|
||||
|
||||
override suspend fun emit(name: Name, dataSet: DataSet<T>) {
|
||||
if (dataSet is StaticDataTree) {
|
||||
set(name, DataTreeItem.Node(dataSet))
|
||||
} else {
|
||||
coroutineScope {
|
||||
dataSet.flow().collect {
|
||||
emit(name + it.name, it.data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("FunctionName")
|
||||
public suspend fun <T : Any> DataTree(
|
||||
dataType: KType,
|
||||
block: suspend DataSetBuilder<T>.() -> Unit,
|
||||
): DataTree<T> = StaticDataTree<T>(dataType).apply { block() }
|
||||
|
||||
@Suppress("FunctionName")
|
||||
public suspend inline fun <reified T : Any> DataTree(
|
||||
noinline block: suspend DataSetBuilder<T>.() -> Unit,
|
||||
): DataTree<T> = DataTree(typeOf<T>(), block)
|
||||
|
||||
public suspend fun <T : Any> DataSet<T>.seal(): DataTree<T> = DataTree(dataType){
|
||||
populate(this@seal)
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.names.NameToken
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Deferred
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
public fun <R : Any, T : R> Data<T>.upcast(type: KClass<out R>): Data<R> {
|
||||
return object : Data<R> by this {
|
||||
override val type: KClass<out R> = type
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Safe upcast a [Data] to a supertype
|
||||
*/
|
||||
public inline fun <reified R : Any, T : R> Data<T>.upcast(): Data<R> = upcast(R::class)
|
||||
|
||||
/**
|
||||
* Check if node could be safely cast to given class
|
||||
*/
|
||||
internal expect fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean
|
||||
|
||||
/**
|
||||
* Check if data could be safely cast to given class
|
||||
*/
|
||||
internal expect fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean
|
||||
|
||||
public fun <R : Any> DataItem<*>.canCast(type: KClass<out R>): Boolean = when (this) {
|
||||
is DataItem.Node -> node.canCast(type)
|
||||
is DataItem.Leaf -> data.canCast(type)
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsafe cast of data node
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public fun <R : Any> Data<*>.cast(type: KClass<out R>): Data<R> {
|
||||
return object : Data<R> {
|
||||
override val meta: Meta get() = this@cast.meta
|
||||
override val dependencies: Collection<Goal<*>> get() = this@cast.dependencies
|
||||
override val result: Deferred<R>? get() = this@cast.result as Deferred<R>
|
||||
override fun CoroutineScope.startAsync(): Deferred<R> = this@cast.run { startAsync() as Deferred<R> }
|
||||
override fun reset() = this@cast.reset()
|
||||
override val type: KClass<out R> = type
|
||||
}
|
||||
}
|
||||
|
||||
public inline fun <reified R : Any> Data<*>.cast(): Data<R> = cast(R::class)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public fun <R : Any> DataNode<*>.cast(type: KClass<out R>): DataNode<R> {
|
||||
return object : DataNode<R> {
|
||||
override val meta: Meta get() = this@cast.meta
|
||||
override val type: KClass<out R> = type
|
||||
override val items: Map<NameToken, DataItem<R>> get() = this@cast.items as Map<NameToken, DataItem<R>>
|
||||
}
|
||||
}
|
||||
|
||||
public inline fun <reified R : Any> DataNode<*>.cast(): DataNode<R> = cast(R::class)
|
||||
|
||||
/**
|
||||
* Check that node is compatible with given type meaning that each element could be cast to the type
|
||||
*/
|
||||
public fun <T : Any> DataNode<*>.ensureType(type: KClass<out T>) {
|
||||
if (!canCast(type)) {
|
||||
error("$type expected, but $type received")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//expect fun <T : Any, R : Any> DataNode<T>.cast(type: KClass<out R>): DataNode<R>
|
@ -0,0 +1,71 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import hep.dataforge.names.*
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import kotlin.reflect.KType
|
||||
|
||||
|
||||
/**
|
||||
* A stateless filtered [DataSet]
|
||||
*/
|
||||
public fun <T : Any> DataSet<T>.filter(
|
||||
predicate: suspend (Name, Data<T>) -> Boolean,
|
||||
): ActiveDataSet<T> = object : ActiveDataSet<T> {
|
||||
override val dataType: KType get() = this@filter.dataType
|
||||
|
||||
override fun flow(): Flow<NamedData<T>> =
|
||||
this@filter.flow().filter { predicate(it.name, it.data) }
|
||||
|
||||
override suspend fun getData(name: Name): Data<T>? = this@filter.getData(name)?.takeIf {
|
||||
predicate(name, it)
|
||||
}
|
||||
|
||||
override val updates: Flow<Name> = this@filter.updates.filter flowFilter@{ name ->
|
||||
val theData = this@filter.getData(name) ?: return@flowFilter false
|
||||
predicate(name, theData)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a wrapper data set with a given name prefix appended to all names
|
||||
*/
|
||||
public fun <T : Any> DataSet<T>.withNamePrefix(prefix: Name): DataSet<T> = if (prefix.isEmpty()) this
|
||||
else object : ActiveDataSet<T> {
|
||||
override val dataType: KType get() = this@withNamePrefix.dataType
|
||||
|
||||
override fun flow(): Flow<NamedData<T>> = this@withNamePrefix.flow().map { it.data.named(prefix + it.name) }
|
||||
|
||||
override suspend fun getData(name: Name): Data<T>? =
|
||||
name.removeHeadOrNull(name)?.let { this@withNamePrefix.getData(it) }
|
||||
|
||||
override val updates: Flow<Name> get() = this@withNamePrefix.updates.map { prefix + it }
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a subset of data starting with a given [branchName]
|
||||
*/
|
||||
public fun <T : Any> DataSet<T>.branch(branchName: Name): DataSet<T> = if (branchName.isEmpty()) {
|
||||
this
|
||||
} else object : ActiveDataSet<T> {
|
||||
override val dataType: KType get() = this@branch.dataType
|
||||
|
||||
override fun flow(): Flow<NamedData<T>> = this@branch.flow().mapNotNull {
|
||||
it.name.removeHeadOrNull(branchName)?.let { name ->
|
||||
it.data.named(name)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun getData(name: Name): Data<T>? = this@branch.getData(branchName + name)
|
||||
|
||||
override val updates: Flow<Name> get() = this@branch.updates.mapNotNull { it.removeHeadOrNull(branchName) }
|
||||
}
|
||||
|
||||
public fun <T : Any> DataSet<T>.branch(branchName: String): DataSet<T> = this@branch.branch(branchName.toName())
|
||||
|
||||
@DFExperimental
|
||||
public suspend fun <T : Any> DataSet<T>.rootData(): Data<T>? = getData(Name.EMPTY)
|
||||
|
@ -0,0 +1,20 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
|
||||
|
||||
/**
|
||||
* Get a metadata node for this set if it is present
|
||||
*/
|
||||
public suspend fun DataSet<*>.getMeta(): Meta? = getData(DataSet.META_KEY)?.meta
|
||||
|
||||
/**
|
||||
* Add meta-data node to a [DataSet]
|
||||
*/
|
||||
public suspend fun DataSetBuilder<*>.meta(meta: Meta): Unit = emit(DataSet.META_KEY, Data.empty(meta))
|
||||
|
||||
/**
|
||||
* Add meta-data node to a [DataSet]
|
||||
*/
|
||||
public suspend fun DataSetBuilder<*>.meta(metaBuilder: MetaBuilder.() -> Unit): Unit = meta(Meta(metaBuilder))
|
@ -0,0 +1,181 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
import hep.dataforge.meta.seal
|
||||
import hep.dataforge.meta.toMutableMeta
|
||||
import hep.dataforge.misc.DFInternal
|
||||
import kotlinx.coroutines.flow.*
|
||||
import kotlin.contracts.InvocationKind
|
||||
import kotlin.contracts.contract
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
import kotlin.coroutines.EmptyCoroutineContext
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
/**
|
||||
* Lazily transform this data to another data. By convention [block] should not use external data (be pure).
|
||||
* @param coroutineContext additional [CoroutineContext] elements used for data computation.
|
||||
* @param meta for the resulting data. By default equals input data.
|
||||
* @param block the transformation itself
|
||||
*/
|
||||
public inline fun <T : Any, reified R : Any> Data<T>.map(
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
meta: Meta = this.meta,
|
||||
crossinline block: suspend (T) -> R,
|
||||
): Data<R> = Data(meta, coroutineContext, listOf(this)) {
|
||||
block(await())
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine this data with the other data using [block]. See [map] for other details
|
||||
*/
|
||||
public inline fun <T1 : Any, T2 : Any, reified R : Any> Data<T1>.combine(
|
||||
other: Data<T2>,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
meta: Meta = this.meta,
|
||||
crossinline block: suspend (left: T1, right: T2) -> R,
|
||||
): Data<R> = Data(meta, coroutineContext, listOf(this, other)) {
|
||||
block(await(), other.await())
|
||||
}
|
||||
|
||||
|
||||
//data collection operations
|
||||
|
||||
/**
|
||||
* Lazily reduce a collection of [Data] to a single data.
|
||||
*/
|
||||
public inline fun <T : Any, reified R : Any> Collection<Data<T>>.reduceToData(
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
meta: Meta = Meta.EMPTY,
|
||||
crossinline block: suspend (Collection<T>) -> R,
|
||||
): Data<R> = Data(
|
||||
meta,
|
||||
coroutineContext,
|
||||
this
|
||||
) {
|
||||
block(map { it.await() })
|
||||
}
|
||||
|
||||
@DFInternal
|
||||
public fun <K, T : Any, R : Any> Map<K, Data<T>>.reduceToData(
|
||||
outputType: KType,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
meta: Meta = Meta.EMPTY,
|
||||
block: suspend (Map<K, T>) -> R,
|
||||
): Data<R> = Data(
|
||||
outputType,
|
||||
meta,
|
||||
coroutineContext,
|
||||
this.values
|
||||
) {
|
||||
block(mapValues { it.value.await() })
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Lazily reduce a [Map] of [Data] with any static key.
|
||||
* @param K type of the map key
|
||||
* @param T type of the input goal
|
||||
* @param R type of the result goal
|
||||
*/
|
||||
public inline fun <K, T : Any, reified R : Any> Map<K, Data<T>>.reduceToData(
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
meta: Meta = Meta.EMPTY,
|
||||
noinline block: suspend (Map<K, T>) -> R,
|
||||
): Data<R> = Data(
|
||||
meta,
|
||||
coroutineContext,
|
||||
this.values
|
||||
) {
|
||||
block(mapValues { it.value.await() })
|
||||
}
|
||||
|
||||
//flow operations
|
||||
|
||||
/**
|
||||
* Transform a [Flow] of [NamedData] to a single [Data].
|
||||
*/
|
||||
@DFInternal
|
||||
public suspend fun <T : Any, R : Any> Flow<NamedData<T>>.reduceToData(
|
||||
outputType: KType,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
meta: Meta = Meta.EMPTY,
|
||||
transformation: suspend (Flow<NamedData<T>>) -> R,
|
||||
): Data<R> = Data(
|
||||
outputType,
|
||||
meta,
|
||||
coroutineContext,
|
||||
toList()
|
||||
) {
|
||||
transformation(this)
|
||||
}
|
||||
|
||||
@OptIn(DFInternal::class)
|
||||
public suspend inline fun <T : Any, reified R : Any> Flow<NamedData<T>>.reduceToData(
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
meta: Meta = Meta.EMPTY,
|
||||
noinline transformation: suspend (Flow<NamedData<T>>) -> R,
|
||||
): Data<R> = reduceToData(typeOf<R>(), coroutineContext, meta) {
|
||||
transformation(it)
|
||||
}
|
||||
|
||||
/**
|
||||
* Fold a flow of named data into a single [Data]
|
||||
*/
|
||||
public suspend inline fun <T : Any, reified R : Any> Flow<NamedData<T>>.foldToData(
|
||||
initial: R,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
meta: Meta = Meta.EMPTY,
|
||||
noinline block: suspend (result: R, data: NamedData<T>) -> R,
|
||||
): Data<R> = reduceToData(
|
||||
coroutineContext, meta
|
||||
) {
|
||||
it.fold(initial, block)
|
||||
}
|
||||
|
||||
//DataSet operations
|
||||
|
||||
@DFInternal
|
||||
public suspend fun <T : Any, R : Any> DataSet<T>.map(
|
||||
outputType: KType,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
metaTransform: MetaBuilder.() -> Unit = {},
|
||||
block: suspend (T) -> R,
|
||||
): DataTree<R> = DataTree<R>(outputType) {
|
||||
populate(
|
||||
flow().map {
|
||||
val newMeta = it.meta.toMutableMeta().apply(metaTransform).seal()
|
||||
Data(outputType, newMeta, coroutineContext, listOf(it)) {
|
||||
block(it.await())
|
||||
}.named(it.name)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(DFInternal::class)
|
||||
public suspend inline fun <T : Any, reified R : Any> DataSet<T>.map(
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
noinline metaTransform: MetaBuilder.() -> Unit = {},
|
||||
noinline block: suspend (T) -> R,
|
||||
): DataTree<R> = map(typeOf<R>(), coroutineContext, metaTransform, block)
|
||||
|
||||
public suspend fun <T : Any> DataSet<T>.forEach(block: suspend (NamedData<T>) -> Unit) {
|
||||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) }
|
||||
flow().collect {
|
||||
block(it)
|
||||
}
|
||||
}
|
||||
|
||||
public suspend inline fun <T : Any, reified R : Any> DataSet<T>.reduceToData(
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
meta: Meta = Meta.EMPTY,
|
||||
noinline transformation: suspend (Flow<NamedData<T>>) -> R,
|
||||
): Data<R> = flow().reduceToData(coroutineContext, meta, transformation)
|
||||
|
||||
public suspend inline fun <T : Any, reified R : Any> DataSet<T>.foldToData(
|
||||
initial: R,
|
||||
coroutineContext: CoroutineContext = EmptyCoroutineContext,
|
||||
meta: Meta = Meta.EMPTY,
|
||||
noinline block: suspend (result: R, data: NamedData<T>) -> R,
|
||||
): Data<R> = flow().foldToData(initial, coroutineContext, meta, block)
|
@ -1,32 +0,0 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertTrue
|
||||
|
||||
|
||||
internal class DataTreeBuilderTest{
|
||||
@Test
|
||||
fun testDataUpdate(){
|
||||
val updateData = DataNode<Any>{
|
||||
"update" put {
|
||||
"a" put Data.static("a")
|
||||
"b" put Data.static("b")
|
||||
}
|
||||
}
|
||||
|
||||
val node = DataNode<Any>{
|
||||
node("primary"){
|
||||
static("a","a")
|
||||
static("b","b")
|
||||
}
|
||||
static("root","root")
|
||||
update(updateData)
|
||||
}
|
||||
|
||||
println(node.toMeta())
|
||||
|
||||
assertTrue { node["update.a"] != null }
|
||||
assertTrue { node["primary.a"] != null }
|
||||
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* Check that node is compatible with given type meaning that each element could be cast to the type
|
||||
*/
|
||||
internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean {
|
||||
return this.type == type
|
||||
}
|
||||
|
||||
internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean {
|
||||
return this.type == type
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.names.NameToken
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
|
||||
/**
|
||||
* A zero-copy data node wrapper that returns only children with appropriate type.
|
||||
*/
|
||||
public class TypeFilteredDataNode<out T : Any>(public val origin: DataNode<*>, override val type: KClass<out T>) : DataNode<T> {
|
||||
override val meta: Meta get() = origin.meta
|
||||
override val items: Map<NameToken, DataItem<T>> by lazy {
|
||||
origin.items.mapNotNull { (key, item) ->
|
||||
when (item) {
|
||||
is DataItem.Leaf -> {
|
||||
(item.data.filterIsInstance(type))?.let {
|
||||
key to DataItem.Leaf(it)
|
||||
}
|
||||
}
|
||||
is DataItem.Node -> {
|
||||
key to DataItem.Node(item.node.filterIsInstance(type))
|
||||
}
|
||||
}
|
||||
}.associate { it }
|
||||
}
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.full.isSubclassOf
|
||||
|
||||
/**
|
||||
* Block the thread and get data content
|
||||
*/
|
||||
public fun <T : Any> Data<T>.get(): T = runBlocking { await() }
|
||||
|
||||
/**
|
||||
* Check that node is compatible with given type meaning that each element could be cast to the type
|
||||
*/
|
||||
internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean =
|
||||
type.isSubclassOf(this.type)
|
||||
|
||||
internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean =
|
||||
this.type.isSubclassOf(type)
|
||||
|
||||
/**
|
||||
* Cast the node to given type if the cast is possible or return null
|
||||
*/
|
||||
public fun <R : Any> Data<*>.filterIsInstance(type: KClass<out R>): Data<R>? =
|
||||
if (canCast(type)) cast(type) else null
|
||||
|
||||
/**
|
||||
* Filter a node by data and node type. Resulting node and its subnodes is guaranteed to have border type [type],
|
||||
* but could contain empty nodes
|
||||
*/
|
||||
public fun <R : Any> DataNode<*>.filterIsInstance(type: KClass<out R>): DataNode<R> {
|
||||
return when {
|
||||
canCast(type) -> cast(type)
|
||||
this is TypeFilteredDataNode -> origin.filterIsInstance(type)
|
||||
else -> TypeFilteredDataNode(this, type)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter all elements of given data item that could be cast to given type. If no elements are available, return null.
|
||||
*/
|
||||
public fun <R : Any> DataItem<*>?.filterIsInstance(type: KClass<out R>): DataItem<R>? = when (this) {
|
||||
null -> null
|
||||
is DataItem.Node -> DataItem.Node(this.node.filterIsInstance(type))
|
||||
is DataItem.Leaf -> this.data.filterIsInstance(type)?.let { DataItem.Leaf(it) }
|
||||
}
|
||||
|
||||
public inline fun <reified R : Any> DataItem<*>?.filterIsInstance(): DataItem<R>? = this@filterIsInstance.filterIsInstance(R::class)
|
@ -0,0 +1,64 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.matches
|
||||
import hep.dataforge.names.toName
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.full.isSubtypeOf
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
|
||||
/**
|
||||
* Cast the node to given type if the cast is possible or return null
|
||||
*/
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun <R : Any> Data<*>.castOrNull(type: KType): Data<R>? =
|
||||
if (!this.type.isSubtypeOf(type)) null else object : Data<R> by (this as Data<R>) {
|
||||
override val type: KType = type
|
||||
}
|
||||
|
||||
/**
|
||||
* Select all data matching given type and filters. Does not modify paths
|
||||
*/
|
||||
@OptIn(DFExperimental::class)
|
||||
@PublishedApi
|
||||
internal fun <R : Any> DataSet<*>.select(
|
||||
type: KType,
|
||||
namePattern: Name? = null,
|
||||
): ActiveDataSet<R> = object : ActiveDataSet<R> {
|
||||
override val dataType = type
|
||||
|
||||
|
||||
override fun flow(): Flow<NamedData<R>> = this@select.flow().filter { datum ->
|
||||
datum.type.isSubtypeOf(type) && (namePattern == null || datum.name.matches(namePattern))
|
||||
}.map {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
it as NamedData<R>
|
||||
}
|
||||
|
||||
override suspend fun getData(name: Name): Data<R>? = this@select.getData(name)?.castOrNull(type)
|
||||
|
||||
override val updates: Flow<Name> = this@select.updates.filter {
|
||||
val datum = this@select.getData(it)
|
||||
datum?.type?.isSubtypeOf(type) ?: false
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Select a single datum of the appropriate type
|
||||
*/
|
||||
public inline fun <reified R : Any> DataSet<*>.select(namePattern: Name? = null): DataSet<R> =
|
||||
select(typeOf<R>(), namePattern)
|
||||
|
||||
public suspend fun <R : Any> DataSet<*>.selectOne(type: KType, name: Name): NamedData<R>? =
|
||||
getData(name)?.castOrNull<R>(type)?.named(name)
|
||||
|
||||
public suspend inline fun <reified R : Any> DataSet<*>.selectOne(name: Name): NamedData<R>? = selectOne(typeOf<R>(), name)
|
||||
|
||||
public suspend inline fun <reified R : Any> DataSet<*>.selectOne(name: String): NamedData<R>? =
|
||||
selectOne(typeOf<R>(), name.toName())
|
@ -0,0 +1,42 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.actions.Action
|
||||
import hep.dataforge.actions.map
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.junit.jupiter.api.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@Suppress("EXPERIMENTAL_API_USAGE")
|
||||
class ActionsTest {
|
||||
val data: DataTree<Int> = runBlocking {
|
||||
DataTree {
|
||||
repeat(10) {
|
||||
static(it.toString(), it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testStaticMapAction() {
|
||||
val plusOne = Action.map<Int, Int> {
|
||||
result { it + 1 }
|
||||
}
|
||||
runBlocking {
|
||||
val result = plusOne.execute(data)
|
||||
assertEquals(2, result.getData("1")?.await())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDynamicMapAction() {
|
||||
val plusOne = Action.map<Int, Int> {
|
||||
result { it + 1 }
|
||||
}
|
||||
val datum = runBlocking {
|
||||
val result = plusOne.execute(data, scope = this)
|
||||
result.getData("1")?.await()
|
||||
}
|
||||
assertEquals(2, datum)
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import hep.dataforge.names.toName
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
|
||||
internal class DataTreeBuilderTest {
|
||||
@Test
|
||||
fun testTreeBuild() = runBlocking {
|
||||
val node = DataTree<Any> {
|
||||
"primary" put {
|
||||
static("a", "a")
|
||||
static("b", "b")
|
||||
}
|
||||
static("c.d", "c.d")
|
||||
static("c.f", "c.f")
|
||||
}
|
||||
runBlocking {
|
||||
assertEquals("a", node.getData("primary.a")?.await())
|
||||
assertEquals("b", node.getData("primary.b")?.await())
|
||||
assertEquals("c.d", node.getData("c.d")?.await())
|
||||
assertEquals("c.f", node.getData("c.f")?.await())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDataUpdate() = runBlocking {
|
||||
val updateData: DataTree<Any> = DataTree {
|
||||
"update" put {
|
||||
"a" put Data.static("a")
|
||||
"b" put Data.static("b")
|
||||
}
|
||||
}
|
||||
|
||||
val node = DataTree<Any> {
|
||||
"primary" put {
|
||||
static("a", "a")
|
||||
static("b", "b")
|
||||
}
|
||||
static("root", "root")
|
||||
populate(updateData)
|
||||
}
|
||||
|
||||
runBlocking {
|
||||
assertEquals("a", node.getData("update.a")?.await())
|
||||
assertEquals("a", node.getData("primary.a")?.await())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDynamicUpdates() = runBlocking {
|
||||
try {
|
||||
lateinit var updateJob: Job
|
||||
supervisorScope {
|
||||
val subNode = ActiveDataTree<Int> {
|
||||
updateJob = launch {
|
||||
repeat(10) {
|
||||
delay(10)
|
||||
static("value", it)
|
||||
}
|
||||
delay(10)
|
||||
}
|
||||
}
|
||||
launch {
|
||||
subNode.updatesWithData.collect {
|
||||
println(it)
|
||||
}
|
||||
}
|
||||
val rootNode = ActiveDataTree<Int> {
|
||||
setAndObserve("sub".toName(), subNode)
|
||||
}
|
||||
|
||||
launch {
|
||||
rootNode.updatesWithData.collect {
|
||||
println(it)
|
||||
}
|
||||
}
|
||||
updateJob.join()
|
||||
assertEquals(9, rootNode.getData("sub.value")?.await())
|
||||
cancel()
|
||||
}
|
||||
} catch (t: Throwable) {
|
||||
if (t !is CancellationException) throw t
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
package hep.dataforge.data
|
||||
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
/**
|
||||
* Check that node is compatible with given type meaning that each element could be cast to the type
|
||||
*/
|
||||
internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean {
|
||||
return this.type == type
|
||||
}
|
||||
|
||||
internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean {
|
||||
return this.type == type
|
||||
}
|
@ -7,7 +7,7 @@ public final class hep/dataforge/io/BinaryMetaFormat : hep/dataforge/io/MetaForm
|
||||
public fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Lhep/dataforge/io/MetaFormat;
|
||||
public synthetic fun invoke (Lhep/dataforge/meta/Meta;Lhep/dataforge/context/Context;)Ljava/lang/Object;
|
||||
public fun readMeta (Lkotlinx/io/Input;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Meta;
|
||||
public final fun readMetaItem (Lkotlinx/io/Input;)Lhep/dataforge/meta/MetaItem;
|
||||
public final fun readMetaItem (Lkotlinx/io/Input;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/meta/Meta;
|
||||
public synthetic fun readObject (Lkotlinx/io/Input;)Ljava/lang/Object;
|
||||
public fun toMeta ()Lhep/dataforge/meta/Meta;
|
||||
@ -77,6 +77,10 @@ public final class hep/dataforge/io/EnvelopeBuilder : hep/dataforge/io/Envelope
|
||||
public final fun setType (Ljava/lang/String;)V
|
||||
}
|
||||
|
||||
public final class hep/dataforge/io/EnvelopeBuilderKt {
|
||||
public static final fun Envelope (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/io/Envelope;
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/io/EnvelopeFormat : hep/dataforge/io/IOFormat {
|
||||
public abstract fun getDefaultMetaFormat ()Lhep/dataforge/io/MetaFormatFactory;
|
||||
public abstract fun readObject (Lkotlinx/io/Input;)Lhep/dataforge/io/Envelope;
|
||||
@ -215,8 +219,8 @@ public final class hep/dataforge/io/IOPlugin : hep/dataforge/context/AbstractPlu
|
||||
public final fun getIoFormatFactories ()Ljava/util/Collection;
|
||||
public final fun getMetaFormatFactories ()Ljava/util/Collection;
|
||||
public fun getTag ()Lhep/dataforge/context/PluginTag;
|
||||
public final fun resolveEnvelopeFormat (Lhep/dataforge/meta/MetaItem;)Lhep/dataforge/io/EnvelopeFormat;
|
||||
public final fun resolveIOFormat (Lhep/dataforge/meta/MetaItem;Lkotlin/reflect/KClass;)Lhep/dataforge/io/IOFormat;
|
||||
public final fun resolveEnvelopeFormat (Lhep/dataforge/meta/TypedMetaItem;)Lhep/dataforge/io/EnvelopeFormat;
|
||||
public final fun resolveIOFormat (Lhep/dataforge/meta/TypedMetaItem;Lkotlin/reflect/KClass;)Lhep/dataforge/io/IOFormat;
|
||||
public final fun resolveMetaFormat (Ljava/lang/String;Lhep/dataforge/meta/Meta;)Lhep/dataforge/io/MetaFormat;
|
||||
public final fun resolveMetaFormat (SLhep/dataforge/meta/Meta;)Lhep/dataforge/io/MetaFormat;
|
||||
public static synthetic fun resolveMetaFormat$default (Lhep/dataforge/io/IOPlugin;Ljava/lang/String;Lhep/dataforge/meta/Meta;ILjava/lang/Object;)Lhep/dataforge/io/MetaFormat;
|
||||
|
@ -23,3 +23,7 @@ kotlin {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readme{
|
||||
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
|
||||
}
|
@ -57,3 +57,10 @@ public final class hep/dataforge/io/yaml/YamlMetaFormat$Companion : hep/dataforg
|
||||
public synthetic fun writeObject (Lkotlinx/io/Output;Ljava/lang/Object;)V
|
||||
}
|
||||
|
||||
public final class hep/dataforge/io/yaml/YamlMetaFormatKt {
|
||||
public static final fun toMeta (Lnet/mamoe/yamlkt/YamlMap;)Lhep/dataforge/meta/Meta;
|
||||
public static final fun toMetaItem (Lnet/mamoe/yamlkt/YamlElement;Lhep/dataforge/meta/descriptors/ItemDescriptor;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static synthetic fun toMetaItem$default (Lnet/mamoe/yamlkt/YamlElement;Lhep/dataforge/meta/descriptors/ItemDescriptor;ILjava/lang/Object;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static final fun toYaml (Lhep/dataforge/meta/Meta;)Lnet/mamoe/yamlkt/YamlMap;
|
||||
}
|
||||
|
||||
|
@ -1,16 +1,33 @@
|
||||
plugins {
|
||||
id("ru.mipt.npm.jvm")
|
||||
id("ru.mipt.npm.mpp")
|
||||
// id("ru.mipt.npm.native")
|
||||
}
|
||||
|
||||
description = "YAML meta IO"
|
||||
|
||||
kscience {
|
||||
useSerialization{
|
||||
yaml()
|
||||
yamlKt("0.9.0-dev-1")
|
||||
}
|
||||
}
|
||||
|
||||
repositories{
|
||||
maven("https://dl.bintray.com/mamoe/yamlkt")
|
||||
}
|
||||
|
||||
kotlin {
|
||||
sourceSets {
|
||||
commonMain{
|
||||
dependencies {
|
||||
api(project(":dataforge-io"))
|
||||
api("org.yaml:snakeyaml:1.26")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
readme{
|
||||
maturity = ru.mipt.npm.gradle.Maturity.PROTOTYPE
|
||||
description ="""
|
||||
YAML meta converters and Front Matter envelope format
|
||||
""".trimIndent()
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ import hep.dataforge.context.Context
|
||||
import hep.dataforge.io.*
|
||||
import hep.dataforge.io.IOFormat.Companion.META_KEY
|
||||
import hep.dataforge.io.IOFormat.Companion.NAME_KEY
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import kotlinx.io.*
|
||||
import kotlinx.io.text.readUtf8Line
|
||||
import kotlinx.io.text.writeUtf8String
|
||||
@ -17,11 +17,11 @@ public class FrontMatterEnvelopeFormat(
|
||||
) : EnvelopeFormat {
|
||||
|
||||
override fun readPartial(input: Input): PartialEnvelope {
|
||||
var line = ""
|
||||
var line: String
|
||||
var offset = 0u
|
||||
do {
|
||||
line = input.readUtf8Line() //?: error("Input does not contain front matter separator")
|
||||
offset += line.toByteArray().size.toUInt()
|
||||
offset += line.encodeToByteArray().size.toUInt()
|
||||
} while (!line.startsWith(SEPARATOR))
|
||||
|
||||
val readMetaFormat =
|
||||
@ -33,7 +33,7 @@ public class FrontMatterEnvelopeFormat(
|
||||
do {
|
||||
line = input.readUtf8Line()
|
||||
writeUtf8String(line + "\r\n")
|
||||
offset += line.toByteArray().size.toUInt()
|
||||
offset += line.encodeToByteArray().size.toUInt()
|
||||
} while (!line.startsWith(SEPARATOR))
|
||||
}.read {
|
||||
readMetaFormat.readMeta(input)
|
||||
@ -43,7 +43,7 @@ public class FrontMatterEnvelopeFormat(
|
||||
}
|
||||
|
||||
override fun readObject(input: Input): Envelope {
|
||||
var line = ""
|
||||
var line: String
|
||||
do {
|
||||
line = input.readUtf8Line() //?: error("Input does not contain front matter separator")
|
||||
} while (!line.startsWith(SEPARATOR))
|
||||
@ -86,7 +86,7 @@ public class FrontMatterEnvelopeFormat(
|
||||
}
|
||||
|
||||
public companion object : EnvelopeFormatFactory {
|
||||
public const val SEPARATOR = "---"
|
||||
public const val SEPARATOR: String = "---"
|
||||
|
||||
private val metaTypeRegex = "---(\\w*)\\s*".toRegex()
|
||||
|
@ -0,0 +1,122 @@
|
||||
package hep.dataforge.io.yaml
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.io.IOFormat.Companion.META_KEY
|
||||
import hep.dataforge.io.IOFormat.Companion.NAME_KEY
|
||||
import hep.dataforge.io.MetaFormat
|
||||
import hep.dataforge.io.MetaFormatFactory
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.meta.descriptors.ItemDescriptor
|
||||
import hep.dataforge.meta.descriptors.NodeDescriptor
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import hep.dataforge.names.NameToken
|
||||
import hep.dataforge.names.withIndex
|
||||
import hep.dataforge.values.ListValue
|
||||
import hep.dataforge.values.Null
|
||||
import hep.dataforge.values.parseValue
|
||||
import kotlinx.io.Input
|
||||
import kotlinx.io.Output
|
||||
import kotlinx.io.text.readUtf8String
|
||||
import kotlinx.io.text.writeUtf8String
|
||||
import net.mamoe.yamlkt.*
|
||||
|
||||
public fun Meta.toYaml(): YamlMap {
|
||||
val map: Map<String, Any?> = items.entries.associate { (key, item) ->
|
||||
key.toString() to when (item) {
|
||||
is MetaItemValue -> {
|
||||
item.value.value
|
||||
}
|
||||
is MetaItemNode -> {
|
||||
item.node.toYaml()
|
||||
}
|
||||
}
|
||||
}
|
||||
return YamlMap(map)
|
||||
}
|
||||
|
||||
private class YamlMeta(private val yamlMap: YamlMap, private val descriptor: NodeDescriptor? = null) : MetaBase() {
|
||||
|
||||
private fun buildItems(): Map<NameToken, MetaItem> {
|
||||
val map = LinkedHashMap<NameToken, MetaItem>()
|
||||
|
||||
yamlMap.content.entries.forEach { (key, value) ->
|
||||
val stringKey = key.toString()
|
||||
val itemDescriptor = descriptor?.items?.get(stringKey)
|
||||
val token = NameToken(stringKey)
|
||||
when (value) {
|
||||
YamlNull -> Null.asMetaItem()
|
||||
is YamlLiteral -> map[token] = value.content.parseValue().asMetaItem()
|
||||
is YamlMap -> map[token] = value.toMeta().asMetaItem()
|
||||
is YamlList -> if (value.all { it is YamlLiteral }) {
|
||||
val listValue = ListValue(
|
||||
value.map {
|
||||
//We already checked that all values are primitives
|
||||
(it as YamlLiteral).content.parseValue()
|
||||
}
|
||||
)
|
||||
map[token] = MetaItemValue(listValue)
|
||||
} else value.forEachIndexed { index, yamlElement ->
|
||||
val indexKey = (itemDescriptor as? NodeDescriptor)?.indexKey ?: ItemDescriptor.DEFAULT_INDEX_KEY
|
||||
val indexValue: String = (yamlElement as? YamlMap)?.getStringOrNull(indexKey)
|
||||
?: index.toString() //In case index is non-string, the backward transformation will be broken.
|
||||
|
||||
val tokenWithIndex = token.withIndex(indexValue)
|
||||
map[tokenWithIndex] = yamlElement.toMetaItem(itemDescriptor)
|
||||
}
|
||||
}
|
||||
}
|
||||
return map
|
||||
}
|
||||
|
||||
override val items: Map<NameToken, MetaItem> get() = buildItems()
|
||||
}
|
||||
|
||||
public fun YamlElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem = when (this) {
|
||||
YamlNull -> Null.asMetaItem()
|
||||
is YamlLiteral -> content.parseValue().asMetaItem()
|
||||
is YamlMap -> toMeta().asMetaItem()
|
||||
//We can't return multiple items therefore we create top level node
|
||||
is YamlList -> YamlMap(mapOf("@yamlArray" to this)).toMetaItem(descriptor)
|
||||
}
|
||||
|
||||
public fun YamlMap.toMeta(): Meta = YamlMeta(this)
|
||||
|
||||
|
||||
/**
|
||||
* Represent meta as Yaml
|
||||
*/
|
||||
@DFExperimental
|
||||
public class YamlMetaFormat(private val meta: Meta) : MetaFormat {
|
||||
|
||||
override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?) {
|
||||
val yaml = meta.toYaml()
|
||||
val string = Yaml.encodeToString(yaml)
|
||||
output.writeUtf8String(string)
|
||||
}
|
||||
|
||||
override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta {
|
||||
val yaml = Yaml.decodeYamlMapFromString(input.readUtf8String())
|
||||
return yaml.toMeta()
|
||||
}
|
||||
|
||||
override fun toMeta(): Meta = Meta {
|
||||
NAME_KEY put FrontMatterEnvelopeFormat.name.toString()
|
||||
META_KEY put meta
|
||||
}
|
||||
|
||||
public companion object : MetaFormatFactory {
|
||||
override fun invoke(meta: Meta, context: Context): MetaFormat = YamlMetaFormat(meta)
|
||||
|
||||
override val shortName: String = "yaml"
|
||||
|
||||
override val key: Short = 0x594d //YM
|
||||
|
||||
private val default = YamlMetaFormat()
|
||||
|
||||
override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?): Unit =
|
||||
default.writeMeta(output, meta, descriptor)
|
||||
|
||||
override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta =
|
||||
default.readMeta(input, descriptor)
|
||||
}
|
||||
}
|
@ -2,10 +2,10 @@ package hep.dataforge.io.yaml
|
||||
|
||||
import hep.dataforge.io.parse
|
||||
import hep.dataforge.io.toString
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.get
|
||||
import hep.dataforge.meta.seal
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
@ -1,56 +0,0 @@
|
||||
package hep.dataforge.io.yaml
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.io.IOFormat.Companion.META_KEY
|
||||
import hep.dataforge.io.IOFormat.Companion.NAME_KEY
|
||||
import hep.dataforge.io.MetaFormat
|
||||
import hep.dataforge.io.MetaFormatFactory
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.descriptors.NodeDescriptor
|
||||
import hep.dataforge.meta.toMap
|
||||
import hep.dataforge.meta.toMeta
|
||||
import kotlinx.io.Input
|
||||
import kotlinx.io.Output
|
||||
import kotlinx.io.asInputStream
|
||||
import kotlinx.io.text.writeUtf8String
|
||||
import org.yaml.snakeyaml.Yaml
|
||||
|
||||
/**
|
||||
* Represent meta as Yaml
|
||||
*/
|
||||
@DFExperimental
|
||||
public class YamlMetaFormat(private val meta: Meta) : MetaFormat {
|
||||
private val yaml = Yaml()
|
||||
|
||||
override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?) {
|
||||
val string = yaml.dump(meta.toMap(descriptor))
|
||||
output.writeUtf8String(string)
|
||||
}
|
||||
|
||||
override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta {
|
||||
val map: Map<String, Any?> = yaml.load(input.asInputStream())
|
||||
return map.toMeta(descriptor)
|
||||
}
|
||||
|
||||
override fun toMeta(): Meta = Meta{
|
||||
NAME_KEY put FrontMatterEnvelopeFormat.name.toString()
|
||||
META_KEY put meta
|
||||
}
|
||||
|
||||
public companion object : MetaFormatFactory {
|
||||
override fun invoke(meta: Meta, context: Context): MetaFormat = YamlMetaFormat(meta)
|
||||
|
||||
override val shortName: String = "yaml"
|
||||
|
||||
override val key: Short = 0x594d //YM
|
||||
|
||||
private val default = YamlMetaFormat()
|
||||
|
||||
override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?): Unit =
|
||||
default.writeMeta(output, meta, descriptor)
|
||||
|
||||
override fun readMeta(input: kotlinx.io.Input, descriptor: NodeDescriptor?): Meta =
|
||||
default.readMeta(input, descriptor)
|
||||
}
|
||||
}
|
@ -1,11 +1,8 @@
|
||||
package hep.dataforge.io
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaBuilder
|
||||
import hep.dataforge.meta.MetaItem
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.meta.descriptors.NodeDescriptor
|
||||
import hep.dataforge.meta.setItem
|
||||
import hep.dataforge.values.*
|
||||
import kotlinx.io.*
|
||||
import kotlinx.io.text.readUtf8String
|
||||
@ -22,7 +19,7 @@ public object BinaryMetaFormat : MetaFormat, MetaFormatFactory {
|
||||
override fun invoke(meta: Meta, context: Context): MetaFormat = this
|
||||
|
||||
override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta {
|
||||
return (input.readMetaItem() as MetaItem.NodeItem).node
|
||||
return (input.readMetaItem() as MetaItemNode).node
|
||||
}
|
||||
|
||||
private fun Output.writeChar(char: Char) = writeByte(char.toByte())
|
||||
@ -32,34 +29,27 @@ public object BinaryMetaFormat : MetaFormat, MetaFormatFactory {
|
||||
writeUtf8String(str)
|
||||
}
|
||||
|
||||
public fun Output.writeValue(value: Value) {
|
||||
if (value.isList()) {
|
||||
writeChar('L')
|
||||
writeInt(value.list.size)
|
||||
value.list.forEach {
|
||||
writeValue(it)
|
||||
}
|
||||
} else when (value.type) {
|
||||
public fun Output.writeValue(value: Value): Unit = when (value.type) {
|
||||
ValueType.NUMBER -> when (value.value) {
|
||||
is Short -> {
|
||||
writeChar('s')
|
||||
writeShort(value.number.toShort())
|
||||
writeShort(value.short)
|
||||
}
|
||||
is Int -> {
|
||||
writeChar('i')
|
||||
writeInt(value.number.toInt())
|
||||
writeInt(value.int)
|
||||
}
|
||||
is Long -> {
|
||||
writeChar('l')
|
||||
writeLong(value.number.toLong())
|
||||
writeLong(value.long)
|
||||
}
|
||||
is Float -> {
|
||||
writeChar('f')
|
||||
writeFloat(value.number.toFloat())
|
||||
writeFloat(value.float)
|
||||
}
|
||||
else -> {
|
||||
writeChar('d')
|
||||
writeDouble(value.number.toDouble())
|
||||
writeDouble(value.double)
|
||||
}
|
||||
}
|
||||
ValueType.STRING -> {
|
||||
@ -76,23 +66,29 @@ public object BinaryMetaFormat : MetaFormat, MetaFormatFactory {
|
||||
ValueType.NULL -> {
|
||||
writeChar('N')
|
||||
}
|
||||
ValueType.LIST -> {
|
||||
writeChar('L')
|
||||
writeInt(value.list.size)
|
||||
value.list.forEach {
|
||||
writeValue(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun writeMeta(
|
||||
output: kotlinx.io.Output,
|
||||
meta: hep.dataforge.meta.Meta,
|
||||
descriptor: hep.dataforge.meta.descriptors.NodeDescriptor?
|
||||
descriptor: hep.dataforge.meta.descriptors.NodeDescriptor?,
|
||||
) {
|
||||
output.writeChar('M')
|
||||
output.writeInt(meta.items.size)
|
||||
meta.items.forEach { (key, item) ->
|
||||
output.writeString(key.toString())
|
||||
when (item) {
|
||||
is MetaItem.ValueItem -> {
|
||||
is MetaItemValue -> {
|
||||
output.writeValue(item.value)
|
||||
}
|
||||
is MetaItem.NodeItem -> {
|
||||
is MetaItemNode -> {
|
||||
writeObject(output, item.node)
|
||||
}
|
||||
}
|
||||
@ -105,21 +101,21 @@ public object BinaryMetaFormat : MetaFormat, MetaFormatFactory {
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public fun Input.readMetaItem(): MetaItem<MetaBuilder> {
|
||||
public fun Input.readMetaItem(): TypedMetaItem<MetaBuilder> {
|
||||
return when (val keyChar = readByte().toChar()) {
|
||||
'S' -> MetaItem.ValueItem(StringValue(readString()))
|
||||
'N' -> MetaItem.ValueItem(Null)
|
||||
'+' -> MetaItem.ValueItem(True)
|
||||
'-' -> MetaItem.ValueItem(True)
|
||||
's' -> MetaItem.ValueItem(NumberValue(readShort()))
|
||||
'i' -> MetaItem.ValueItem(NumberValue(readInt()))
|
||||
'l' -> MetaItem.ValueItem(NumberValue(readInt()))
|
||||
'f' -> MetaItem.ValueItem(NumberValue(readFloat()))
|
||||
'd' -> MetaItem.ValueItem(NumberValue(readDouble()))
|
||||
'S' -> MetaItemValue(StringValue(readString()))
|
||||
'N' -> MetaItemValue(Null)
|
||||
'+' -> MetaItemValue(True)
|
||||
'-' -> MetaItemValue(True)
|
||||
's' -> MetaItemValue(NumberValue(readShort()))
|
||||
'i' -> MetaItemValue(NumberValue(readInt()))
|
||||
'l' -> MetaItemValue(NumberValue(readInt()))
|
||||
'f' -> MetaItemValue(NumberValue(readFloat()))
|
||||
'd' -> MetaItemValue(NumberValue(readDouble()))
|
||||
'L' -> {
|
||||
val length = readInt()
|
||||
val list = (1..length).map { (readMetaItem() as MetaItem.ValueItem).value }
|
||||
MetaItem.ValueItem(Value.of(list))
|
||||
val list = (1..length).map { (readMetaItem() as MetaItemValue).value }
|
||||
MetaItemValue(Value.of(list))
|
||||
}
|
||||
'M' -> {
|
||||
val length = readInt()
|
||||
@ -127,10 +123,10 @@ public object BinaryMetaFormat : MetaFormat, MetaFormatFactory {
|
||||
(1..length).forEach { _ ->
|
||||
val name = readString()
|
||||
val item = readMetaItem()
|
||||
setItem(name, item)
|
||||
set(name, item)
|
||||
}
|
||||
}
|
||||
MetaItem.NodeItem(meta)
|
||||
MetaItemNode(meta)
|
||||
}
|
||||
else -> error("Unknown serialization key character: $keyChar")
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
package hep.dataforge.io
|
||||
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
|
||||
/**
|
||||
* A fire-and-forget consumer of messages
|
||||
|
@ -29,6 +29,7 @@ public interface Envelope {
|
||||
/**
|
||||
* Build a static envelope using provided builder
|
||||
*/
|
||||
@Deprecated("Use top level function instead")
|
||||
public inline operator fun invoke(block: EnvelopeBuilder.() -> Unit): Envelope =
|
||||
EnvelopeBuilder().apply(block).seal()
|
||||
}
|
||||
|
@ -44,6 +44,12 @@ public class EnvelopeBuilder : Envelope {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Build a static envelope using provided [builder]
|
||||
*/
|
||||
public inline fun Envelope(builder: EnvelopeBuilder.() -> Unit): Envelope = EnvelopeBuilder().apply(builder).seal()
|
||||
|
||||
//@ExperimentalContracts
|
||||
//suspend fun EnvelopeBuilder.buildData(block: suspend Output.() -> Unit): Binary{
|
||||
// contract {
|
||||
|
@ -3,12 +3,13 @@ package hep.dataforge.io
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.io.EnvelopeFormatFactory.Companion.ENVELOPE_FORMAT_TYPE
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.misc.Type
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.provider.Type
|
||||
import kotlinx.io.Input
|
||||
import kotlinx.io.Output
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
/**
|
||||
* A partially read envelope with meta, but without data
|
||||
@ -16,6 +17,8 @@ import kotlin.reflect.KClass
|
||||
public data class PartialEnvelope(val meta: Meta, val dataOffset: UInt, val dataSize: ULong?)
|
||||
|
||||
public interface EnvelopeFormat : IOFormat<Envelope> {
|
||||
override val type: KType get() = typeOf<Envelope>()
|
||||
|
||||
public val defaultMetaFormat: MetaFormatFactory get() = JsonMetaFormat
|
||||
|
||||
public fun readPartial(input: Input): PartialEnvelope
|
||||
@ -37,7 +40,7 @@ public fun EnvelopeFormat.read(input: Input): Envelope = readObject(input)
|
||||
@Type(ENVELOPE_FORMAT_TYPE)
|
||||
public interface EnvelopeFormatFactory : IOFormatFactory<Envelope>, EnvelopeFormat {
|
||||
override val name: Name get() = "envelope".asName()
|
||||
override val type: KClass<out Envelope> get() = Envelope::class
|
||||
override val type: KType get() = typeOf<Envelope>()
|
||||
|
||||
override fun invoke(meta: Meta, context: Context): EnvelopeFormat
|
||||
|
||||
|
@ -10,13 +10,14 @@ import hep.dataforge.io.PartDescriptor.Companion.SEPARATOR_KEY
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.names.plus
|
||||
import hep.dataforge.names.toName
|
||||
import kotlinx.io.Binary
|
||||
import kotlinx.io.writeBinary
|
||||
|
||||
private class PartDescriptor : Scheme() {
|
||||
var offset by int(0)
|
||||
var size by int(0)
|
||||
var meta by node()
|
||||
var partMeta by node("meta".toName())
|
||||
|
||||
companion object : SchemeSpec<PartDescriptor>(::PartDescriptor) {
|
||||
val MULTIPART_KEY = ENVELOPE_NODE_KEY + "multipart"
|
||||
@ -48,7 +49,7 @@ public fun EnvelopeBuilder.multipart(
|
||||
PartDescriptor {
|
||||
offset = offsetCounter
|
||||
size = binary.size
|
||||
meta = description
|
||||
partMeta = description
|
||||
}.also {
|
||||
offsetCounter += binary.size
|
||||
}
|
||||
@ -95,7 +96,7 @@ public fun Envelope.parts(): EnvelopeParts {
|
||||
} else {
|
||||
parts.map {
|
||||
val binary = data!!.view(it.offset, it.size)
|
||||
val meta = Laminate(it.meta, meta[MULTIPART_KEY].node)
|
||||
val meta = Laminate(it.partMeta, meta[MULTIPART_KEY].node)
|
||||
EnvelopePart(binary, meta)
|
||||
}
|
||||
}
|
||||
|
@ -2,25 +2,28 @@ package hep.dataforge.io
|
||||
|
||||
import hep.dataforge.context.Context
|
||||
import hep.dataforge.context.Factory
|
||||
import hep.dataforge.context.Named
|
||||
import hep.dataforge.io.IOFormat.Companion.NAME_KEY
|
||||
import hep.dataforge.io.IOFormatFactory.Companion.IO_FORMAT_TYPE
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaItem
|
||||
import hep.dataforge.meta.MetaItemValue
|
||||
import hep.dataforge.meta.MetaRepr
|
||||
import hep.dataforge.misc.Named
|
||||
import hep.dataforge.misc.Type
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.provider.Type
|
||||
import hep.dataforge.values.Value
|
||||
import kotlinx.io.*
|
||||
import kotlinx.io.buffer.Buffer
|
||||
import kotlinx.io.pool.ObjectPool
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
/**
|
||||
* And interface for reading and writing objects into with IO streams
|
||||
*/
|
||||
public interface IOFormat<T : Any> : MetaRepr {
|
||||
public val type: KType
|
||||
|
||||
public fun writeObject(output: Output, obj: T)
|
||||
public fun readObject(input: Input): T
|
||||
|
||||
@ -42,10 +45,14 @@ public fun <T : Any> Binary.readWith(format: IOFormat<T>): T = read {
|
||||
public fun <T : Any> Output.writeWith(format: IOFormat<T>, obj: T): Unit =
|
||||
format.run { writeObject(this@writeWith, obj) }
|
||||
|
||||
public class ListIOFormat<T : Any>(public val format: IOFormat<T>) : IOFormat<List<T>> {
|
||||
public inline fun <reified T : Any> IOFormat.Companion.listOf(
|
||||
format: IOFormat<T>,
|
||||
): IOFormat<List<T>> = object : IOFormat<List<T>> {
|
||||
override val type: KType = typeOf<List<T>>()
|
||||
|
||||
override fun writeObject(output: Output, obj: List<T>) {
|
||||
output.writeInt(obj.size)
|
||||
this.format.run {
|
||||
format.run {
|
||||
obj.forEach {
|
||||
writeObject(output, it)
|
||||
}
|
||||
@ -63,9 +70,8 @@ public class ListIOFormat<T : Any>(public val format: IOFormat<T>) : IOFormat<Li
|
||||
NAME_KEY put "list"
|
||||
"contentFormat" put format.toMeta()
|
||||
}
|
||||
}
|
||||
|
||||
//public val <T : Any> IOFormat<T>.list: ListIOFormat<T> get() = ListIOFormat(this)
|
||||
}
|
||||
|
||||
public fun ObjectPool<Buffer>.fill(block: Buffer.() -> Unit): Buffer {
|
||||
val buffer = borrow()
|
||||
@ -82,7 +88,7 @@ public interface IOFormatFactory<T : Any> : Factory<IOFormat<T>>, Named, MetaRep
|
||||
/**
|
||||
* Explicit type for dynamic type checks
|
||||
*/
|
||||
public val type: KClass<out T>
|
||||
public val type: KType
|
||||
|
||||
override fun toMeta(): Meta = Meta {
|
||||
NAME_KEY put name.toString()
|
||||
@ -100,7 +106,7 @@ public object DoubleIOFormat : IOFormat<Double>, IOFormatFactory<Double> {
|
||||
|
||||
override val name: Name = "double".asName()
|
||||
|
||||
override val type: KClass<out Double> get() = Double::class
|
||||
override val type: KType get() = typeOf<Double>()
|
||||
|
||||
override fun writeObject(output: Output, obj: kotlin.Double) {
|
||||
output.writeDouble(obj)
|
||||
@ -114,14 +120,14 @@ public object ValueIOFormat : IOFormat<Value>, IOFormatFactory<Value> {
|
||||
|
||||
override val name: Name = "value".asName()
|
||||
|
||||
override val type: KClass<out Value> get() = Value::class
|
||||
override val type: KType get() = typeOf<Value>()
|
||||
|
||||
override fun writeObject(output: Output, obj: Value) {
|
||||
BinaryMetaFormat.run { output.writeValue(obj) }
|
||||
}
|
||||
|
||||
override fun readObject(input: Input): Value {
|
||||
return (BinaryMetaFormat.run { input.readMetaItem() } as? MetaItem.ValueItem)?.value
|
||||
return (BinaryMetaFormat.run { input.readMetaItem() } as? MetaItemValue)?.value
|
||||
?: error("The item is not a value")
|
||||
}
|
||||
}
|
@ -18,7 +18,7 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
|
||||
context.gather<IOFormatFactory<*>>(IO_FORMAT_TYPE).values
|
||||
}
|
||||
|
||||
public fun <T : Any> resolveIOFormat(item: MetaItem<*>, type: KClass<out T>): IOFormat<T>? {
|
||||
public fun <T : Any> resolveIOFormat(item: MetaItem, type: KClass<out T>): IOFormat<T>? {
|
||||
val key = item.string ?: item.node[NAME_KEY]?.string ?: error("Format name not defined")
|
||||
val name = key.toName()
|
||||
return ioFormatFactories.find { it.name == name }?.let {
|
||||
@ -46,7 +46,7 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
|
||||
private fun resolveEnvelopeFormat(name: Name, meta: Meta = Meta.EMPTY): EnvelopeFormat? =
|
||||
envelopeFormatFactories.find { it.name == name }?.invoke(meta, context)
|
||||
|
||||
public fun resolveEnvelopeFormat(item: MetaItem<*>): EnvelopeFormat? {
|
||||
public fun resolveEnvelopeFormat(item: MetaItem): EnvelopeFormat? {
|
||||
val name = item.string ?: item.node[NAME_KEY]?.string ?: error("Envelope format name not defined")
|
||||
val meta = item.node[META_KEY].node ?: Meta.EMPTY
|
||||
return resolveEnvelopeFormat(name.toName(), meta)
|
||||
|
@ -16,12 +16,16 @@ import kotlinx.io.text.readUtf8String
|
||||
import kotlinx.io.text.writeUtf8String
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
/**
|
||||
* A Json format for Meta representation
|
||||
*/
|
||||
public class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat {
|
||||
|
||||
override val type: KType get() = typeOf<Meta>()
|
||||
|
||||
override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?) {
|
||||
val jsonObject = meta.toJson(descriptor)
|
||||
output.writeUtf8String(json.encodeToString(JsonObject.serializer(), jsonObject))
|
||||
|
@ -4,20 +4,22 @@ import hep.dataforge.context.Context
|
||||
import hep.dataforge.io.MetaFormatFactory.Companion.META_FORMAT_TYPE
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.descriptors.NodeDescriptor
|
||||
import hep.dataforge.misc.Type
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.names.plus
|
||||
import hep.dataforge.provider.Type
|
||||
import kotlinx.io.ByteArrayInput
|
||||
import kotlinx.io.Input
|
||||
import kotlinx.io.Output
|
||||
import kotlinx.io.use
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
/**
|
||||
* A format for meta serialization
|
||||
*/
|
||||
public interface MetaFormat : IOFormat<Meta> {
|
||||
override val type: KType get() = typeOf<Meta>()
|
||||
|
||||
override fun writeObject(output: Output, obj: Meta) {
|
||||
writeMeta(output, obj, null)
|
||||
@ -40,7 +42,7 @@ public interface MetaFormatFactory : IOFormatFactory<Meta>, MetaFormat {
|
||||
|
||||
override val name: Name get() = "meta".asName() + shortName
|
||||
|
||||
override val type: KClass<out Meta> get() = Meta::class
|
||||
override val type: KType get() = typeOf<Meta>()
|
||||
|
||||
public val key: Short get() = name.hashCode().toShort()
|
||||
|
||||
|
@ -7,7 +7,7 @@ import kotlin.test.assertEquals
|
||||
|
||||
|
||||
class EnvelopeFormatTest {
|
||||
val envelope = Envelope.invoke {
|
||||
val envelope = Envelope {
|
||||
type = "test.format"
|
||||
meta{
|
||||
"d" put 22.2
|
||||
|
@ -2,6 +2,8 @@ package hep.dataforge.io
|
||||
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.meta.JsonMeta.Companion.JSON_ARRAY_KEY
|
||||
import hep.dataforge.values.ListValue
|
||||
import hep.dataforge.values.number
|
||||
import kotlinx.io.asBinary
|
||||
import kotlinx.serialization.json.*
|
||||
import kotlin.test.Test
|
||||
@ -78,4 +80,27 @@ class MetaFormatTest {
|
||||
assertEquals(listOf(1.0, 2.0, 3.0), meta["$JSON_ARRAY_KEY[2"].value?.list?.map { it.number.toDouble() })
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testJsonStringToMeta(){
|
||||
val jsonString = """
|
||||
{
|
||||
"comments": [
|
||||
],
|
||||
"end_time": "2018-04-13T22:01:46",
|
||||
"format_description": "https://docs.google.com/document/d/12qmnZRO55y6zr08Wf-BQYAmklqgf5y3j_gD_VkNscXc/edit?usp=sharing",
|
||||
"iteration_info": {
|
||||
"iteration": 4,
|
||||
"reverse": false
|
||||
},
|
||||
"operator": "Vasiliy",
|
||||
"programm_revision": "1.1.1-79-g7c0cad6",
|
||||
"start_time": "2018-04-13T21:42:04",
|
||||
"type": "info_file"
|
||||
}
|
||||
""".trimIndent()
|
||||
val json = Json.parseToJsonElement(jsonString)
|
||||
val meta = json.toMetaItem().node!!
|
||||
assertEquals(ListValue.EMPTY, meta["comments"].value)
|
||||
}
|
||||
|
||||
}
|
@ -1,8 +1,8 @@
|
||||
package hep.dataforge.io
|
||||
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaItem
|
||||
import hep.dataforge.meta.MetaSerializer
|
||||
import hep.dataforge.meta.TypedMetaItem
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.toName
|
||||
import kotlinx.serialization.ExperimentalSerializationApi
|
||||
@ -52,7 +52,7 @@ class MetaSerializerTest {
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
@Test
|
||||
fun testMetaItemDescriptor() {
|
||||
val descriptor = MetaItem.serializer(MetaSerializer).descriptor.getElementDescriptor(0)
|
||||
val descriptor = TypedMetaItem.serializer(MetaSerializer).descriptor.getElementDescriptor(0)
|
||||
println(descriptor)
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
package hep.dataforge.io
|
||||
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.meta.get
|
||||
import hep.dataforge.meta.int
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import kotlinx.io.text.writeUtf8String
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
@ -1,14 +1,15 @@
|
||||
package hep.dataforge.io
|
||||
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.descriptors.NodeDescriptor
|
||||
import hep.dataforge.meta.isEmpty
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import kotlinx.io.*
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.StandardOpenOption
|
||||
import kotlin.reflect.full.isSuperclassOf
|
||||
import kotlin.reflect.full.isSupertypeOf
|
||||
import kotlin.reflect.typeOf
|
||||
import kotlin.streams.asSequence
|
||||
|
||||
public fun <R> Path.read(block: Input.() -> R): R = asBinary().read(block = block)
|
||||
@ -59,7 +60,7 @@ public fun Path.readEnvelope(format: EnvelopeFormat): Envelope {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@DFExperimental
|
||||
public inline fun <reified T : Any> IOPlugin.resolveIOFormat(): IOFormat<T>? {
|
||||
return ioFormatFactories.find { it.type.isSuperclassOf(T::class) } as IOFormat<T>?
|
||||
return ioFormatFactories.find { it.type.isSupertypeOf(typeOf<T>())} as IOFormat<T>?
|
||||
}
|
||||
|
||||
/**
|
||||
@ -115,18 +116,18 @@ public fun IOPlugin.writeMetaFile(
|
||||
* Return inferred [EnvelopeFormat] if only one format could read given file. If no format accepts file, return null. If
|
||||
* multiple formats accepts file, throw an error.
|
||||
*/
|
||||
public fun IOPlugin.peekBinaryFormat(path: Path): EnvelopeFormat? {
|
||||
public fun IOPlugin.peekFileEnvelopeFormat(path: Path): EnvelopeFormat? {
|
||||
val binary = path.asBinary()
|
||||
val formats = envelopeFormatFactories.mapNotNull { factory ->
|
||||
binary.read {
|
||||
factory.peekFormat(this@peekBinaryFormat, this@read)
|
||||
factory.peekFormat(this@peekFileEnvelopeFormat, this@read)
|
||||
}
|
||||
}
|
||||
|
||||
return when (formats.size) {
|
||||
0 -> null
|
||||
1 -> formats.first()
|
||||
else -> error("Envelope format binary recognition clash")
|
||||
else -> error("Envelope format binary recognition clash: $formats")
|
||||
}
|
||||
}
|
||||
|
||||
@ -137,10 +138,10 @@ public val IOPlugin.Companion.DATA_FILE_NAME: String get() = "@data"
|
||||
* Read and envelope from file if the file exists, return null if file does not exist.
|
||||
*
|
||||
* If file is directory, then expect two files inside:
|
||||
* * **meta.<format name>** for meta
|
||||
* * **meta.<meta format extension>** for meta
|
||||
* * **data** for data
|
||||
*
|
||||
* If the file is envelope read it using [EnvelopeFormatFactory.peekFormat] functionality to infer format.
|
||||
* If the file is envelope read it using [EnvelopeFormatFactory.peekFormat] functionality to infer format (if not overridden with [formatPicker]).
|
||||
*
|
||||
* If the file is not an envelope and [readNonEnvelopes] is true, return an Envelope without meta, using file as binary.
|
||||
*
|
||||
@ -150,9 +151,9 @@ public val IOPlugin.Companion.DATA_FILE_NAME: String get() = "@data"
|
||||
public fun IOPlugin.readEnvelopeFile(
|
||||
path: Path,
|
||||
readNonEnvelopes: Boolean = false,
|
||||
formatPeeker: IOPlugin.(Path) -> EnvelopeFormat? = IOPlugin::peekBinaryFormat,
|
||||
): Envelope? {
|
||||
if (!Files.exists(path)) return null
|
||||
formatPicker: IOPlugin.(Path) -> EnvelopeFormat? = IOPlugin::peekFileEnvelopeFormat,
|
||||
): Envelope {
|
||||
if (!Files.exists(path)) error("File with path $path does not exist")
|
||||
|
||||
//read two-files directory
|
||||
if (Files.isDirectory(path)) {
|
||||
@ -177,11 +178,11 @@ public fun IOPlugin.readEnvelopeFile(
|
||||
return SimpleEnvelope(meta, data)
|
||||
}
|
||||
|
||||
return formatPeeker(path)?.let { format ->
|
||||
return formatPicker(path)?.let { format ->
|
||||
path.readEnvelope(format)
|
||||
} ?: if (readNonEnvelopes) { // if no format accepts file, read it as binary
|
||||
SimpleEnvelope(Meta.EMPTY, path.asBinary())
|
||||
} else null
|
||||
} else error("Can't infer format for file $path")
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1,7 +1,7 @@
|
||||
package hep.dataforge.io
|
||||
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import kotlinx.io.asBinary
|
||||
import kotlinx.io.toByteArray
|
||||
import kotlinx.io.writeDouble
|
||||
@ -54,7 +54,7 @@ class FileBinaryTest {
|
||||
val tmpPath = Files.createTempFile("dataforge_test", ".df")
|
||||
Global.io.writeEnvelopeFile(tmpPath, envelope)
|
||||
|
||||
val binary = Global.io.readEnvelopeFile(tmpPath)?.data!!
|
||||
val binary = Global.io.readEnvelopeFile(tmpPath).data!!
|
||||
assertEquals(binary.size, binary.toByteArray().size)
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
package hep.dataforge.io
|
||||
|
||||
import hep.dataforge.context.Global
|
||||
import hep.dataforge.meta.DFExperimental
|
||||
import hep.dataforge.misc.DFExperimental
|
||||
import kotlinx.io.writeDouble
|
||||
import java.nio.file.Files
|
||||
import kotlin.test.Test
|
||||
@ -29,7 +29,7 @@ class FileEnvelopeTest {
|
||||
val tmpPath = Files.createTempFile("dataforge_test", ".df")
|
||||
writeEnvelopeFile(tmpPath, envelope)
|
||||
println(tmpPath.toUri())
|
||||
val restored: Envelope = readEnvelopeFile(tmpPath)!!
|
||||
val restored: Envelope = readEnvelopeFile(tmpPath)
|
||||
assertTrue { envelope.contentEquals(restored) }
|
||||
}
|
||||
}
|
||||
@ -40,7 +40,7 @@ class FileEnvelopeTest {
|
||||
val tmpPath = Files.createTempFile("dataforge_test_tagless", ".df")
|
||||
writeEnvelopeFile(tmpPath, envelope, envelopeFormat = TaglessEnvelopeFormat)
|
||||
println(tmpPath.toUri())
|
||||
val restored: Envelope = readEnvelopeFile(tmpPath)!!
|
||||
val restored: Envelope = readEnvelopeFile(tmpPath)
|
||||
assertTrue { envelope.contentEquals(restored) }
|
||||
}
|
||||
}
|
||||
|
@ -1,20 +1,18 @@
|
||||
public abstract class hep/dataforge/meta/AbstractMetaNode : hep/dataforge/meta/MetaBase, hep/dataforge/meta/MetaNode {
|
||||
public fun <init> ()V
|
||||
public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
|
||||
public fun toMeta ()Lhep/dataforge/meta/Meta;
|
||||
}
|
||||
|
||||
public abstract class hep/dataforge/meta/AbstractMutableMeta : hep/dataforge/meta/AbstractMetaNode, hep/dataforge/meta/MutableMeta {
|
||||
public abstract class hep/dataforge/meta/AbstractMutableMeta : hep/dataforge/meta/AbstractTypedMeta, hep/dataforge/meta/MutableMeta {
|
||||
public fun <init> ()V
|
||||
protected final fun getChildren ()Ljava/util/Map;
|
||||
public fun getItems ()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;
|
||||
protected fun replaceItem (Lhep/dataforge/names/NameToken;Lhep/dataforge/meta/TypedMetaItem;Lhep/dataforge/meta/TypedMetaItem;)V
|
||||
public fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/TypedMetaItem;)V
|
||||
protected abstract fun wrapNode (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MutableMeta;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/Config : hep/dataforge/meta/AbstractMutableMeta, hep/dataforge/meta/ObservableMeta {
|
||||
public abstract class hep/dataforge/meta/AbstractTypedMeta : hep/dataforge/meta/MetaBase, hep/dataforge/meta/TypedMeta {
|
||||
public fun <init> ()V
|
||||
public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/Config : hep/dataforge/meta/AbstractMutableMeta, hep/dataforge/meta/ObservableItemProvider {
|
||||
public static final field ConfigSerializer Lhep/dataforge/meta/Config$ConfigSerializer;
|
||||
public fun <init> ()V
|
||||
public synthetic fun empty$dataforge_meta ()Lhep/dataforge/meta/MutableMeta;
|
||||
@ -35,7 +33,8 @@ public final class hep/dataforge/meta/Config$ConfigSerializer : kotlinx/serializ
|
||||
|
||||
public final class hep/dataforge/meta/ConfigKt {
|
||||
public static final fun asConfig (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Config;
|
||||
public static final fun get (Lhep/dataforge/meta/Config;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/MetaItem;
|
||||
public static final fun get (Lhep/dataforge/meta/Config;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static final fun toConfig (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Config;
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/meta/Configurable {
|
||||
@ -49,19 +48,6 @@ public final class hep/dataforge/meta/ConfigurableKt {
|
||||
public static final fun configure (Lhep/dataforge/meta/Configurable;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Configurable;
|
||||
}
|
||||
|
||||
public abstract interface annotation class hep/dataforge/meta/DFBuilder : java/lang/annotation/Annotation {
|
||||
}
|
||||
|
||||
public abstract interface annotation class hep/dataforge/meta/DFExperimental : java/lang/annotation/Annotation {
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/GetIndexedKt {
|
||||
public static final fun getIndexed (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)Ljava/util/Map;
|
||||
public static final fun getIndexed (Lhep/dataforge/meta/Meta;Ljava/lang/String;)Ljava/util/Map;
|
||||
public static final fun getIndexed (Lhep/dataforge/meta/MetaNode;Lhep/dataforge/names/Name;)Ljava/util/Map;
|
||||
public static final fun getIndexed (Lhep/dataforge/meta/MetaNode;Ljava/lang/String;)Ljava/util/Map;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/ItemDelegateKt {
|
||||
public static final fun boolean (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadOnlyProperty;
|
||||
public static final fun boolean (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadOnlyProperty;
|
||||
@ -108,15 +94,41 @@ public final class hep/dataforge/meta/ItemDelegateKt {
|
||||
public static synthetic fun value$default (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadOnlyProperty;
|
||||
}
|
||||
|
||||
public final class hep/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;)Lhep/dataforge/meta/ItemListener;
|
||||
public static synthetic fun copy$default (Lhep/dataforge/meta/ItemListener;Ljava/lang/Object;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/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 hep/dataforge/meta/ItemProvider {
|
||||
public static final field Companion Lhep/dataforge/meta/ItemProvider$Companion;
|
||||
public abstract fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
|
||||
public abstract fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/ItemProvider$Companion {
|
||||
public final fun getEMPTY ()Lhep/dataforge/meta/ItemProvider;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/ItemProviderKt {
|
||||
public static final fun get (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static final fun get (Lhep/dataforge/meta/ItemProvider;Ljava/lang/String;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static final fun getChild (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/ItemProvider;
|
||||
public static final fun getChild (Lhep/dataforge/meta/ItemProvider;Ljava/lang/String;)Lhep/dataforge/meta/ItemProvider;
|
||||
public static final fun getIndexed (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/names/Name;)Ljava/util/Map;
|
||||
public static final fun getIndexed (Lhep/dataforge/meta/ItemProvider;Ljava/lang/String;)Ljava/util/Map;
|
||||
public static final fun getRootItem (Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static final fun getRootNode (Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Meta;
|
||||
public static final fun withDefault (Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/ItemProvider;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/JsonMeta : hep/dataforge/meta/MetaBase {
|
||||
public static final field Companion Lhep/dataforge/meta/JsonMeta$Companion;
|
||||
public static final field JSON_ARRAY_KEY Ljava/lang/String;
|
||||
@ -135,8 +147,8 @@ public final class hep/dataforge/meta/JsonMetaKt {
|
||||
public static synthetic fun toJson$default (Lhep/dataforge/values/Value;Lhep/dataforge/meta/descriptors/ValueDescriptor;ILjava/lang/Object;)Lkotlinx/serialization/json/JsonElement;
|
||||
public static final fun toMeta (Lkotlinx/serialization/json/JsonObject;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/JsonMeta;
|
||||
public static synthetic fun toMeta$default (Lkotlinx/serialization/json/JsonObject;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Lhep/dataforge/meta/JsonMeta;
|
||||
public static final fun toMetaItem (Lkotlinx/serialization/json/JsonElement;Lhep/dataforge/meta/descriptors/ItemDescriptor;)Lhep/dataforge/meta/MetaItem;
|
||||
public static synthetic fun toMetaItem$default (Lkotlinx/serialization/json/JsonElement;Lhep/dataforge/meta/descriptors/ItemDescriptor;ILjava/lang/Object;)Lhep/dataforge/meta/MetaItem;
|
||||
public static final fun toMetaItem (Lkotlinx/serialization/json/JsonElement;Lhep/dataforge/meta/descriptors/ItemDescriptor;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static synthetic fun toMetaItem$default (Lkotlinx/serialization/json/JsonElement;Lhep/dataforge/meta/descriptors/ItemDescriptor;ILjava/lang/Object;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static final fun toValue (Lkotlinx/serialization/json/JsonPrimitive;Lhep/dataforge/meta/descriptors/ValueDescriptor;)Lhep/dataforge/values/Value;
|
||||
}
|
||||
|
||||
@ -155,7 +167,7 @@ public final class hep/dataforge/meta/Laminate$Companion {
|
||||
|
||||
public final class hep/dataforge/meta/LaminateKt {
|
||||
public static final fun Laminate ([Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Laminate;
|
||||
public static final fun getFirst (Lhep/dataforge/meta/Laminate;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
|
||||
public static final fun getFirst (Lhep/dataforge/meta/Laminate;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static final fun withBottom (Lhep/dataforge/meta/Laminate;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Laminate;
|
||||
public static final fun withTop (Lhep/dataforge/meta/Laminate;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Laminate;
|
||||
}
|
||||
@ -172,7 +184,7 @@ public abstract interface class hep/dataforge/meta/Meta : hep/dataforge/meta/Ite
|
||||
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 getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public abstract fun getItems ()Ljava/util/Map;
|
||||
public abstract fun hashCode ()I
|
||||
public abstract fun toMeta ()Lhep/dataforge/meta/Meta;
|
||||
@ -186,14 +198,14 @@ public final class hep/dataforge/meta/Meta$Companion {
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/Meta$DefaultImpls {
|
||||
public static fun getItem (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
|
||||
public static fun getItem (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static fun toMeta (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Meta;
|
||||
}
|
||||
|
||||
public abstract class hep/dataforge/meta/MetaBase : hep/dataforge/meta/Meta {
|
||||
public fun <init> ()V
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
|
||||
public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public fun hashCode ()I
|
||||
public fun toMeta ()Lhep/dataforge/meta/Meta;
|
||||
public fun toString ()Ljava/lang/String;
|
||||
@ -211,8 +223,8 @@ public final class hep/dataforge/meta/MetaBuilder : hep/dataforge/meta/AbstractM
|
||||
public final fun put (Lhep/dataforge/names/Name;Ljava/lang/String;)V
|
||||
public final fun put (Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)V
|
||||
public final fun put (Ljava/lang/String;Lhep/dataforge/meta/Meta;)V
|
||||
public final fun put (Ljava/lang/String;Lhep/dataforge/meta/MetaItem;)V
|
||||
public final fun put (Ljava/lang/String;Lhep/dataforge/meta/MetaRepr;)V
|
||||
public final fun put (Ljava/lang/String;Lhep/dataforge/meta/TypedMetaItem;)V
|
||||
public final fun put (Ljava/lang/String;Lhep/dataforge/values/Value;)V
|
||||
public final fun put (Ljava/lang/String;Ljava/lang/Boolean;)V
|
||||
public final fun put (Ljava/lang/String;Ljava/lang/Enum;)V
|
||||
@ -231,23 +243,27 @@ public final class hep/dataforge/meta/MetaBuilder : hep/dataforge/meta/AbstractM
|
||||
|
||||
public final class hep/dataforge/meta/MetaBuilderKt {
|
||||
public static final fun Meta (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MetaBuilder;
|
||||
public static final fun builder (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MetaBuilder;
|
||||
public static final fun edit (Lhep/dataforge/meta/Meta;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MetaBuilder;
|
||||
public static final fun toMutableMeta (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MetaBuilder;
|
||||
}
|
||||
|
||||
public abstract class hep/dataforge/meta/MetaItem {
|
||||
public static final field Companion Lhep/dataforge/meta/MetaItem$Companion;
|
||||
public abstract fun equals (Ljava/lang/Object;)Z
|
||||
public abstract fun hashCode ()I
|
||||
public final class hep/dataforge/meta/MetaItemKt {
|
||||
public static final fun asMetaItem (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MetaItemNode;
|
||||
public static final fun asMetaItem (Lhep/dataforge/values/Value;)Lhep/dataforge/meta/MetaItemValue;
|
||||
public static final fun getBoolean (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Boolean;
|
||||
public static final fun getDouble (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Double;
|
||||
public static final fun getFloat (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Float;
|
||||
public static final fun getInt (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Integer;
|
||||
public static final fun getLong (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Long;
|
||||
public static final fun getNode (Lhep/dataforge/meta/TypedMetaItem;)Lhep/dataforge/meta/Meta;
|
||||
public static final fun getNumber (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Number;
|
||||
public static final fun getShort (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Short;
|
||||
public static final fun getString (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/String;
|
||||
public static final fun getStringList (Lhep/dataforge/meta/TypedMetaItem;)Ljava/util/List;
|
||||
public static final fun getValue (Lhep/dataforge/meta/TypedMetaItem;)Lhep/dataforge/values/Value;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/MetaItem$Companion {
|
||||
public final fun of (Ljava/lang/Object;)Lhep/dataforge/meta/MetaItem;
|
||||
public final fun serializer (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/MetaItem$NodeItem : hep/dataforge/meta/MetaItem {
|
||||
public static final field Companion Lhep/dataforge/meta/MetaItem$NodeItem$Companion;
|
||||
public final class hep/dataforge/meta/MetaItemNode : hep/dataforge/meta/TypedMetaItem {
|
||||
public static final field Companion Lhep/dataforge/meta/MetaItemNode$Companion;
|
||||
public fun <init> (Lhep/dataforge/meta/Meta;)V
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getNode ()Lhep/dataforge/meta/Meta;
|
||||
@ -255,12 +271,21 @@ public final class hep/dataforge/meta/MetaItem$NodeItem : hep/dataforge/meta/Met
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/MetaItem$NodeItem$Companion {
|
||||
public final class hep/dataforge/meta/MetaItemNode$Companion {
|
||||
public final fun serializer (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/MetaItem$ValueItem : hep/dataforge/meta/MetaItem {
|
||||
public static final field Companion Lhep/dataforge/meta/MetaItem$ValueItem$Companion;
|
||||
public final class hep/dataforge/meta/MetaItemSerializer : kotlinx/serialization/KSerializer {
|
||||
public static final field INSTANCE Lhep/dataforge/meta/MetaItemSerializer;
|
||||
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/meta/TypedMetaItem;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/MetaItemValue : hep/dataforge/meta/TypedMetaItem {
|
||||
public static final field Companion Lhep/dataforge/meta/MetaItemValue$Companion;
|
||||
public fun <init> (Lhep/dataforge/values/Value;)V
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getValue ()Lhep/dataforge/values/Value;
|
||||
@ -268,68 +293,16 @@ public final class hep/dataforge/meta/MetaItem$ValueItem : hep/dataforge/meta/Me
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/MetaItem$ValueItem$Companion {
|
||||
public final class hep/dataforge/meta/MetaItemValue$Companion {
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/MetaItemSerializer : kotlinx/serialization/KSerializer {
|
||||
public static final field INSTANCE Lhep/dataforge/meta/MetaItemSerializer;
|
||||
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/meta/MetaItem;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/meta/MetaItem;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/MetaKt {
|
||||
public static final fun asMetaItem (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/MetaItem$NodeItem;
|
||||
public static final fun asMetaItem (Lhep/dataforge/values/Value;)Lhep/dataforge/meta/MetaItem$ValueItem;
|
||||
public static final fun get (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
|
||||
public static final fun get (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/MetaItem;
|
||||
public static final fun get (Lhep/dataforge/meta/Meta;Ljava/lang/String;)Lhep/dataforge/meta/MetaItem;
|
||||
public static final fun get (Lhep/dataforge/meta/MetaNode;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
|
||||
public static final fun get (Lhep/dataforge/meta/MetaNode;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/MetaItem;
|
||||
public static final fun get (Lhep/dataforge/meta/MetaNode;Ljava/lang/String;)Lhep/dataforge/meta/MetaItem;
|
||||
public static final fun getBoolean (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Boolean;
|
||||
public static final fun getDouble (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Double;
|
||||
public static final fun getFloat (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Float;
|
||||
public static final fun getInt (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Integer;
|
||||
public static final fun getLong (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Long;
|
||||
public static final fun getNode (Lhep/dataforge/meta/MetaItem;)Lhep/dataforge/meta/Meta;
|
||||
public static final fun getNumber (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Number;
|
||||
public static final fun getShort (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Short;
|
||||
public static final fun getString (Lhep/dataforge/meta/MetaItem;)Ljava/lang/String;
|
||||
public static final fun getStringList (Lhep/dataforge/meta/MetaItem;)Ljava/util/List;
|
||||
public static final fun getValue (Lhep/dataforge/meta/MetaItem;)Lhep/dataforge/values/Value;
|
||||
public static final fun get (Lhep/dataforge/meta/Meta;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static final fun isEmpty (Lhep/dataforge/meta/Meta;)Z
|
||||
public static final fun itemSequence (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
|
||||
public static final fun iterator (Lhep/dataforge/meta/Meta;)Ljava/util/Iterator;
|
||||
public static final fun seal (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/SealedMeta;
|
||||
public static final fun seal (Lhep/dataforge/meta/MetaItem;)Lhep/dataforge/meta/MetaItem;
|
||||
public static final fun sequence (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
|
||||
public static final fun values (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/MetaListener {
|
||||
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;)Lhep/dataforge/meta/MetaListener;
|
||||
public static synthetic fun copy$default (Lhep/dataforge/meta/MetaListener;Ljava/lang/Object;Lkotlin/jvm/functions/Function3;ILjava/lang/Object;)Lhep/dataforge/meta/MetaListener;
|
||||
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 hep/dataforge/meta/MetaNode : hep/dataforge/meta/Meta {
|
||||
public abstract fun getItems ()Ljava/util/Map;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/MetaNode$DefaultImpls {
|
||||
public static fun getItem (Lhep/dataforge/meta/MetaNode;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
|
||||
public static fun toMeta (Lhep/dataforge/meta/MetaNode;)Lhep/dataforge/meta/Meta;
|
||||
public static final fun valueSequence (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/meta/MetaRepr {
|
||||
@ -345,18 +318,6 @@ 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;
|
||||
@ -389,6 +350,8 @@ public final class hep/dataforge/meta/MutableItemDelegateKt {
|
||||
public static final fun long (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
|
||||
public static synthetic fun long$default (Lhep/dataforge/meta/MutableItemProvider;JLhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
|
||||
public static synthetic fun long$default (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;ILjava/lang/Object;)Lkotlin/properties/ReadWriteProperty;
|
||||
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 number (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
|
||||
public static final fun number (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function0;)Lkotlin/properties/ReadWriteProperty;
|
||||
public static final fun number (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/Number;Lhep/dataforge/names/Name;)Lkotlin/properties/ReadWriteProperty;
|
||||
@ -414,18 +377,23 @@ public final class hep/dataforge/meta/MutableItemDelegateKt {
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/meta/MutableItemProvider : hep/dataforge/meta/ItemProvider {
|
||||
public abstract fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)V
|
||||
public abstract fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/TypedMetaItem;)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 editChild (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
public static final fun getChild (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
public static final fun getChild (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
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;Lhep/dataforge/meta/Meta;)V
|
||||
public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lhep/dataforge/meta/TypedMetaItem;)V
|
||||
public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Lhep/dataforge/values/Value;)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;Lhep/dataforge/meta/Meta;)V
|
||||
public static final fun set (Lhep/dataforge/meta/MutableItemProvider;Ljava/lang/String;Lhep/dataforge/meta/TypedMetaItem;)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
|
||||
@ -433,108 +401,126 @@ public final class hep/dataforge/meta/MutableItemProviderKt {
|
||||
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 static final fun update (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Meta;)V
|
||||
public static final fun withDefault (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/meta/MutableMeta : hep/dataforge/meta/MetaNode, hep/dataforge/meta/MutableItemProvider {
|
||||
public abstract interface class hep/dataforge/meta/MutableMeta : hep/dataforge/meta/MutableItemProvider, hep/dataforge/meta/TypedMeta {
|
||||
public abstract fun getItems ()Ljava/util/Map;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/MutableMeta$DefaultImpls {
|
||||
public static fun getItem (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
|
||||
public static fun getItem (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static fun toMeta (Lhep/dataforge/meta/MutableMeta;)Lhep/dataforge/meta/Meta;
|
||||
}
|
||||
|
||||
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 append (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/names/Name;Ljava/lang/Object;)V
|
||||
public static final fun append (Lhep/dataforge/meta/MutableItemProvider;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 update (Lhep/dataforge/meta/MutableMeta;Lhep/dataforge/meta/Meta;)V
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/meta/ObservableMeta : hep/dataforge/meta/Meta {
|
||||
public abstract interface class hep/dataforge/meta/ObservableItemProvider : hep/dataforge/meta/ItemProvider {
|
||||
public abstract fun onChange (Ljava/lang/Object;Lkotlin/jvm/functions/Function3;)V
|
||||
public abstract fun removeListener (Ljava/lang/Object;)V
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/ObservableMeta$DefaultImpls {
|
||||
public static fun getItem (Lhep/dataforge/meta/ObservableMeta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
|
||||
public static fun toMeta (Lhep/dataforge/meta/ObservableMeta;)Lhep/dataforge/meta/Meta;
|
||||
public abstract interface class hep/dataforge/meta/ReadOnlySpecification {
|
||||
public abstract fun empty ()Lhep/dataforge/meta/ItemProvider;
|
||||
public abstract fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/ItemProvider;
|
||||
public abstract fun read (Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/ItemProvider;
|
||||
}
|
||||
|
||||
public class hep/dataforge/meta/Scheme : hep/dataforge/meta/Configurable, hep/dataforge/meta/MetaRepr, hep/dataforge/meta/MutableItemProvider, hep/dataforge/meta/descriptors/Described {
|
||||
public final class hep/dataforge/meta/ReadOnlySpecification$DefaultImpls {
|
||||
public static fun invoke (Lhep/dataforge/meta/ReadOnlySpecification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/ItemProvider;
|
||||
}
|
||||
|
||||
public class hep/dataforge/meta/Scheme : hep/dataforge/meta/MetaRepr, hep/dataforge/meta/MutableItemProvider, hep/dataforge/meta/descriptors/Described {
|
||||
public fun <init> ()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 final fun getDefaultItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/MetaItem;
|
||||
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 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 final fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
|
||||
public fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public final fun setDescriptor (Lhep/dataforge/meta/descriptors/NodeDescriptor;)V
|
||||
public fun setItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/TypedMetaItem;)V
|
||||
public fun toMeta ()Lhep/dataforge/meta/Laminate;
|
||||
public synthetic fun toMeta ()Lhep/dataforge/meta/Meta;
|
||||
public final fun validateItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
|
||||
public fun validateItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/TypedMetaItem;)Z
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/SchemeKt {
|
||||
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/MutableItemProvider;
|
||||
public static synthetic fun toScheme$default (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
public static final fun isEmpty (Lhep/dataforge/meta/Scheme;)Z
|
||||
public static final fun retarget (Lhep/dataforge/meta/Scheme;Lhep/dataforge/meta/MutableItemProvider;)Lhep/dataforge/meta/Scheme;
|
||||
public static final fun wrap (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Scheme;
|
||||
public static synthetic fun wrap$default (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/ItemProvider;Lhep/dataforge/meta/descriptors/NodeDescriptor;ILjava/lang/Object;)Lhep/dataforge/meta/Scheme;
|
||||
}
|
||||
|
||||
public class hep/dataforge/meta/SchemeSpec : hep/dataforge/meta/Specification, hep/dataforge/meta/descriptors/Described {
|
||||
public fun <init> (Lkotlin/jvm/functions/Function0;)V
|
||||
public fun <init> (Lkotlin/jvm/functions/Function3;)V
|
||||
public synthetic fun empty ()Lhep/dataforge/meta/MutableItemProvider;
|
||||
public synthetic fun empty ()Lhep/dataforge/meta/ItemProvider;
|
||||
public fun empty ()Lhep/dataforge/meta/Scheme;
|
||||
public synthetic fun getDescriptor ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
|
||||
public fun getDescriptor ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
|
||||
public synthetic fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
public synthetic fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/ItemProvider;
|
||||
public final fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/Scheme;
|
||||
public synthetic fun read (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
public fun read (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
|
||||
public synthetic fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
public fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
|
||||
public synthetic fun read (Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/ItemProvider;
|
||||
public fun read (Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
|
||||
public synthetic fun write (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
public fun write (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/Scheme;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/SealedMeta : hep/dataforge/meta/AbstractMetaNode {
|
||||
public final class hep/dataforge/meta/SealedMeta : hep/dataforge/meta/AbstractTypedMeta {
|
||||
public fun getItems ()Ljava/util/Map;
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/meta/Specification {
|
||||
public abstract fun empty ()Lhep/dataforge/meta/MutableItemProvider;
|
||||
public abstract fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
public abstract fun read (Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
public abstract fun wrap (Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
public final class hep/dataforge/meta/SealedMetaKt {
|
||||
public static final fun seal (Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/SealedMeta;
|
||||
public static final fun seal (Lhep/dataforge/meta/TypedMetaItem;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/meta/Specification : hep/dataforge/meta/ReadOnlySpecification {
|
||||
public abstract fun write (Lhep/dataforge/meta/MutableItemProvider;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/MutableItemProvider;
|
||||
public static fun invoke (Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
public static synthetic fun read$default (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Meta;Lhep/dataforge/meta/ItemProvider;ILjava/lang/Object;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
public static fun wrap (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
public static synthetic fun wrap$default (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/Config;Lhep/dataforge/meta/ItemProvider;ILjava/lang/Object;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
public static synthetic fun write$default (Lhep/dataforge/meta/Specification;Lhep/dataforge/meta/MutableItemProvider;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/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/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/Meta;Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
public static final fun update (Lhep/dataforge/meta/Configurable;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)V
|
||||
public static final fun update (Lhep/dataforge/meta/MutableItemProvider;Lhep/dataforge/meta/Specification;Lkotlin/jvm/functions/Function1;)V
|
||||
public static final fun withSpec (Lhep/dataforge/meta/TypedMetaItem;Lhep/dataforge/meta/Specification;)Lhep/dataforge/meta/MutableItemProvider;
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/meta/TypedMeta : hep/dataforge/meta/Meta {
|
||||
public abstract fun getItem (Lhep/dataforge/names/Name;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public abstract fun getItems ()Ljava/util/Map;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/TypedMeta$DefaultImpls {
|
||||
public static fun getItem (Lhep/dataforge/meta/TypedMeta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static fun toMeta (Lhep/dataforge/meta/TypedMeta;)Lhep/dataforge/meta/Meta;
|
||||
}
|
||||
|
||||
public abstract class hep/dataforge/meta/TypedMetaItem {
|
||||
public static final field Companion Lhep/dataforge/meta/TypedMetaItem$Companion;
|
||||
public abstract fun equals (Ljava/lang/Object;)Z
|
||||
public abstract fun hashCode ()I
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/TypedMetaItem$Companion {
|
||||
public final fun of (Ljava/lang/Object;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public final fun serializer (Lkotlinx/serialization/KSerializer;)Lkotlinx/serialization/KSerializer;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/TypedMetaKt {
|
||||
public static final fun get (Lhep/dataforge/meta/TypedMeta;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static final fun get (Lhep/dataforge/meta/TypedMeta;Lhep/dataforge/names/NameToken;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static final fun get (Lhep/dataforge/meta/TypedMeta;Ljava/lang/String;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/meta/descriptors/Described {
|
||||
@ -546,14 +532,15 @@ public final class hep/dataforge/meta/descriptors/Described$Companion {
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/descriptors/DescriptorMetaKt {
|
||||
public static final fun defaultItem (Lhep/dataforge/meta/descriptors/ItemDescriptor;)Lhep/dataforge/meta/MetaItem;
|
||||
public static final fun defaultItem (Lhep/dataforge/meta/descriptors/ItemDescriptor;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static final fun defaultMeta (Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/Laminate;
|
||||
}
|
||||
|
||||
public abstract class hep/dataforge/meta/descriptors/ItemDescriptor {
|
||||
public abstract class hep/dataforge/meta/descriptors/ItemDescriptor : hep/dataforge/meta/Configurable {
|
||||
public static final field Companion Lhep/dataforge/meta/descriptors/ItemDescriptor$Companion;
|
||||
public static final field DEFAULT_INDEX_KEY Ljava/lang/String;
|
||||
public synthetic fun <init> (Lhep/dataforge/meta/Config;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public abstract fun copy ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
|
||||
public final fun getAttributes ()Lhep/dataforge/meta/Config;
|
||||
public final fun getConfig ()Lhep/dataforge/meta/Config;
|
||||
public final fun getIndexKey ()Ljava/lang/String;
|
||||
@ -571,11 +558,12 @@ public final class hep/dataforge/meta/descriptors/ItemDescriptor$Companion {
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/descriptors/ItemDescriptorKt {
|
||||
public static final fun NodeDescriptor (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/descriptors/NodeDescriptor;
|
||||
public static final fun attributes (Lhep/dataforge/meta/descriptors/ItemDescriptor;Lkotlin/jvm/functions/Function1;)V
|
||||
public static final fun get (Lhep/dataforge/meta/descriptors/ItemDescriptor;Lhep/dataforge/names/Name;)Lhep/dataforge/meta/descriptors/ItemDescriptor;
|
||||
public static final fun get (Lhep/dataforge/meta/descriptors/ItemDescriptor;Ljava/lang/String;)Lhep/dataforge/meta/descriptors/ItemDescriptor;
|
||||
public static final fun plus (Lhep/dataforge/meta/descriptors/NodeDescriptor;Lhep/dataforge/meta/descriptors/NodeDescriptor;)Lhep/dataforge/meta/descriptors/NodeDescriptor;
|
||||
public static final fun validateItem (Lhep/dataforge/meta/descriptors/ItemDescriptor;Lhep/dataforge/meta/MetaItem;)Z
|
||||
public static final fun validateItem (Lhep/dataforge/meta/descriptors/ItemDescriptor;Lhep/dataforge/meta/TypedMetaItem;)Z
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/descriptors/NodeDescriptor : hep/dataforge/meta/descriptors/ItemDescriptor {
|
||||
@ -583,6 +571,8 @@ public final class hep/dataforge/meta/descriptors/NodeDescriptor : hep/dataforge
|
||||
public fun <init> ()V
|
||||
public fun <init> (Lhep/dataforge/meta/Config;)V
|
||||
public synthetic fun <init> (Lhep/dataforge/meta/Config;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public synthetic fun copy ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
|
||||
public fun copy ()Lhep/dataforge/meta/descriptors/NodeDescriptor;
|
||||
public final fun getDefault ()Lhep/dataforge/meta/Config;
|
||||
public final fun getItems ()Ljava/util/Map;
|
||||
public final fun getNodes ()Ljava/util/Map;
|
||||
@ -599,7 +589,6 @@ public final class hep/dataforge/meta/descriptors/NodeDescriptor : hep/dataforge
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/descriptors/NodeDescriptor$Companion {
|
||||
public final fun invoke (Lkotlin/jvm/functions/Function1;)Lhep/dataforge/meta/descriptors/NodeDescriptor;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/descriptors/ValueDescriptor : hep/dataforge/meta/descriptors/ItemDescriptor {
|
||||
@ -607,6 +596,8 @@ public final class hep/dataforge/meta/descriptors/ValueDescriptor : hep/dataforg
|
||||
public fun <init> (Lhep/dataforge/meta/Config;)V
|
||||
public synthetic fun <init> (Lhep/dataforge/meta/Config;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
|
||||
public final fun allow ([Ljava/lang/Object;)V
|
||||
public synthetic fun copy ()Lhep/dataforge/meta/descriptors/ItemDescriptor;
|
||||
public fun copy ()Lhep/dataforge/meta/descriptors/ValueDescriptor;
|
||||
public final fun default (Ljava/lang/Object;)V
|
||||
public final fun getAllowedValues ()Ljava/util/List;
|
||||
public final fun getDefault ()Lhep/dataforge/values/Value;
|
||||
@ -628,16 +619,16 @@ public final class hep/dataforge/meta/transformations/KeepTransformationRule : h
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public final fun getSelector ()Lkotlin/jvm/functions/Function1;
|
||||
public fun hashCode ()I
|
||||
public fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
|
||||
public fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/meta/TypedMetaItem;)Z
|
||||
public fun selectItems (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
|
||||
public fun toString ()Ljava/lang/String;
|
||||
public fun transformItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/MutableMeta;)V
|
||||
public fun transformItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/TypedMetaItem;Lhep/dataforge/meta/MutableMeta;)V
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/meta/transformations/MetaConverter {
|
||||
public static final field Companion Lhep/dataforge/meta/transformations/MetaConverter$Companion;
|
||||
public abstract fun itemToObject (Lhep/dataforge/meta/MetaItem;)Ljava/lang/Object;
|
||||
public abstract fun objectToMetaItem (Ljava/lang/Object;)Lhep/dataforge/meta/MetaItem;
|
||||
public abstract fun itemToObject (Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Object;
|
||||
public abstract fun objectToMetaItem (Ljava/lang/Object;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/transformations/MetaConverter$Companion {
|
||||
@ -657,8 +648,8 @@ public final class hep/dataforge/meta/transformations/MetaConverter$Companion {
|
||||
|
||||
public final class hep/dataforge/meta/transformations/MetaConverterKt {
|
||||
public static final fun metaToObject (Lhep/dataforge/meta/transformations/MetaConverter;Lhep/dataforge/meta/Meta;)Ljava/lang/Object;
|
||||
public static final fun nullableItemToObject (Lhep/dataforge/meta/transformations/MetaConverter;Lhep/dataforge/meta/MetaItem;)Ljava/lang/Object;
|
||||
public static final fun nullableObjectToMetaItem (Lhep/dataforge/meta/transformations/MetaConverter;Ljava/lang/Object;)Lhep/dataforge/meta/MetaItem;
|
||||
public static final fun nullableItemToObject (Lhep/dataforge/meta/transformations/MetaConverter;Lhep/dataforge/meta/TypedMetaItem;)Ljava/lang/Object;
|
||||
public static final fun nullableObjectToMetaItem (Lhep/dataforge/meta/transformations/MetaConverter;Ljava/lang/Object;)Lhep/dataforge/meta/TypedMetaItem;
|
||||
public static final fun valueToObject (Lhep/dataforge/meta/transformations/MetaConverter;Lhep/dataforge/values/Value;)Ljava/lang/Object;
|
||||
}
|
||||
|
||||
@ -671,7 +662,7 @@ public final class hep/dataforge/meta/transformations/MetaTransformation {
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public static fun equals-impl (Ljava/util/Collection;Ljava/lang/Object;)Z
|
||||
public static final fun equals-impl0 (Ljava/util/Collection;Ljava/util/Collection;)Z
|
||||
public static final fun generate-impl (Ljava/util/Collection;Lhep/dataforge/meta/Config;)Lhep/dataforge/meta/ObservableMeta;
|
||||
public static final fun generate-impl (Ljava/util/Collection;Lhep/dataforge/meta/Config;)Lhep/dataforge/meta/ObservableItemProvider;
|
||||
public static final fun generate-impl (Ljava/util/Collection;Lhep/dataforge/meta/Meta;)Lhep/dataforge/meta/Meta;
|
||||
public final fun getTransformations ()Ljava/util/Collection;
|
||||
public fun hashCode ()I
|
||||
@ -682,7 +673,7 @@ public final class hep/dataforge/meta/transformations/MetaTransformation {
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/transformations/MetaTransformation$Companion {
|
||||
public final fun make-S5KKvQA (Lkotlin/jvm/functions/Function1;)Ljava/util/Collection;
|
||||
public final fun make-edBMxVg (Lkotlin/jvm/functions/Function1;)Ljava/util/Collection;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/transformations/MetaTransformationBuilder {
|
||||
@ -705,10 +696,10 @@ public final class hep/dataforge/meta/transformations/RegexItemTransformationRul
|
||||
public final fun getFrom ()Lkotlin/text/Regex;
|
||||
public final fun getTransform ()Lkotlin/jvm/functions/Function4;
|
||||
public fun hashCode ()I
|
||||
public fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
|
||||
public fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/meta/TypedMetaItem;)Z
|
||||
public fun selectItems (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
|
||||
public fun toString ()Ljava/lang/String;
|
||||
public fun transformItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/MutableMeta;)V
|
||||
public fun transformItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/TypedMetaItem;Lhep/dataforge/meta/MutableMeta;)V
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/transformations/SingleItemTransformationRule : hep/dataforge/meta/transformations/TransformationRule {
|
||||
@ -721,22 +712,48 @@ public final class hep/dataforge/meta/transformations/SingleItemTransformationRu
|
||||
public final fun getFrom ()Lhep/dataforge/names/Name;
|
||||
public final fun getTransform ()Lkotlin/jvm/functions/Function3;
|
||||
public fun hashCode ()I
|
||||
public fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
|
||||
public fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/meta/TypedMetaItem;)Z
|
||||
public fun selectItems (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
|
||||
public fun toString ()Ljava/lang/String;
|
||||
public fun transformItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/MutableMeta;)V
|
||||
public fun transformItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/TypedMetaItem;Lhep/dataforge/meta/MutableMeta;)V
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/meta/transformations/TransformationRule {
|
||||
public abstract fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;)Z
|
||||
public abstract fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/meta/TypedMetaItem;)Z
|
||||
public abstract fun selectItems (Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
|
||||
public abstract fun transformItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/MetaItem;Lhep/dataforge/meta/MutableMeta;)V
|
||||
public abstract fun transformItem (Lhep/dataforge/names/Name;Lhep/dataforge/meta/TypedMetaItem;Lhep/dataforge/meta/MutableMeta;)V
|
||||
}
|
||||
|
||||
public final class hep/dataforge/meta/transformations/TransformationRule$DefaultImpls {
|
||||
public static fun selectItems (Lhep/dataforge/meta/transformations/TransformationRule;Lhep/dataforge/meta/Meta;)Lkotlin/sequences/Sequence;
|
||||
}
|
||||
|
||||
public abstract interface annotation class hep/dataforge/misc/DFBuilder : java/lang/annotation/Annotation {
|
||||
}
|
||||
|
||||
public abstract interface annotation class hep/dataforge/misc/DFExperimental : java/lang/annotation/Annotation {
|
||||
}
|
||||
|
||||
public abstract interface annotation class hep/dataforge/misc/DFInternal : java/lang/annotation/Annotation {
|
||||
}
|
||||
|
||||
public abstract interface class hep/dataforge/misc/Named {
|
||||
public static final field Companion Lhep/dataforge/misc/Named$Companion;
|
||||
public abstract fun getName ()Lhep/dataforge/names/Name;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/misc/Named$Companion {
|
||||
public final fun nameOf (Ljava/lang/Object;)Lhep/dataforge/names/Name;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/misc/NamedKt {
|
||||
public static final fun isAnonymous (Lhep/dataforge/misc/Named;)Z
|
||||
}
|
||||
|
||||
public abstract interface annotation class hep/dataforge/misc/Type : java/lang/annotation/Annotation {
|
||||
public abstract fun id ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/names/Name {
|
||||
public static final field Companion Lhep/dataforge/names/Name$Companion;
|
||||
public static final field NAME_SEPARATOR Ljava/lang/String;
|
||||
@ -752,6 +769,8 @@ public final class hep/dataforge/names/Name$Companion : kotlinx/serialization/KS
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
public fun getDescriptor ()Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public final fun getEMPTY ()Lhep/dataforge/names/Name;
|
||||
public final fun getMATCH_ALL_TOKEN ()Lhep/dataforge/names/NameToken;
|
||||
public final fun getMATCH_ANY_TOKEN ()Lhep/dataforge/names/NameToken;
|
||||
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Lhep/dataforge/names/Name;)V
|
||||
public synthetic fun serialize (Lkotlinx/serialization/encoding/Encoder;Ljava/lang/Object;)V
|
||||
public final fun serializer ()Lkotlinx/serialization/KSerializer;
|
||||
@ -777,6 +796,7 @@ public final class hep/dataforge/names/NameKt {
|
||||
public static final fun plus (Lhep/dataforge/names/Name;Lhep/dataforge/names/NameToken;)Lhep/dataforge/names/Name;
|
||||
public static final fun plus (Lhep/dataforge/names/Name;Ljava/lang/String;)Lhep/dataforge/names/Name;
|
||||
public static final fun plus (Lhep/dataforge/names/NameToken;Lhep/dataforge/names/Name;)Lhep/dataforge/names/Name;
|
||||
public static final fun removeHeadOrNull (Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;)Lhep/dataforge/names/Name;
|
||||
public static final fun set (Ljava/util/Map;Ljava/lang/String;Ljava/lang/Object;)V
|
||||
public static final fun startsWith (Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;)Z
|
||||
public static final fun startsWith (Lhep/dataforge/names/Name;Lhep/dataforge/names/NameToken;)Z
|
||||
@ -784,6 +804,12 @@ public final class hep/dataforge/names/NameKt {
|
||||
public static final fun withIndex (Lhep/dataforge/names/Name;Ljava/lang/String;)Lhep/dataforge/names/Name;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/names/NameMatcherKt {
|
||||
public static final fun matches (Lhep/dataforge/names/Name;Lhep/dataforge/names/Name;)Z
|
||||
public static final fun matches (Lhep/dataforge/names/Name;Ljava/lang/String;)Z
|
||||
public static final fun matches (Lhep/dataforge/names/NameToken;Lhep/dataforge/names/NameToken;)Z
|
||||
}
|
||||
|
||||
public final class hep/dataforge/names/NameToken {
|
||||
public static final field Companion Lhep/dataforge/names/NameToken$Companion;
|
||||
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
|
||||
@ -813,17 +839,15 @@ public final class hep/dataforge/names/NameTokenKt {
|
||||
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 final class hep/dataforge/values/DoubleArrayValue : hep/dataforge/values/Value, java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker {
|
||||
public fun <init> ([D)V
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun getList ()Ljava/util/List;
|
||||
public fun getNumber ()Ljava/lang/Double;
|
||||
public synthetic fun getNumber ()Ljava/lang/Number;
|
||||
public fun getString ()Ljava/lang/String;
|
||||
public fun getType ()Lhep/dataforge/values/ValueType;
|
||||
public synthetic fun getValue ()Ljava/lang/Object;
|
||||
public fun getValue ()[D
|
||||
public fun hashCode ()I
|
||||
public fun iterator ()Ljava/util/Iterator;
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
@ -831,8 +855,6 @@ public final class hep/dataforge/values/EnumValue : hep/dataforge/values/Value {
|
||||
public fun <init> (Ljava/lang/Enum;)V
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun getList ()Ljava/util/List;
|
||||
public fun getNumber ()Ljava/lang/Number;
|
||||
public fun getString ()Ljava/lang/String;
|
||||
public fun getType ()Lhep/dataforge/values/ValueType;
|
||||
public fun getValue ()Ljava/lang/Enum;
|
||||
public synthetic fun getValue ()Ljava/lang/Object;
|
||||
@ -849,8 +871,6 @@ public final class hep/dataforge/values/False : hep/dataforge/values/Value {
|
||||
public static final field INSTANCE Lhep/dataforge/values/False;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun getList ()Ljava/util/List;
|
||||
public fun getNumber ()Ljava/lang/Number;
|
||||
public fun getString ()Ljava/lang/String;
|
||||
public fun getType ()Lhep/dataforge/values/ValueType;
|
||||
public fun getValue ()Ljava/lang/Object;
|
||||
public fun hashCode ()I
|
||||
@ -861,33 +881,34 @@ public final class hep/dataforge/values/LazyParsedValue : hep/dataforge/values/V
|
||||
public fun <init> (Ljava/lang/String;)V
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun getList ()Ljava/util/List;
|
||||
public fun getNumber ()Ljava/lang/Number;
|
||||
public fun getString ()Ljava/lang/String;
|
||||
public final fun getString ()Ljava/lang/String;
|
||||
public fun getType ()Lhep/dataforge/values/ValueType;
|
||||
public fun getValue ()Ljava/lang/Object;
|
||||
public fun hashCode ()I
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/values/ListValue : hep/dataforge/values/Value {
|
||||
public final class hep/dataforge/values/ListValue : hep/dataforge/values/Value, java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker {
|
||||
public static final field Companion Lhep/dataforge/values/ListValue$Companion;
|
||||
public fun <init> (Ljava/util/List;)V
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun getList ()Ljava/util/List;
|
||||
public fun getNumber ()Ljava/lang/Number;
|
||||
public fun getString ()Ljava/lang/String;
|
||||
public fun getType ()Lhep/dataforge/values/ValueType;
|
||||
public synthetic fun getValue ()Ljava/lang/Object;
|
||||
public fun getValue ()Ljava/util/List;
|
||||
public fun hashCode ()I
|
||||
public fun iterator ()Ljava/util/Iterator;
|
||||
public fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/values/ListValue$Companion {
|
||||
public final fun getEMPTY ()Lhep/dataforge/values/ListValue;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/values/Null : hep/dataforge/values/Value {
|
||||
public static final field INSTANCE Lhep/dataforge/values/Null;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun getList ()Ljava/util/List;
|
||||
public fun getNumber ()Ljava/lang/Number;
|
||||
public fun getString ()Ljava/lang/String;
|
||||
public fun getType ()Lhep/dataforge/values/ValueType;
|
||||
public fun getValue ()Ljava/lang/Object;
|
||||
public fun hashCode ()I
|
||||
@ -898,8 +919,7 @@ public final class hep/dataforge/values/NumberValue : hep/dataforge/values/Value
|
||||
public fun <init> (Ljava/lang/Number;)V
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun getList ()Ljava/util/List;
|
||||
public fun getNumber ()Ljava/lang/Number;
|
||||
public fun getString ()Ljava/lang/String;
|
||||
public final fun getNumber ()Ljava/lang/Number;
|
||||
public fun getType ()Lhep/dataforge/values/ValueType;
|
||||
public fun getValue ()Ljava/lang/Object;
|
||||
public fun hashCode ()I
|
||||
@ -910,8 +930,7 @@ public final class hep/dataforge/values/StringValue : hep/dataforge/values/Value
|
||||
public fun <init> (Ljava/lang/String;)V
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun getList ()Ljava/util/List;
|
||||
public fun getNumber ()Ljava/lang/Number;
|
||||
public fun getString ()Ljava/lang/String;
|
||||
public final fun getString ()Ljava/lang/String;
|
||||
public fun getType ()Lhep/dataforge/values/ValueType;
|
||||
public fun getValue ()Ljava/lang/Object;
|
||||
public fun hashCode ()I
|
||||
@ -922,8 +941,6 @@ public final class hep/dataforge/values/True : hep/dataforge/values/Value {
|
||||
public static final field INSTANCE Lhep/dataforge/values/True;
|
||||
public fun equals (Ljava/lang/Object;)Z
|
||||
public fun getList ()Ljava/util/List;
|
||||
public fun getNumber ()Ljava/lang/Number;
|
||||
public fun getString ()Ljava/lang/String;
|
||||
public fun getType ()Lhep/dataforge/values/ValueType;
|
||||
public fun getValue ()Ljava/lang/Object;
|
||||
public fun hashCode ()I
|
||||
@ -932,18 +949,17 @@ public final class hep/dataforge/values/True : hep/dataforge/values/Value {
|
||||
|
||||
public abstract interface class hep/dataforge/values/Value {
|
||||
public static final field Companion Lhep/dataforge/values/Value$Companion;
|
||||
public static final field TARGET Ljava/lang/String;
|
||||
public static final field TYPE Ljava/lang/String;
|
||||
public abstract fun equals (Ljava/lang/Object;)Z
|
||||
public abstract fun getList ()Ljava/util/List;
|
||||
public abstract fun getNumber ()Ljava/lang/Number;
|
||||
public abstract fun getString ()Ljava/lang/String;
|
||||
public abstract fun getType ()Lhep/dataforge/values/ValueType;
|
||||
public abstract fun getValue ()Ljava/lang/Object;
|
||||
public abstract fun hashCode ()I
|
||||
public abstract fun toString ()Ljava/lang/String;
|
||||
}
|
||||
|
||||
public final class hep/dataforge/values/Value$Companion {
|
||||
public static final field TARGET Ljava/lang/String;
|
||||
public static final field TYPE Ljava/lang/String;
|
||||
public final fun of (Ljava/lang/Object;)Lhep/dataforge/values/Value;
|
||||
}
|
||||
|
||||
@ -976,6 +992,9 @@ public final class hep/dataforge/values/ValueKt {
|
||||
public static final fun asValue ([I)Lhep/dataforge/values/Value;
|
||||
public static final fun asValue ([J)Lhep/dataforge/values/Value;
|
||||
public static final fun asValue ([S)Lhep/dataforge/values/Value;
|
||||
public static final fun getNumber (Lhep/dataforge/values/Value;)Ljava/lang/Number;
|
||||
public static final fun getNumberOrNull (Lhep/dataforge/values/Value;)Ljava/lang/Number;
|
||||
public static final fun getString (Lhep/dataforge/values/Value;)Ljava/lang/String;
|
||||
public static final fun parseValue (Ljava/lang/String;)Lhep/dataforge/values/Value;
|
||||
}
|
||||
|
||||
@ -991,6 +1010,7 @@ public final class hep/dataforge/values/ValueSerializer : kotlinx/serialization/
|
||||
public final class hep/dataforge/values/ValueType : java/lang/Enum {
|
||||
public static final field BOOLEAN Lhep/dataforge/values/ValueType;
|
||||
public static final field Companion Lhep/dataforge/values/ValueType$Companion;
|
||||
public static final field LIST Lhep/dataforge/values/ValueType;
|
||||
public static final field NULL Lhep/dataforge/values/ValueType;
|
||||
public static final field NUMBER Lhep/dataforge/values/ValueType;
|
||||
public static final field STRING Lhep/dataforge/values/ValueType;
|
||||
@ -1000,6 +1020,7 @@ public final class hep/dataforge/values/ValueType : java/lang/Enum {
|
||||
|
||||
public final class hep/dataforge/values/ValueType$$serializer : kotlinx/serialization/internal/GeneratedSerializer {
|
||||
public static final field INSTANCE Lhep/dataforge/values/ValueType$$serializer;
|
||||
public static final synthetic field descriptor Lkotlinx/serialization/descriptors/SerialDescriptor;
|
||||
public fun childSerializers ()[Lkotlinx/serialization/KSerializer;
|
||||
public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lhep/dataforge/values/ValueType;
|
||||
public synthetic fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Ljava/lang/Object;
|
||||
|
@ -10,3 +10,7 @@ kscience {
|
||||
}
|
||||
|
||||
description = "Meta definition and basic operations on meta"
|
||||
|
||||
readme{
|
||||
maturity = ru.mipt.npm.gradle.Maturity.DEVELOPMENT
|
||||
}
|
@ -10,16 +10,17 @@ import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
import kotlin.collections.set
|
||||
import kotlin.jvm.Synchronized
|
||||
|
||||
//TODO add validator to configuration
|
||||
|
||||
public data class MetaListener(
|
||||
public data class ItemListener(
|
||||
val owner: Any? = null,
|
||||
val action: (name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) -> Unit
|
||||
val action: (name: Name, oldItem: MetaItem?, newItem: MetaItem?) -> Unit
|
||||
)
|
||||
|
||||
public interface ObservableMeta : Meta {
|
||||
public fun onChange(owner: Any?, 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?)
|
||||
}
|
||||
|
||||
@ -27,37 +28,40 @@ public interface ObservableMeta : Meta {
|
||||
* Mutable meta representing object state
|
||||
*/
|
||||
@Serializable(Config.Companion::class)
|
||||
public class Config() : AbstractMutableMeta<Config>(), ObservableMeta {
|
||||
public class Config() : AbstractMutableMeta<Config>(), ObservableItemProvider {
|
||||
|
||||
private val listeners = HashSet<MetaListener>()
|
||||
private val listeners = HashSet<ItemListener>()
|
||||
|
||||
private fun itemChanged(name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) {
|
||||
@Synchronized
|
||||
private fun itemChanged(name: Name, oldItem: MetaItem?, newItem: MetaItem?) {
|
||||
listeners.forEach { it.action(name, oldItem, newItem) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Add change listener to this meta. Owner is declared to be able to remove listeners later. Listener without owner could not be removed
|
||||
*/
|
||||
override fun onChange(owner: Any?, action: (Name, MetaItem<*>?, MetaItem<*>?) -> Unit) {
|
||||
listeners.add(MetaListener(owner, action))
|
||||
@Synchronized
|
||||
override fun onChange(owner: Any?, action: (Name, MetaItem?, MetaItem?) -> Unit) {
|
||||
listeners.add(ItemListener(owner, action))
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all listeners belonging to given owner
|
||||
*/
|
||||
@Synchronized
|
||||
override fun removeListener(owner: Any?) {
|
||||
listeners.removeAll { it.owner === owner }
|
||||
}
|
||||
|
||||
override fun replaceItem(key: NameToken, oldItem: MetaItem<Config>?, newItem: MetaItem<Config>?) {
|
||||
override fun replaceItem(key: NameToken, oldItem: TypedMetaItem<Config>?, newItem: TypedMetaItem<Config>?) {
|
||||
if (newItem == null) {
|
||||
children.remove(key)
|
||||
if (oldItem != null && oldItem is MetaItem.NodeItem<Config>) {
|
||||
if (oldItem != null && oldItem is MetaItemNode<Config>) {
|
||||
oldItem.node.removeListener(this)
|
||||
}
|
||||
} else {
|
||||
children[key] = newItem
|
||||
if (newItem is MetaItem.NodeItem) {
|
||||
if (newItem is MetaItemNode) {
|
||||
newItem.node.onChange(this) { name, oldChild, newChild ->
|
||||
itemChanged(key + name, oldChild, newChild)
|
||||
}
|
||||
@ -88,14 +92,23 @@ public class Config() : AbstractMutableMeta<Config>(), ObservableMeta {
|
||||
}
|
||||
}
|
||||
|
||||
public operator fun Config.get(token: NameToken): MetaItem<Config>? = items[token]
|
||||
public operator fun Config.get(token: NameToken): TypedMetaItem<Config>? = items[token]
|
||||
|
||||
public fun Meta.asConfig(): Config = this as? Config ?: Config().also { builder ->
|
||||
/**
|
||||
* Create a mutable copy of this [Meta]. The copy is created event if initial [Meta] is a [Config].
|
||||
* Listeners are not preserved
|
||||
*/
|
||||
public fun Meta.toConfig(): Config = Config().also { builder ->
|
||||
this.items.mapValues { entry ->
|
||||
val item = entry.value
|
||||
builder[entry.key.asName()] = when (item) {
|
||||
is MetaItem.ValueItem -> item.value
|
||||
is MetaItem.NodeItem -> MetaItem.NodeItem(item.node.asConfig())
|
||||
is MetaItemValue -> item.value
|
||||
is MetaItemNode -> MetaItemNode(item.node.asConfig())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return this [Meta] as [Config] if it is [Config] and create a new copy otherwise
|
||||
*/
|
||||
public fun Meta.asConfig(): Config = this as? Config ?: toConfig()
|
@ -1,5 +1,6 @@
|
||||
package hep.dataforge.meta
|
||||
|
||||
import hep.dataforge.misc.DFBuilder
|
||||
import hep.dataforge.names.Name
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
|
||||
|
@ -8,10 +8,10 @@ import kotlin.properties.ReadOnlyProperty
|
||||
|
||||
/* Meta delegates */
|
||||
|
||||
public typealias ItemDelegate = ReadOnlyProperty<Any?, MetaItem<*>?>
|
||||
public typealias ItemDelegate = ReadOnlyProperty<Any?, MetaItem?>
|
||||
|
||||
public fun ItemProvider.item(key: Name? = null): ItemDelegate = ReadOnlyProperty { _, property ->
|
||||
getItem(key ?: property.name.asName())
|
||||
get(key ?: property.name.asName())
|
||||
}
|
||||
|
||||
//TODO add caching for sealed nodes
|
||||
@ -40,7 +40,7 @@ public fun <R : Any> ItemDelegate.convert(
|
||||
* A converter with a custom reader transformation
|
||||
*/
|
||||
public fun <R> ItemDelegate.convert(
|
||||
reader: (MetaItem<*>?) -> R,
|
||||
reader: (MetaItem?) -> R,
|
||||
): ReadOnlyProperty<Any?, R> = ReadOnlyProperty<Any?, R> { thisRef, property ->
|
||||
this@convert.getValue(thisRef, property).let(reader)
|
||||
}
|
||||
|
@ -0,0 +1,88 @@
|
||||
package hep.dataforge.meta
|
||||
|
||||
import hep.dataforge.names.*
|
||||
|
||||
public fun interface ItemProvider {
|
||||
//getItem used instead of get in order to provide extension freedom
|
||||
public fun getItem(name: Name): MetaItem?
|
||||
|
||||
public companion object {
|
||||
public val EMPTY: ItemProvider = ItemProvider { null }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Get operations*/
|
||||
|
||||
/**
|
||||
* Perform recursive item search using given [name]. Each [NameToken] is treated as a name in [Meta.items] of a parent node.
|
||||
*
|
||||
* If [name] is empty return current [Meta] as a [MetaItemNode]
|
||||
*/
|
||||
public operator fun ItemProvider?.get(name: Name): MetaItem? = this?.getItem(name)
|
||||
|
||||
/**
|
||||
* Root item of this provider
|
||||
*/
|
||||
public val ItemProvider.rootItem: MetaItem? get() = get(Name.EMPTY)
|
||||
|
||||
/**
|
||||
* The root node of this item provider if it is present
|
||||
*/
|
||||
public val ItemProvider.rootNode: Meta? get() = rootItem.node
|
||||
|
||||
/**
|
||||
* Parse [Name] from [key] using full name notation and pass it to [Meta.get]
|
||||
*/
|
||||
public operator fun ItemProvider?.get(key: String): MetaItem? = this?.get(key.toName())
|
||||
|
||||
/**
|
||||
* Create a provider that uses given provider for default values if those are not found in this provider
|
||||
*/
|
||||
public fun ItemProvider.withDefault(default: ItemProvider?): ItemProvider = if (default == null) {
|
||||
this
|
||||
} else {
|
||||
ItemProvider {
|
||||
this[it] ?: default[it]
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all items matching given name. The index of the last element, if present is used as a [Regex],
|
||||
* against which indexes of elements are matched.
|
||||
*/
|
||||
public fun ItemProvider.getIndexed(name: Name): Map<String?, MetaItem> {
|
||||
val root: Meta = when (name.length) {
|
||||
0 -> error("Can't use empty name for 'getIndexed'")
|
||||
1 -> this.rootNode ?: return emptyMap()
|
||||
else -> this[name.cutLast()].node ?: return emptyMap()
|
||||
}
|
||||
|
||||
val (body, index) = name.lastOrNull()!!
|
||||
return if (index == null) {
|
||||
root.items.filter { it.key.body == body }.mapKeys { it.key.index }
|
||||
} else {
|
||||
val regex = index.toRegex()
|
||||
root.items.filter { it.key.body == body && (regex.matches(it.key.index ?: "")) }
|
||||
.mapKeys { it.key.index }
|
||||
}
|
||||
}
|
||||
|
||||
public fun ItemProvider.getIndexed(name: String): Map<String?, MetaItem> = this@getIndexed.getIndexed(name.toName())
|
||||
|
||||
/**
|
||||
* Return a provider referencing a child node
|
||||
*/
|
||||
public fun ItemProvider.getChild(childName: Name): ItemProvider = get(childName).node ?: ItemProvider.EMPTY
|
||||
|
||||
public fun ItemProvider.getChild(childName: String): ItemProvider = getChild(childName.toName())
|
||||
|
||||
///**
|
||||
// * Get all items matching given name.
|
||||
// */
|
||||
//@Suppress("UNCHECKED_CAST")
|
||||
//public fun <M : TypedMeta<M>> M.getIndexed(name: Name): Map<String?, MetaItem<M>> =
|
||||
// (this as Meta).getIndexed(name) as Map<String?, MetaItem<M>>
|
||||
//
|
||||
//public fun <M : TypedMeta<M>> M.getIndexed(name: String): Map<String?, MetaItem<M>> =
|
||||
// getIndexed(name.toName())
|
@ -16,21 +16,17 @@ import kotlinx.serialization.json.*
|
||||
/**
|
||||
* @param descriptor reserved for custom serialization in future
|
||||
*/
|
||||
public fun Value.toJson(descriptor: ValueDescriptor? = null): JsonElement {
|
||||
return if (isList()) {
|
||||
JsonArray(list.map { it.toJson() })
|
||||
} else {
|
||||
when (type) {
|
||||
ValueType.NUMBER -> JsonPrimitive(number)
|
||||
public fun Value.toJson(descriptor: ValueDescriptor? = null): JsonElement = when (type) {
|
||||
ValueType.NUMBER -> JsonPrimitive(numberOrNull)
|
||||
ValueType.STRING -> JsonPrimitive(string)
|
||||
ValueType.BOOLEAN -> JsonPrimitive(boolean)
|
||||
ValueType.LIST -> JsonArray(list.map { it.toJson() })
|
||||
ValueType.NULL -> JsonNull
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Use these methods to customize JSON key mapping
|
||||
private fun String.toJsonKey(descriptor: ItemDescriptor?) = descriptor?.attributes["jsonName"].string ?: toString()
|
||||
@Suppress("NULLABLE_EXTENSION_OPERATOR_WITH_SAFE_CALL_RECEIVER")
|
||||
private fun String.toJsonKey(descriptor: ItemDescriptor?) = descriptor?.attributes?.get("jsonName").string ?: toString()
|
||||
|
||||
//private fun NodeDescriptor?.getDescriptor(key: String) = this?.items?.get(key)
|
||||
|
||||
@ -41,11 +37,11 @@ private fun Meta.toJsonWithIndex(descriptor: NodeDescriptor?, indexValue: String
|
||||
|
||||
val elementMap = HashMap<String, JsonElement>()
|
||||
|
||||
fun MetaItem<*>.toJsonElement(itemDescriptor: ItemDescriptor?, index: String?): JsonElement = when (this) {
|
||||
is MetaItem.ValueItem -> {
|
||||
fun MetaItem.toJsonElement(itemDescriptor: ItemDescriptor?, index: String?): JsonElement = when (this) {
|
||||
is MetaItemValue -> {
|
||||
value.toJson(itemDescriptor as? ValueDescriptor)
|
||||
}
|
||||
is MetaItem.NodeItem -> {
|
||||
is MetaItemNode -> {
|
||||
node.toJsonWithIndex(itemDescriptor as? NodeDescriptor, index)
|
||||
}
|
||||
}
|
||||
@ -53,7 +49,7 @@ private fun Meta.toJsonWithIndex(descriptor: NodeDescriptor?, indexValue: String
|
||||
fun addElement(key: String) {
|
||||
val itemDescriptor = descriptor?.items?.get(key)
|
||||
val jsonKey = key.toJsonKey(itemDescriptor)
|
||||
val items: Map<String?, MetaItem<*>> = getIndexed(key)
|
||||
val items: Map<String?, MetaItem> = getIndexed(key)
|
||||
when (items.size) {
|
||||
0 -> {
|
||||
//do nothing
|
||||
@ -100,14 +96,14 @@ public fun JsonPrimitive.toValue(descriptor: ValueDescriptor?): Value {
|
||||
}
|
||||
}
|
||||
|
||||
public fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem<JsonMeta> = when (this) {
|
||||
public fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): TypedMetaItem<JsonMeta> = when (this) {
|
||||
is JsonPrimitive -> {
|
||||
val value = this.toValue(descriptor as? ValueDescriptor)
|
||||
MetaItem.ValueItem(value)
|
||||
MetaItemValue(value)
|
||||
}
|
||||
is JsonObject -> {
|
||||
val meta = JsonMeta(this, descriptor as? NodeDescriptor)
|
||||
MetaItem.NodeItem(meta)
|
||||
MetaItemNode(meta)
|
||||
}
|
||||
is JsonArray -> {
|
||||
if (this.all { it is JsonPrimitive }) {
|
||||
@ -119,7 +115,7 @@ public fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem<
|
||||
(it as JsonPrimitive).toValue(descriptor as? ValueDescriptor)
|
||||
}.asValue()
|
||||
}
|
||||
MetaItem.ValueItem(value)
|
||||
MetaItemValue(value)
|
||||
} else {
|
||||
//We can't return multiple items therefore we create top level node
|
||||
buildJsonObject { put(JSON_ARRAY_KEY, this@toMetaItem) }.toMetaItem(descriptor)
|
||||
@ -132,18 +128,18 @@ public fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem<
|
||||
*/
|
||||
public class JsonMeta(private val json: JsonObject, private val descriptor: NodeDescriptor? = null) : MetaBase() {
|
||||
|
||||
private fun buildItems(): Map<NameToken, MetaItem<JsonMeta>> {
|
||||
val map = LinkedHashMap<NameToken, MetaItem<JsonMeta>>()
|
||||
private fun buildItems(): Map<NameToken, TypedMetaItem<JsonMeta>> {
|
||||
val map = LinkedHashMap<NameToken, TypedMetaItem<JsonMeta>>()
|
||||
|
||||
json.forEach { (jsonKey, value) ->
|
||||
val key = NameToken(jsonKey)
|
||||
val itemDescriptor = descriptor?.items?.get(jsonKey)
|
||||
when (value) {
|
||||
is JsonPrimitive -> {
|
||||
map[key] = MetaItem.ValueItem(value.toValue(itemDescriptor as? ValueDescriptor))
|
||||
map[key] = MetaItemValue(value.toValue(itemDescriptor as? ValueDescriptor))
|
||||
}
|
||||
is JsonObject -> {
|
||||
map[key] = MetaItem.NodeItem(
|
||||
map[key] = MetaItemNode(
|
||||
JsonMeta(
|
||||
value,
|
||||
itemDescriptor as? NodeDescriptor
|
||||
@ -157,7 +153,7 @@ public class JsonMeta(private val json: JsonObject, private val descriptor: Node
|
||||
(it as JsonPrimitive).toValue(itemDescriptor as? ValueDescriptor)
|
||||
}
|
||||
)
|
||||
map[key] = MetaItem.ValueItem(listValue)
|
||||
map[key] = MetaItemValue(listValue)
|
||||
} else value.forEachIndexed { index, jsonElement ->
|
||||
val indexKey = (itemDescriptor as? NodeDescriptor)?.indexKey ?: DEFAULT_INDEX_KEY
|
||||
val indexValue: String = (jsonElement as? JsonObject)
|
||||
@ -172,7 +168,7 @@ public class JsonMeta(private val json: JsonObject, private val descriptor: Node
|
||||
return map
|
||||
}
|
||||
|
||||
override val items: Map<NameToken, MetaItem<JsonMeta>> by lazy(::buildItems)
|
||||
override val items: Map<NameToken, TypedMetaItem<JsonMeta>> by lazy(::buildItems)
|
||||
|
||||
public companion object {
|
||||
/**
|
||||
|
@ -17,7 +17,7 @@ public class Laminate(layers: List<Meta>) : MetaBase() {
|
||||
}
|
||||
}
|
||||
|
||||
override val items: Map<NameToken, MetaItem<Meta>> by lazy {
|
||||
override val items: Map<NameToken, TypedMetaItem<Meta>> by lazy {
|
||||
layers.map { it.items.keys }.flatten().associateWith { key ->
|
||||
layers.asSequence().map { it.items[key] }.filterNotNull().let(replaceRule)
|
||||
}
|
||||
@ -40,15 +40,15 @@ public class Laminate(layers: List<Meta>) : MetaBase() {
|
||||
*
|
||||
* TODO add picture
|
||||
*/
|
||||
public val replaceRule: (Sequence<MetaItem<*>>) -> MetaItem<SealedMeta> = { it.first().seal() }
|
||||
public val replaceRule: (Sequence<MetaItem>) -> TypedMetaItem<SealedMeta> = { it.first().seal() }
|
||||
|
||||
private fun Sequence<MetaItem<*>>.merge(): MetaItem<SealedMeta> {
|
||||
private fun Sequence<MetaItem>.merge(): TypedMetaItem<SealedMeta> {
|
||||
return when {
|
||||
all { it is MetaItem.ValueItem } -> //If all items are values, take first
|
||||
all { it is MetaItemValue } -> //If all items are values, take first
|
||||
first().seal()
|
||||
all { it is MetaItem.NodeItem } -> {
|
||||
all { it is MetaItemNode } -> {
|
||||
//list nodes in item
|
||||
val nodes = map { (it as MetaItem.NodeItem).node }
|
||||
val nodes = map { (it as MetaItemNode).node }
|
||||
//represent as key->value entries
|
||||
val entries = nodes.flatMap { it.items.entries.asSequence() }
|
||||
//group by keys
|
||||
@ -57,13 +57,13 @@ public class Laminate(layers: List<Meta>) : MetaBase() {
|
||||
val items = groups.mapValues { entry ->
|
||||
entry.value.asSequence().map { it.value }.merge()
|
||||
}
|
||||
MetaItem.NodeItem(SealedMeta(items))
|
||||
MetaItemNode(SealedMeta(items))
|
||||
|
||||
}
|
||||
else -> map {
|
||||
when (it) {
|
||||
is MetaItem.ValueItem -> MetaItem.NodeItem(Meta { Meta.VALUE_KEY put it.value })
|
||||
is MetaItem.NodeItem -> it
|
||||
is MetaItemValue -> MetaItemNode(Meta { Meta.VALUE_KEY put it.value })
|
||||
is MetaItemNode -> it
|
||||
}
|
||||
}.merge()
|
||||
}
|
||||
@ -74,7 +74,7 @@ public class Laminate(layers: List<Meta>) : MetaBase() {
|
||||
* The values a replaced but meta children are joined
|
||||
* TODO add picture
|
||||
*/
|
||||
public val mergeRule: (Sequence<MetaItem<*>>) -> MetaItem<SealedMeta> = { it.merge() }
|
||||
public val mergeRule: (Sequence<MetaItem>) -> TypedMetaItem<SealedMeta> = { it.merge() }
|
||||
}
|
||||
}
|
||||
|
||||
@ -84,7 +84,7 @@ public fun Laminate(vararg layers: Meta?): Laminate = Laminate(layers.filterNotN
|
||||
/**
|
||||
* Performance optimized version of get method
|
||||
*/
|
||||
public fun Laminate.getFirst(name: Name): MetaItem<*>? {
|
||||
public fun Laminate.getFirst(name: Name): MetaItem? {
|
||||
layers.forEach { layer ->
|
||||
layer[name]?.let { return it }
|
||||
}
|
||||
|
@ -1,67 +1,10 @@
|
||||
package hep.dataforge.meta
|
||||
|
||||
import hep.dataforge.meta.Meta.Companion.VALUE_KEY
|
||||
import hep.dataforge.meta.MetaItem.NodeItem
|
||||
import hep.dataforge.meta.MetaItem.ValueItem
|
||||
import hep.dataforge.names.*
|
||||
import hep.dataforge.values.EnumValue
|
||||
import hep.dataforge.values.Null
|
||||
import hep.dataforge.values.Value
|
||||
import hep.dataforge.values.boolean
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
|
||||
/**
|
||||
* A member of the meta tree. Could be represented as one of following:
|
||||
* * a [ValueItem] (leaf)
|
||||
* * a [NodeItem] (node)
|
||||
*/
|
||||
@Serializable(MetaItemSerializer::class)
|
||||
public sealed class MetaItem<out M : Meta>() {
|
||||
|
||||
abstract override fun equals(other: Any?): Boolean
|
||||
|
||||
abstract override fun hashCode(): Int
|
||||
|
||||
@Serializable(MetaItemSerializer::class)
|
||||
public class ValueItem(public val value: Value) : MetaItem<Nothing>() {
|
||||
override fun toString(): String = value.toString()
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return this.value == (other as? ValueItem)?.value
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return value.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable(MetaItemSerializer::class)
|
||||
public class NodeItem<M : Meta>(public val node: M) : MetaItem<M>() {
|
||||
//Fixing serializer for node could cause class cast problems, but it should not since Meta descendants are not serializeable
|
||||
override fun toString(): String = node.toString()
|
||||
|
||||
override fun equals(other: Any?): Boolean = node == (other as? NodeItem<*>)?.node
|
||||
|
||||
override fun hashCode(): Int = node.hashCode()
|
||||
}
|
||||
|
||||
public companion object {
|
||||
public fun of(arg: Any?): MetaItem<*> {
|
||||
return when (arg) {
|
||||
null -> ValueItem(Null)
|
||||
is MetaItem<*> -> arg
|
||||
is Meta -> NodeItem(arg)
|
||||
else -> ValueItem(Value.of(arg))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun Value.asMetaItem(): ValueItem = ValueItem(this)
|
||||
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.
|
||||
@ -71,18 +14,10 @@ public interface MetaRepr {
|
||||
public fun toMeta(): Meta
|
||||
}
|
||||
|
||||
public fun interface ItemProvider {
|
||||
public fun getItem(name: Name): MetaItem<*>?
|
||||
|
||||
public companion object {
|
||||
public val EMPTY: ItemProvider = ItemProvider { null }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generic meta tree representation. Elements are [MetaItem] objects that could be represented by three different entities:
|
||||
* * [MetaItem.ValueItem] (leaf)
|
||||
* * [MetaItem.NodeItem] single node
|
||||
* Generic meta tree representation. Elements are [TypedMetaItem] objects that could be represented by three different entities:
|
||||
* * [MetaItemValue] (leaf)
|
||||
* * [MetaItemNode] single node
|
||||
*
|
||||
* * Same name siblings are supported via elements with the same [Name] but different queries
|
||||
*/
|
||||
@ -90,10 +25,10 @@ public interface Meta : MetaRepr, ItemProvider {
|
||||
/**
|
||||
* Top level items of meta tree
|
||||
*/
|
||||
public val items: Map<NameToken, MetaItem<*>>
|
||||
public val items: Map<NameToken, MetaItem>
|
||||
|
||||
override fun getItem(name: Name): MetaItem<*>? {
|
||||
if (name.isEmpty()) return NodeItem(this)
|
||||
override fun getItem(name: Name): MetaItem? {
|
||||
if (name.isEmpty()) return MetaItemNode(this)
|
||||
return name.firstOrNull()?.let { token ->
|
||||
val tail = name.cutFirst()
|
||||
when (tail.length) {
|
||||
@ -103,7 +38,7 @@ public interface Meta : MetaRepr, ItemProvider {
|
||||
}
|
||||
}
|
||||
|
||||
override fun toMeta(): Meta = seal()
|
||||
override fun toMeta(): Meta = this
|
||||
|
||||
override fun equals(other: Any?): Boolean
|
||||
|
||||
@ -120,151 +55,39 @@ public interface Meta : MetaRepr, ItemProvider {
|
||||
public const val VALUE_KEY: String = "@value"
|
||||
|
||||
public val EMPTY: Meta = object : MetaBase() {
|
||||
override val items: Map<NameToken, MetaItem<*>> = emptyMap()
|
||||
override val items: Map<NameToken, MetaItem> = emptyMap()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get operations*/
|
||||
|
||||
/**
|
||||
* Perform recursive item search using given [name]. Each [NameToken] is treated as a name in [Meta.items] of a parent node.
|
||||
*
|
||||
* If [name] is empty return current [Meta] as a [NodeItem]
|
||||
*/
|
||||
public operator fun Meta?.get(name: Name): MetaItem<*>? = this?.getItem(name)
|
||||
|
||||
public operator fun Meta?.get(token: NameToken): MetaItem<*>? = this?.items?.get(token)
|
||||
|
||||
/**
|
||||
* Parse [Name] from [key] using full name notation and pass it to [Meta.get]
|
||||
*/
|
||||
public operator fun Meta?.get(key: String): MetaItem<*>? = get(key.toName())
|
||||
public operator fun Meta.get(token: NameToken): MetaItem? = items.get(token)
|
||||
|
||||
/**
|
||||
* Get a sequence of [Name]-[Value] pairs
|
||||
*/
|
||||
public fun Meta.values(): Sequence<Pair<Name, Value>> {
|
||||
public fun Meta.valueSequence(): Sequence<Pair<Name, Value>> {
|
||||
return items.asSequence().flatMap { (key, item) ->
|
||||
when (item) {
|
||||
is ValueItem -> sequenceOf(key.asName() to item.value)
|
||||
is NodeItem -> item.node.values().map { pair -> (key.asName() + pair.first) to pair.second }
|
||||
is MetaItemValue -> sequenceOf(key.asName() to item.value)
|
||||
is MetaItemNode -> item.node.valueSequence().map { pair -> (key.asName() + pair.first) to pair.second }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a sequence of all [Name]-[MetaItem] pairs for all items including nodes
|
||||
* Get a sequence of all [Name]-[TypedMetaItem] pairs for all items including nodes
|
||||
*/
|
||||
public fun Meta.sequence(): Sequence<Pair<Name, MetaItem<*>>> {
|
||||
return sequence {
|
||||
public fun Meta.itemSequence(): Sequence<Pair<Name, MetaItem>> = sequence {
|
||||
items.forEach { (key, item) ->
|
||||
yield(key.asName() to item)
|
||||
if (item is NodeItem<*>) {
|
||||
yieldAll(item.node.sequence().map { (innerKey, innerItem) ->
|
||||
if (item is MetaItemNode) {
|
||||
yieldAll(item.node.itemSequence().map { (innerKey, innerItem) ->
|
||||
(key + innerKey) to innerItem
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public operator fun Meta.iterator(): Iterator<Pair<Name, MetaItem<*>>> = sequence().iterator()
|
||||
|
||||
/**
|
||||
* A meta node that ensures that all of its descendants has at least the same type
|
||||
*/
|
||||
public interface MetaNode<out M : MetaNode<M>> : Meta {
|
||||
override val items: Map<NameToken, MetaItem<M>>
|
||||
}
|
||||
|
||||
/**
|
||||
* The same as [Meta.get], but with specific node type
|
||||
*/
|
||||
public operator fun <M : MetaNode<M>> M?.get(name: Name): MetaItem<M>? = if (this == null) {
|
||||
null
|
||||
} else {
|
||||
@Suppress("UNCHECKED_CAST", "ReplaceGetOrSet")
|
||||
(this as Meta).get(name) as MetaItem<M>? // Do not change
|
||||
}
|
||||
|
||||
public operator fun <M : MetaNode<M>> M?.get(key: String): MetaItem<M>? = this[key.toName()]
|
||||
|
||||
public operator fun <M : MetaNode<M>> M?.get(key: NameToken): MetaItem<M>? = this[key.asName()]
|
||||
|
||||
/**
|
||||
* Equals, hashcode and to string for any meta
|
||||
*/
|
||||
public abstract class MetaBase : Meta {
|
||||
|
||||
override fun equals(other: Any?): Boolean = if (other is Meta) {
|
||||
this.items == other.items
|
||||
} else {
|
||||
false
|
||||
}
|
||||
|
||||
override fun hashCode(): Int = items.hashCode()
|
||||
|
||||
override fun toString(): String = Json {
|
||||
prettyPrint = true
|
||||
useArrayPolymorphism = true
|
||||
}.encodeToString(MetaSerializer, this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Equals and hash code implementation for meta node
|
||||
*/
|
||||
public abstract class AbstractMetaNode<M : MetaNode<M>> : MetaNode<M>, MetaBase()
|
||||
|
||||
/**
|
||||
* The meta implementation which is guaranteed to be immutable.
|
||||
*
|
||||
* If the argument is possibly mutable node, it is copied on creation
|
||||
*/
|
||||
public class SealedMeta internal constructor(
|
||||
override val items: Map<NameToken, MetaItem<SealedMeta>>,
|
||||
) : AbstractMetaNode<SealedMeta>()
|
||||
|
||||
/**
|
||||
* Generate sealed node from [this]. If it is already sealed return it as is
|
||||
*/
|
||||
public fun Meta.seal(): SealedMeta = this as? SealedMeta ?: SealedMeta(items.mapValues { entry -> entry.value.seal() })
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
public fun MetaItem<*>.seal(): MetaItem<SealedMeta> = when (this) {
|
||||
is ValueItem -> this
|
||||
is NodeItem -> NodeItem(node.seal())
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsafe methods to access values and nodes directly from [MetaItem]
|
||||
*/
|
||||
public val MetaItem<*>?.value: Value?
|
||||
get() = (this as? ValueItem)?.value
|
||||
?: (this?.node?.get(VALUE_KEY) as? ValueItem)?.value
|
||||
|
||||
public val MetaItem<*>?.string: String? get() = value?.string
|
||||
public val MetaItem<*>?.boolean: Boolean? get() = value?.boolean
|
||||
public val MetaItem<*>?.number: Number? get() = value?.number
|
||||
public val MetaItem<*>?.double: Double? get() = number?.toDouble()
|
||||
public val MetaItem<*>?.float: Float? get() = number?.toFloat()
|
||||
public val MetaItem<*>?.int: Int? get() = number?.toInt()
|
||||
public val MetaItem<*>?.long: Long? get() = number?.toLong()
|
||||
public val MetaItem<*>?.short: Short? get() = number?.toShort()
|
||||
|
||||
public inline fun <reified E : Enum<E>> MetaItem<*>?.enum(): E? = if (this is ValueItem && this.value is EnumValue<*>) {
|
||||
this.value.value as E
|
||||
} else {
|
||||
string?.let { enumValueOf<E>(it) }
|
||||
}
|
||||
|
||||
public val MetaItem<*>.stringList: List<String>? get() = value?.list?.map { it.string }
|
||||
|
||||
public val <M : Meta> MetaItem<M>?.node: M?
|
||||
get() = when (this) {
|
||||
null -> null
|
||||
is ValueItem -> null//error("Trying to interpret value meta item as node item")
|
||||
is NodeItem -> node
|
||||
}
|
||||
public operator fun Meta.iterator(): Iterator<Pair<Name, MetaItem>> = itemSequence().iterator()
|
||||
|
||||
public fun Meta.isEmpty(): Boolean = this === Meta.EMPTY || this.items.isEmpty()
|
@ -1,5 +1,6 @@
|
||||
package hep.dataforge.meta
|
||||
|
||||
import hep.dataforge.misc.DFBuilder
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.values.EnumValue
|
||||
@ -12,10 +13,10 @@ import kotlin.jvm.JvmName
|
||||
*/
|
||||
@DFBuilder
|
||||
public class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
|
||||
override fun wrapNode(meta: Meta): MetaBuilder = if (meta is MetaBuilder) meta else meta.builder()
|
||||
override fun wrapNode(meta: Meta): MetaBuilder = if (meta is MetaBuilder) meta else meta.toMutableMeta()
|
||||
override fun empty(): MetaBuilder = MetaBuilder()
|
||||
|
||||
public infix fun String.put(item: MetaItem<*>?) {
|
||||
public infix fun String.put(item: MetaItem?) {
|
||||
set(this, item)
|
||||
}
|
||||
|
||||
@ -71,7 +72,7 @@ public class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
|
||||
set(this,value.toList())
|
||||
}
|
||||
|
||||
public infix fun String.put(metaBuilder: MetaBuilder.() -> Unit) {
|
||||
public inline infix fun String.put(metaBuilder: MetaBuilder.() -> Unit) {
|
||||
this@MetaBuilder[this] = MetaBuilder().apply(metaBuilder)
|
||||
}
|
||||
|
||||
@ -121,25 +122,20 @@ public class MetaBuilder : AbstractMutableMeta<MetaBuilder>() {
|
||||
/**
|
||||
* For safety, builder always copies the initial meta even if it is builder itself
|
||||
*/
|
||||
public fun Meta.builder(): MetaBuilder {
|
||||
public fun Meta.toMutableMeta(): MetaBuilder {
|
||||
return MetaBuilder().also { builder ->
|
||||
items.mapValues { entry ->
|
||||
val item = entry.value
|
||||
builder[entry.key.asName()] = when (item) {
|
||||
is MetaItem.ValueItem -> item.value
|
||||
is MetaItem.NodeItem -> MetaItem.NodeItem(item.node.builder())
|
||||
is MetaItemValue -> item.value
|
||||
is MetaItemNode -> MetaItemNode(item.node.toMutableMeta())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a deep copy of this meta and apply builder to it
|
||||
*/
|
||||
public fun Meta.edit(builder: MetaBuilder.() -> Unit): MetaBuilder = builder().apply(builder)
|
||||
|
||||
/**
|
||||
* Build a [MetaBuilder] using given transformation
|
||||
*/
|
||||
@Suppress("FunctionName")
|
||||
public fun Meta(builder: MetaBuilder.() -> Unit): MetaBuilder = MetaBuilder().apply(builder)
|
||||
public inline fun Meta(builder: MetaBuilder.() -> Unit): MetaBuilder = MetaBuilder().apply(builder)
|
@ -0,0 +1,90 @@
|
||||
package hep.dataforge.meta
|
||||
|
||||
import hep.dataforge.values.*
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* A member of the meta tree. Could be represented as one of following:
|
||||
* * a [MetaItemValue] (leaf)
|
||||
* * a [MetaItemNode] (node)
|
||||
*/
|
||||
@Serializable(MetaItemSerializer::class)
|
||||
public sealed class TypedMetaItem<out M : Meta>() {
|
||||
|
||||
abstract override fun equals(other: Any?): Boolean
|
||||
|
||||
abstract override fun hashCode(): Int
|
||||
|
||||
public companion object {
|
||||
public fun of(arg: Any?): MetaItem {
|
||||
return when (arg) {
|
||||
null -> Null.asMetaItem()
|
||||
is MetaItem -> arg
|
||||
is Meta -> arg.asMetaItem()
|
||||
is ItemProvider -> arg.rootItem ?: Null.asMetaItem()
|
||||
else -> Value.of(arg).asMetaItem()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public typealias MetaItem = TypedMetaItem<*>
|
||||
|
||||
@Serializable(MetaItemSerializer::class)
|
||||
public class MetaItemValue(public val value: Value) : TypedMetaItem<Nothing>() {
|
||||
override fun toString(): String = value.toString()
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return this.value == (other as? MetaItemValue)?.value
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return value.hashCode()
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable(MetaItemSerializer::class)
|
||||
public class MetaItemNode<M : Meta>(public val node: M) : TypedMetaItem<M>() {
|
||||
//Fixing serializer for node could cause class cast problems, but it should not since Meta descendants are not serializable
|
||||
override fun toString(): String = node.toString()
|
||||
|
||||
override fun equals(other: Any?): Boolean = node == (other as? MetaItemNode<*>)?.node
|
||||
|
||||
override fun hashCode(): Int = node.hashCode()
|
||||
}
|
||||
|
||||
public fun Value.asMetaItem(): MetaItemValue = MetaItemValue(this)
|
||||
public fun <M : Meta> M.asMetaItem(): MetaItemNode<M> = MetaItemNode(this)
|
||||
|
||||
|
||||
/**
|
||||
* Unsafe methods to access values and nodes directly from [TypedMetaItem]
|
||||
*/
|
||||
public val MetaItem?.value: Value?
|
||||
get() = (this as? MetaItemValue)?.value
|
||||
?: (this?.node?.get(Meta.VALUE_KEY) as? MetaItemValue)?.value
|
||||
|
||||
public val MetaItem?.string: String? get() = value?.string
|
||||
public val MetaItem?.boolean: Boolean? get() = value?.boolean
|
||||
public val MetaItem?.number: Number? get() = value?.numberOrNull
|
||||
public val MetaItem?.double: Double? get() = number?.toDouble()
|
||||
public val MetaItem?.float: Float? get() = number?.toFloat()
|
||||
public val MetaItem?.int: Int? get() = number?.toInt()
|
||||
public val MetaItem?.long: Long? get() = number?.toLong()
|
||||
public val MetaItem?.short: Short? get() = number?.toShort()
|
||||
|
||||
public inline fun <reified E : Enum<E>> MetaItem?.enum(): E? =
|
||||
if (this is MetaItemValue && this.value is EnumValue<*>) {
|
||||
this.value.value as E
|
||||
} else {
|
||||
string?.let { enumValueOf<E>(it) }
|
||||
}
|
||||
|
||||
public val MetaItem.stringList: List<String>? get() = value?.list?.map { it.string }
|
||||
|
||||
public val <M : Meta> TypedMetaItem<M>?.node: M?
|
||||
get() = when (this) {
|
||||
null -> null
|
||||
is MetaItemValue -> null//error("Trying to interpret value meta item as node item")
|
||||
is MetaItemNode -> node
|
||||
}
|
@ -12,16 +12,15 @@ import kotlinx.serialization.json.JsonDecoder
|
||||
import kotlinx.serialization.json.JsonEncoder
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
|
||||
@OptIn(ExperimentalSerializationApi::class)
|
||||
public object MetaItemSerializer : KSerializer<MetaItem<*>> {
|
||||
public object MetaItemSerializer : KSerializer<MetaItem> {
|
||||
|
||||
@OptIn(InternalSerializationApi::class)
|
||||
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("hep.dataforge.meta.MetaItem") {
|
||||
@OptIn(InternalSerializationApi::class, ExperimentalSerializationApi::class)
|
||||
override val descriptor: SerialDescriptor = buildSerialDescriptor("MetaItem", PolymorphicKind.SEALED) {
|
||||
element<Boolean>("isNode")
|
||||
element("content", buildSerialDescriptor("MetaItem.content", PolymorphicKind.SEALED))
|
||||
element("value", buildSerialDescriptor("MetaItem.value", SerialKind.CONTEXTUAL))
|
||||
}
|
||||
|
||||
override fun deserialize(decoder: Decoder): MetaItem<*> {
|
||||
override fun deserialize(decoder: Decoder): MetaItem {
|
||||
decoder.decodeStructure(descriptor) {
|
||||
//Force strict serialization order
|
||||
require(decodeElementIndex(descriptor) == 0) { "Node flag must be first item serialized" }
|
||||
@ -37,12 +36,12 @@ public object MetaItemSerializer : KSerializer<MetaItem<*>> {
|
||||
}
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: MetaItem<*>) {
|
||||
override fun serialize(encoder: Encoder, value: MetaItem) {
|
||||
encoder.encodeStructure(descriptor) {
|
||||
encodeBooleanElement(descriptor, 0, value is MetaItem.NodeItem)
|
||||
encodeBooleanElement(descriptor, 0, value is MetaItemNode)
|
||||
when (value) {
|
||||
is MetaItem.ValueItem -> encodeSerializableElement(descriptor, 1, ValueSerializer, value.value)
|
||||
is MetaItem.NodeItem -> encodeSerializableElement(descriptor, 1, MetaSerializer, value.node)
|
||||
is MetaItemValue -> encodeSerializableElement(descriptor, 1, ValueSerializer, value.value)
|
||||
is MetaItemNode -> encodeSerializableElement(descriptor, 1, MetaSerializer, value.node)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -53,19 +52,19 @@ public object MetaItemSerializer : KSerializer<MetaItem<*>> {
|
||||
*/
|
||||
public object MetaSerializer : KSerializer<Meta> {
|
||||
|
||||
private val mapSerializer: KSerializer<Map<NameToken, MetaItem<Meta>>> = MapSerializer(
|
||||
private val mapSerializer: KSerializer<Map<NameToken, TypedMetaItem<Meta>>> = MapSerializer(
|
||||
NameToken,
|
||||
MetaItemSerializer//MetaItem.serializer(MetaSerializer)
|
||||
)
|
||||
|
||||
override val descriptor: SerialDescriptor get() = mapSerializer.descriptor
|
||||
override val descriptor: SerialDescriptor = buildClassSerialDescriptor("Meta")
|
||||
|
||||
override fun deserialize(decoder: Decoder): Meta {
|
||||
return if (decoder is JsonDecoder) {
|
||||
JsonObject.serializer().deserialize(decoder).toMeta()
|
||||
} else {
|
||||
object : MetaBase() {
|
||||
override val items: Map<NameToken, MetaItem<*>> = mapSerializer.deserialize(decoder)
|
||||
override val items: Map<NameToken, MetaItem> = mapSerializer.deserialize(decoder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +0,0 @@
|
||||
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)
|
@ -3,32 +3,29 @@ package hep.dataforge.meta
|
||||
import hep.dataforge.meta.transformations.MetaConverter
|
||||
import hep.dataforge.names.Name
|
||||
import hep.dataforge.names.asName
|
||||
import hep.dataforge.values.DoubleArrayValue
|
||||
import hep.dataforge.values.Value
|
||||
import hep.dataforge.values.asValue
|
||||
import hep.dataforge.values.doubleArray
|
||||
import hep.dataforge.values.*
|
||||
import kotlin.properties.ReadWriteProperty
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
/* Read-write delegates */
|
||||
|
||||
public typealias MutableItemDelegate = ReadWriteProperty<Any?, MetaItem<*>?>
|
||||
public typealias MutableItemDelegate = ReadWriteProperty<Any?, MetaItem?>
|
||||
|
||||
public fun MutableItemProvider.item(key: Name? = null): MutableItemDelegate = object : MutableItemDelegate {
|
||||
override fun getValue(thisRef: Any?, property: KProperty<*>): MetaItem<*>? {
|
||||
return getItem(key ?: property.name.asName())
|
||||
override fun getValue(thisRef: Any?, property: KProperty<*>): MetaItem? {
|
||||
return get(key ?: property.name.asName())
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: MetaItem<*>?) {
|
||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: MetaItem?) {
|
||||
val name = key ?: property.name.asName()
|
||||
setItem(name, value)
|
||||
set(name, value)
|
||||
}
|
||||
}
|
||||
|
||||
/* Mutable converters */
|
||||
|
||||
/**
|
||||
* A type converter for a mutable [MetaItem] delegate
|
||||
* A type converter for a mutable [TypedMetaItem] delegate
|
||||
*/
|
||||
public fun <R : Any> MutableItemDelegate.convert(
|
||||
converter: MetaConverter<R>,
|
||||
@ -58,8 +55,8 @@ public fun <R : Any> MutableItemDelegate.convert(
|
||||
}
|
||||
|
||||
public fun <R> MutableItemDelegate.convert(
|
||||
reader: (MetaItem<*>?) -> R,
|
||||
writer: (R) -> MetaItem<*>?,
|
||||
reader: (MetaItem?) -> R,
|
||||
writer: (R) -> MetaItem?,
|
||||
): ReadWriteProperty<Any?, R> = object : ReadWriteProperty<Any?, R> {
|
||||
|
||||
override fun getValue(thisRef: Any?, property: KProperty<*>): R =
|
||||
@ -72,7 +69,6 @@ public fun <R> MutableItemDelegate.convert(
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Read-write delegates for [MutableItemProvider] */
|
||||
|
||||
/**
|
||||
@ -117,8 +113,13 @@ public inline fun <reified E : Enum<E>> MutableItemProvider.enum(
|
||||
): ReadWriteProperty<Any?, E> =
|
||||
item(key).convert(MetaConverter.enum()) { default }
|
||||
|
||||
public fun MutableItemProvider.node(key: Name? = null): ReadWriteProperty<Any?, Meta?> = item(key).convert(
|
||||
reader = { it.node },
|
||||
writer = { it?.asMetaItem() }
|
||||
)
|
||||
|
||||
public inline fun <reified M : MutableMeta<M>> M.node(key: Name? = null): ReadWriteProperty<Any?, M?> =
|
||||
item(key).convert(reader = { it?.let { it.node as M } }, writer = { it?.let { MetaItem.NodeItem(it) } })
|
||||
item(key).convert(reader = { it?.let { it.node as M } }, writer = { it?.let { MetaItemNode(it) } })
|
||||
|
||||
/* Number delegates */
|
||||
|
||||
@ -171,7 +172,7 @@ public fun MutableItemProvider.numberList(
|
||||
vararg default: Number,
|
||||
key: Name? = null,
|
||||
): ReadWriteProperty<Any?, List<Number>> = item(key).convert(
|
||||
reader = { it?.value?.list?.map { value -> value.number } ?: listOf(*default) },
|
||||
reader = { it?.value?.list?.map { value -> value.numberOrNull ?: Double.NaN } ?: listOf(*default) },
|
||||
writer = { it.map { num -> num.asValue() }.asValue().asMetaItem() }
|
||||
)
|
||||
|
||||
|
@ -2,32 +2,20 @@ 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 setItem(name: Name, item: MetaItem?)
|
||||
}
|
||||
|
||||
public fun MutableItemProvider.getItem(key: String): MetaItem<*>? = getItem(key.toName())
|
||||
public operator fun MutableItemProvider.set(name: Name, item: MetaItem?): Unit = setItem(name, item)
|
||||
|
||||
public fun MutableItemProvider.setValue(name: Name, value: Value?): Unit =
|
||||
setItem(name, value?.let { MetaItem.ValueItem(value) })
|
||||
public operator fun MutableItemProvider.set(name: Name, value: Value?): Unit = set(name, value?.asMetaItem())
|
||||
|
||||
public fun MutableItemProvider.setNode(name: Name, meta: Meta?): Unit =
|
||||
setItem(name, meta?.let { MetaItem.NodeItem(meta) })
|
||||
public operator fun MutableItemProvider.set(name: Name, meta: Meta?): Unit = set(name, meta?.asMetaItem())
|
||||
|
||||
public fun MutableItemProvider.setItem(key: String, item: MetaItem<*>?): Unit = setItem(key.toName(), item)
|
||||
public operator fun MutableItemProvider.set(key: String, item: MetaItem?): Unit = set(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) } }
|
||||
)
|
||||
public operator fun MutableItemProvider.set(key: String, meta: Meta?): Unit = set(key, meta?.asMetaItem())
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
public inline fun MutableItemProvider.remove(name: Name): Unit = setItem(name, null)
|
||||
@ -35,17 +23,13 @@ public inline fun MutableItemProvider.remove(name: Name): Unit = setItem(name, n
|
||||
@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))
|
||||
else -> set(name, MetaItem.of(value))
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,30 +43,87 @@ public operator fun MutableItemProvider.set(key: String, index: String, value: A
|
||||
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() }
|
||||
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)
|
||||
set(Name(tokens), meta)
|
||||
}
|
||||
}
|
||||
|
||||
public fun MutableItemProvider.setIndexed(
|
||||
name: Name,
|
||||
metas: Iterable<Meta>,
|
||||
indexFactory: (Meta, index: Int) -> String = { _, index -> index.toString() }
|
||||
indexFactory: (Meta, index: Int) -> String = { _, index -> index.toString() },
|
||||
) {
|
||||
setIndexedItems(name, metas.map { MetaItem.NodeItem(it) }) { item, index -> indexFactory(item.node!!, index) }
|
||||
setIndexedItems(name, metas.map { MetaItemNode(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)
|
||||
public operator fun MutableItemProvider.set(name: String, metas: Iterable<Meta>): Unit =
|
||||
setIndexed(name.toName(), metas)
|
||||
|
||||
/**
|
||||
* Get a [MutableItemProvider] referencing a child node
|
||||
*/
|
||||
public fun MutableItemProvider.getChild(childName: Name): MutableItemProvider {
|
||||
fun createProvider() = object : MutableItemProvider {
|
||||
override fun setItem(name: Name, item: MetaItem?) {
|
||||
this@getChild.setItem(childName + name, item)
|
||||
}
|
||||
|
||||
override fun getItem(name: Name): MetaItem? = this@getChild.getItem(childName + name)
|
||||
}
|
||||
|
||||
return when {
|
||||
childName.isEmpty() -> this
|
||||
this is MutableMeta<*> -> {
|
||||
get(childName).node ?: createProvider()
|
||||
}
|
||||
else -> {
|
||||
createProvider()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun MutableItemProvider.getChild(childName: String): MutableItemProvider = getChild(childName.toName())
|
||||
|
||||
/**
|
||||
* Update existing mutable node with another node. The rules are following:
|
||||
* * value replaces anything
|
||||
* * node updates node and replaces anything but node
|
||||
* * node list updates node list if number of nodes in the list is the same and replaces anything otherwise
|
||||
*/
|
||||
public fun MutableItemProvider.update(meta: Meta) {
|
||||
meta.valueSequence().forEach { (name, value) -> set(name, value) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a provider child at given name location
|
||||
*/
|
||||
public fun MutableItemProvider.editChild(name: Name, builder: MutableItemProvider.() -> Unit): MutableItemProvider =
|
||||
getChild(name).apply(builder)
|
||||
|
||||
/**
|
||||
* Create a mutable item provider that uses given provider for default values if those are not found in this provider.
|
||||
* Changes are propagated only to this provider.
|
||||
*/
|
||||
public fun MutableItemProvider.withDefault(default: ItemProvider?): MutableItemProvider =
|
||||
if (default == null || (default is Meta && default.isEmpty())) {
|
||||
//Optimize for use with empty default
|
||||
this
|
||||
} else object : MutableItemProvider {
|
||||
override fun setItem(name: Name, item: MetaItem?) {
|
||||
this@withDefault.setItem(name, item)
|
||||
}
|
||||
|
||||
override fun getItem(name: Name): MetaItem? = this@withDefault.getItem(name) ?: default.getItem(name)
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user