Migration to 1.4
This commit is contained in:
parent
b8d775aa30
commit
57b263ec63
@ -1,13 +1,10 @@
|
|||||||
plugins {
|
plugins {
|
||||||
val toolsVersion = "0.6.0"
|
id("kscience.publish") apply false
|
||||||
id("kscience.mpp") version toolsVersion apply false
|
|
||||||
id("kscience.jvm") version toolsVersion apply false
|
|
||||||
id("kscience.publish") version toolsVersion apply false
|
|
||||||
id("org.jetbrains.dokka") version "1.4.0-rc"
|
id("org.jetbrains.dokka") version "1.4.0-rc"
|
||||||
id("org.jetbrains.changelog") version "0.4.0"
|
id("org.jetbrains.changelog") version "0.4.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
val dataforgeVersion by extra("0.1.9-dev-1")
|
val dataforgeVersion by extra("0.1.9-dev-2")
|
||||||
|
|
||||||
val bintrayRepo by extra("dataforge")
|
val bintrayRepo by extra("dataforge")
|
||||||
val githubProject by extra("dataforge-core")
|
val githubProject by extra("dataforge-core")
|
||||||
|
@ -4,16 +4,20 @@ plugins {
|
|||||||
|
|
||||||
description = "Context and provider definitions"
|
description = "Context and provider definitions"
|
||||||
|
|
||||||
kscience{
|
kscience {
|
||||||
useCoroutines()
|
useCoroutines()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
maven("https://maven.pkg.github.com/altavir/kotlin-logging")
|
||||||
|
}
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
sourceSets {
|
sourceSets {
|
||||||
val commonMain by getting {
|
val commonMain by getting {
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":dataforge-meta"))
|
api(project(":dataforge-meta"))
|
||||||
api("io.github.microutils:kotlin-logging:1.9.0")
|
api("io.github.microutils:kotlin-logging:1.9.0-dev-npm")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val jvmMain by getting {
|
val jvmMain by getting {
|
||||||
|
@ -20,12 +20,12 @@ 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
|
* Check if node could be safely cast to given class
|
||||||
*/
|
*/
|
||||||
expect fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean
|
internal expect fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if data could be safely cast to given class
|
* Check if data could be safely cast to given class
|
||||||
*/
|
*/
|
||||||
expect fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean
|
internal expect fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean
|
||||||
|
|
||||||
fun <R : Any> DataItem<*>.canCast(type: KClass<out R>): Boolean = when (this) {
|
fun <R : Any> DataItem<*>.canCast(type: KClass<out R>): Boolean = when (this) {
|
||||||
is DataItem.Node -> node.canCast(type)
|
is DataItem.Node -> node.canCast(type)
|
||||||
|
@ -5,12 +5,12 @@ import kotlin.reflect.KClass
|
|||||||
/**
|
/**
|
||||||
* Check that node is compatible with given type meaning that each element could be cast to the type
|
* Check that node is compatible with given type meaning that each element could be cast to the type
|
||||||
*/
|
*/
|
||||||
actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean {
|
internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean {
|
||||||
//Not supported in js yet
|
//Not supported in js yet
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean {
|
internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean {
|
||||||
//Not supported in js yet
|
//Not supported in js yet
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -8,28 +8,28 @@ import kotlin.reflect.full.isSuperclassOf
|
|||||||
/**
|
/**
|
||||||
* Block the thread and get data content
|
* Block the thread and get data content
|
||||||
*/
|
*/
|
||||||
fun <T : Any> Data<T>.get(): T = runBlocking { await() }
|
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
|
* Check that node is compatible with given type meaning that each element could be cast to the type
|
||||||
*/
|
*/
|
||||||
actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean =
|
internal actual fun <R : Any> DataNode<*>.canCast(type: KClass<out R>): Boolean =
|
||||||
type.isSuperclassOf(type)
|
type.isSuperclassOf(type)
|
||||||
|
|
||||||
actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean =
|
internal actual fun <R : Any> Data<*>.canCast(type: KClass<out R>): Boolean =
|
||||||
this.type.isSubclassOf(type)
|
this.type.isSubclassOf(type)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Cast the node to given type if the cast is possible or return null
|
* Cast the node to given type if the cast is possible or return null
|
||||||
*/
|
*/
|
||||||
fun <R : Any> Data<*>.filterIsInstance(type: KClass<out R>): Data<R>? =
|
public fun <R : Any> Data<*>.filterIsInstance(type: KClass<out R>): Data<R>? =
|
||||||
if (canCast(type)) cast(type) else null
|
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],
|
* 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
|
* but could contain empty nodes
|
||||||
*/
|
*/
|
||||||
fun <R : Any> DataNode<*>.filterIsInstance(type: KClass<out R>): DataNode<R> {
|
public fun <R : Any> DataNode<*>.filterIsInstance(type: KClass<out R>): DataNode<R> {
|
||||||
return when {
|
return when {
|
||||||
canCast(type) -> cast(type)
|
canCast(type) -> cast(type)
|
||||||
this is TypeFilteredDataNode -> origin.filterIsInstance(type)
|
this is TypeFilteredDataNode -> origin.filterIsInstance(type)
|
||||||
|
@ -0,0 +1,11 @@
|
|||||||
|
package hep.dataforge.io
|
||||||
|
|
||||||
|
import hep.dataforge.meta.DFExperimental
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A fire-and-forget consumer of messages
|
||||||
|
*/
|
||||||
|
@DFExperimental
|
||||||
|
public interface Consumer {
|
||||||
|
public fun consume(message: Envelope): Unit
|
||||||
|
}
|
@ -1,21 +1,12 @@
|
|||||||
package hep.dataforge.io
|
package hep.dataforge.io
|
||||||
|
|
||||||
import hep.dataforge.meta.DFExperimental
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An object that could respond to external messages asynchronously
|
* An object that could respond to external messages asynchronously
|
||||||
*/
|
*/
|
||||||
interface Responder {
|
public interface Responder {
|
||||||
/**
|
/**
|
||||||
* Send a request and wait for response for this specific request
|
* Send a request and wait for response for this specific request
|
||||||
*/
|
*/
|
||||||
suspend fun respond(request: Envelope): Envelope
|
public suspend fun respond(request: Envelope): Envelope
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* A fire-and-forget consumer of messages
|
|
||||||
*/
|
|
||||||
@DFExperimental
|
|
||||||
interface Consumer {
|
|
||||||
fun consume(message: Envelope): Unit
|
|
||||||
}
|
|
@ -4,16 +4,13 @@ import hep.dataforge.names.Name
|
|||||||
import hep.dataforge.names.NameToken
|
import hep.dataforge.names.NameToken
|
||||||
import hep.dataforge.names.asName
|
import hep.dataforge.names.asName
|
||||||
import hep.dataforge.names.plus
|
import hep.dataforge.names.plus
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.Serializer
|
import kotlinx.serialization.Serializer
|
||||||
import kotlinx.serialization.descriptors.SerialDescriptor
|
import kotlinx.serialization.descriptors.SerialDescriptor
|
||||||
import kotlinx.serialization.encoding.Decoder
|
import kotlinx.serialization.encoding.Decoder
|
||||||
import kotlinx.serialization.encoding.Encoder
|
import kotlinx.serialization.encoding.Encoder
|
||||||
import kotlin.collections.HashSet
|
|
||||||
import kotlin.collections.forEach
|
|
||||||
import kotlin.collections.mapValues
|
|
||||||
import kotlin.collections.removeAll
|
|
||||||
import kotlin.collections.set
|
import kotlin.collections.set
|
||||||
|
|
||||||
//TODO add validator to configuration
|
//TODO add validator to configuration
|
||||||
@ -24,15 +21,15 @@ public data class MetaListener(
|
|||||||
)
|
)
|
||||||
|
|
||||||
public interface ObservableMeta : Meta {
|
public interface ObservableMeta : Meta {
|
||||||
fun onChange(owner: Any?, action: (name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) -> Unit)
|
public fun onChange(owner: Any?, action: (name: Name, oldItem: MetaItem<*>?, newItem: MetaItem<*>?) -> Unit)
|
||||||
fun removeListener(owner: Any?)
|
public fun removeListener(owner: Any?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Mutable meta representing object state
|
* Mutable meta representing object state
|
||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
class Config : AbstractMutableMeta<Config>(), ObservableMeta {
|
public class Config : AbstractMutableMeta<Config>(), ObservableMeta {
|
||||||
|
|
||||||
private val listeners = HashSet<MetaListener>()
|
private val listeners = HashSet<MetaListener>()
|
||||||
|
|
||||||
@ -78,10 +75,11 @@ class Config : AbstractMutableMeta<Config>(), ObservableMeta {
|
|||||||
|
|
||||||
override fun empty(): Config = Config()
|
override fun empty(): Config = Config()
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
@Serializer(Config::class)
|
@Serializer(Config::class)
|
||||||
companion object ConfigSerializer : KSerializer<Config> {
|
public companion object ConfigSerializer : KSerializer<Config> {
|
||||||
|
|
||||||
fun empty(): Config = Config()
|
public fun empty(): Config = Config()
|
||||||
override val descriptor: SerialDescriptor get() = MetaSerializer.descriptor
|
override val descriptor: SerialDescriptor get() = MetaSerializer.descriptor
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): Config {
|
override fun deserialize(decoder: Decoder): Config {
|
||||||
@ -94,9 +92,9 @@ class Config : AbstractMutableMeta<Config>(), ObservableMeta {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun Config.get(token: NameToken): MetaItem<Config>? = items[token]
|
public operator fun Config.get(token: NameToken): MetaItem<Config>? = items[token]
|
||||||
|
|
||||||
fun Meta.asConfig(): Config = this as? Config ?: Config().also { builder ->
|
public fun Meta.asConfig(): Config = this as? Config ?: Config().also { builder ->
|
||||||
this.items.mapValues { entry ->
|
this.items.mapValues { entry ->
|
||||||
val item = entry.value
|
val item = entry.value
|
||||||
builder[entry.key.asName()] = when (item) {
|
builder[entry.key.asName()] = when (item) {
|
||||||
|
@ -14,21 +14,21 @@ import kotlin.reflect.KProperty
|
|||||||
* It is not possible to know if some property is declared by provider just by looking on [Configurable],
|
* It is not possible to know if some property is declared by provider just by looking on [Configurable],
|
||||||
* this information should be provided externally.
|
* this information should be provided externally.
|
||||||
*/
|
*/
|
||||||
interface Configurable : Described, MutableItemProvider {
|
public interface Configurable : Described, MutableItemProvider {
|
||||||
/**
|
/**
|
||||||
* Backing config
|
* Backing config
|
||||||
*/
|
*/
|
||||||
val config: Config
|
public val config: Config
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default meta item provider
|
* Default meta item provider
|
||||||
*/
|
*/
|
||||||
fun getDefaultItem(name: Name): MetaItem<*>? = null
|
public fun getDefaultItem(name: Name): MetaItem<*>? = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if property with given [name] could be assigned to [item]
|
* Check if property with given [name] could be assigned to [item]
|
||||||
*/
|
*/
|
||||||
fun validateItem(name: Name, item: MetaItem<*>?): Boolean {
|
public fun validateItem(name: Name, item: MetaItem<*>?): Boolean {
|
||||||
val descriptor = descriptor?.get(name)
|
val descriptor = descriptor?.get(name)
|
||||||
return descriptor?.validateItem(item) ?: true
|
return descriptor?.validateItem(item) ?: true
|
||||||
}
|
}
|
||||||
@ -53,40 +53,32 @@ interface Configurable : Described, MutableItemProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public fun Configurable.getItem(key: String): MetaItem<*>? = getItem(key.toName())
|
||||||
* Reset the property to its default value
|
|
||||||
*/
|
|
||||||
@Deprecated("To be removed since unused", ReplaceWith("setItem(name, null)"))
|
|
||||||
fun Configurable.resetProperty(name: Name) {
|
|
||||||
setItem(name, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Configurable.getItem(key: String) = getItem(key.toName())
|
public fun Configurable.setItem(name: Name, value: Value?): Unit = setItem(name, value?.let { MetaItem.ValueItem(value) })
|
||||||
|
public fun Configurable.setItem(name: Name, meta: Meta?): Unit = setItem(name, meta?.let { MetaItem.NodeItem(meta) })
|
||||||
|
|
||||||
fun Configurable.setItem(name: Name, value: Value?) = setItem(name, value?.let { MetaItem.ValueItem(value) })
|
public fun Configurable.setItem(key: String, item: MetaItem<*>?): Unit = setItem(key.toName(), item)
|
||||||
fun Configurable.setItem(name: Name, meta: Meta?) = setItem(name, meta?.let { MetaItem.NodeItem(meta) })
|
|
||||||
|
|
||||||
fun Configurable.setItem(key: String, item: MetaItem<*>?) = setItem(key.toName(), item)
|
public fun Configurable.setItem(key: String, value: Value?): Unit = setItem(key, value?.let { MetaItem.ValueItem(value) })
|
||||||
|
public fun Configurable.setItem(key: String, meta: Meta?): Unit = setItem(key, meta?.let { MetaItem.NodeItem(meta) })
|
||||||
|
|
||||||
fun Configurable.setItem(key: String, value: Value?) = setItem(key, value?.let { MetaItem.ValueItem(value) })
|
public fun <T : Configurable> T.configure(meta: Meta): T = this.apply { config.update(meta) }
|
||||||
fun Configurable.setItem(key: String, meta: Meta?) = setItem(key, meta?.let { MetaItem.NodeItem(meta) })
|
|
||||||
|
|
||||||
fun <T : Configurable> T.configure(meta: Meta): T = this.apply { config.update(meta) }
|
|
||||||
|
|
||||||
@DFBuilder
|
@DFBuilder
|
||||||
inline fun <T : Configurable> T.configure(action: Config.() -> Unit): T = apply { config.apply(action) }
|
public inline fun <T : Configurable> T.configure(action: Config.() -> Unit): T = apply { config.apply(action) }
|
||||||
|
|
||||||
/* Node delegates */
|
/* Node delegates */
|
||||||
|
|
||||||
fun Configurable.config(key: Name? = null): ReadWriteProperty<Any?, Config?> =
|
public fun Configurable.config(key: Name? = null): ReadWriteProperty<Any?, Config?> =
|
||||||
config.node(key)
|
config.node(key)
|
||||||
|
|
||||||
fun MutableItemProvider.node(key: Name? = null): ReadWriteProperty<Any?, Meta?> = item(key).convert(
|
public fun MutableItemProvider.node(key: Name? = null): ReadWriteProperty<Any?, Meta?> = item(key).convert(
|
||||||
reader = { it.node },
|
reader = { it.node },
|
||||||
writer = { it?.let { MetaItem.NodeItem(it) } }
|
writer = { it?.let { MetaItem.NodeItem(it) } }
|
||||||
)
|
)
|
||||||
|
|
||||||
fun <T : Configurable> Configurable.spec(
|
public fun <T : Configurable> Configurable.spec(
|
||||||
spec: Specification<T>, key: Name? = null
|
spec: Specification<T>, key: Name? = null
|
||||||
): ReadWriteProperty<Any?, T?> = object : ReadWriteProperty<Any?, T?> {
|
): ReadWriteProperty<Any?, T?> = object : ReadWriteProperty<Any?, T?> {
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
|
override fun getValue(thisRef: Any?, property: KProperty<*>): T? {
|
||||||
@ -100,7 +92,7 @@ fun <T : Configurable> Configurable.spec(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T : Configurable> Configurable.spec(
|
public fun <T : Configurable> Configurable.spec(
|
||||||
spec: Specification<T>, default: T, key: Name? = null
|
spec: Specification<T>, default: T, key: Name? = null
|
||||||
): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> {
|
): ReadWriteProperty<Any?, T> = object : ReadWriteProperty<Any?, T> {
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
override fun getValue(thisRef: Any?, property: KProperty<*>): T {
|
||||||
|
@ -19,7 +19,7 @@ open class ItemDelegate(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ItemProvider.item(key: Name? = null): ItemDelegate = ItemDelegate(this, key)
|
public fun ItemProvider.item(key: Name? = null): ItemDelegate = ItemDelegate(this, key)
|
||||||
|
|
||||||
//TODO add caching for sealed nodes
|
//TODO add caching for sealed nodes
|
||||||
|
|
||||||
@ -29,62 +29,62 @@ fun ItemProvider.item(key: Name? = null): ItemDelegate = ItemDelegate(this, key)
|
|||||||
/**
|
/**
|
||||||
* A property delegate that uses custom key
|
* A property delegate that uses custom key
|
||||||
*/
|
*/
|
||||||
fun ItemProvider.value(key: Name? = null): ReadOnlyProperty<Any?, Value?> =
|
public fun ItemProvider.value(key: Name? = null): ReadOnlyProperty<Any?, Value?> =
|
||||||
item(key).convert(MetaConverter.value)
|
item(key).convert(MetaConverter.value)
|
||||||
|
|
||||||
fun ItemProvider.string(key: Name? = null): ReadOnlyProperty<Any?, String?> =
|
public fun ItemProvider.string(key: Name? = null): ReadOnlyProperty<Any?, String?> =
|
||||||
item(key).convert(MetaConverter.string)
|
item(key).convert(MetaConverter.string)
|
||||||
|
|
||||||
fun ItemProvider.boolean(key: Name? = null): ReadOnlyProperty<Any?, Boolean?> =
|
public fun ItemProvider.boolean(key: Name? = null): ReadOnlyProperty<Any?, Boolean?> =
|
||||||
item(key).convert(MetaConverter.boolean)
|
item(key).convert(MetaConverter.boolean)
|
||||||
|
|
||||||
fun ItemProvider.number(key: Name? = null): ReadOnlyProperty<Any?, Number?> =
|
public fun ItemProvider.number(key: Name? = null): ReadOnlyProperty<Any?, Number?> =
|
||||||
item(key).convert(MetaConverter.number)
|
item(key).convert(MetaConverter.number)
|
||||||
|
|
||||||
fun ItemProvider.double(key: Name? = null): ReadOnlyProperty<Any?, Double?> =
|
public fun ItemProvider.double(key: Name? = null): ReadOnlyProperty<Any?, Double?> =
|
||||||
item(key).convert(MetaConverter.double)
|
item(key).convert(MetaConverter.double)
|
||||||
|
|
||||||
fun ItemProvider.float(key: Name? = null): ReadOnlyProperty<Any?, Float?> =
|
public fun ItemProvider.float(key: Name? = null): ReadOnlyProperty<Any?, Float?> =
|
||||||
item(key).convert(MetaConverter.float)
|
item(key).convert(MetaConverter.float)
|
||||||
|
|
||||||
fun ItemProvider.int(key: Name? = null): ReadOnlyProperty<Any?, Int?> =
|
public fun ItemProvider.int(key: Name? = null): ReadOnlyProperty<Any?, Int?> =
|
||||||
item(key).convert(MetaConverter.int)
|
item(key).convert(MetaConverter.int)
|
||||||
|
|
||||||
fun ItemProvider.long(key: Name? = null): ReadOnlyProperty<Any?, Long?> =
|
public fun ItemProvider.long(key: Name? = null): ReadOnlyProperty<Any?, Long?> =
|
||||||
item(key).convert(MetaConverter.long)
|
item(key).convert(MetaConverter.long)
|
||||||
|
|
||||||
fun ItemProvider.node(key: Name? = null): ReadOnlyProperty<Any?, Meta?> =
|
public fun ItemProvider.node(key: Name? = null): ReadOnlyProperty<Any?, Meta?> =
|
||||||
item(key).convert(MetaConverter.meta)
|
item(key).convert(MetaConverter.meta)
|
||||||
|
|
||||||
fun ItemProvider.string(default: String, key: Name? = null): ReadOnlyProperty<Any?, String> =
|
public fun ItemProvider.string(default: String, key: Name? = null): ReadOnlyProperty<Any?, String> =
|
||||||
item(key).convert(MetaConverter.string) { default }
|
item(key).convert(MetaConverter.string) { default }
|
||||||
|
|
||||||
fun ItemProvider.boolean(default: Boolean, key: Name? = null): ReadOnlyProperty<Any?, Boolean> =
|
public fun ItemProvider.boolean(default: Boolean, key: Name? = null): ReadOnlyProperty<Any?, Boolean> =
|
||||||
item(key).convert(MetaConverter.boolean) { default }
|
item(key).convert(MetaConverter.boolean) { default }
|
||||||
|
|
||||||
fun ItemProvider.number(default: Number, key: Name? = null): ReadOnlyProperty<Any?, Number> =
|
public fun ItemProvider.number(default: Number, key: Name? = null): ReadOnlyProperty<Any?, Number> =
|
||||||
item(key).convert(MetaConverter.number) { default }
|
item(key).convert(MetaConverter.number) { default }
|
||||||
|
|
||||||
fun ItemProvider.double(default: Double, key: Name? = null): ReadOnlyProperty<Any?, Double> =
|
public fun ItemProvider.double(default: Double, key: Name? = null): ReadOnlyProperty<Any?, Double> =
|
||||||
item(key).convert(MetaConverter.double) { default }
|
item(key).convert(MetaConverter.double) { default }
|
||||||
|
|
||||||
fun ItemProvider.float(default: Float, key: Name? = null): ReadOnlyProperty<Any?, Float> =
|
public fun ItemProvider.float(default: Float, key: Name? = null): ReadOnlyProperty<Any?, Float> =
|
||||||
item(key).convert(MetaConverter.float) { default }
|
item(key).convert(MetaConverter.float) { default }
|
||||||
|
|
||||||
fun ItemProvider.int(default: Int, key: Name? = null): ReadOnlyProperty<Any?, Int> =
|
public fun ItemProvider.int(default: Int, key: Name? = null): ReadOnlyProperty<Any?, Int> =
|
||||||
item(key).convert(MetaConverter.int) { default }
|
item(key).convert(MetaConverter.int) { default }
|
||||||
|
|
||||||
fun ItemProvider.long(default: Long, key: Name? = null): ReadOnlyProperty<Any?, Long> =
|
public fun ItemProvider.long(default: Long, key: Name? = null): ReadOnlyProperty<Any?, Long> =
|
||||||
item(key).convert(MetaConverter.long) { default }
|
item(key).convert(MetaConverter.long) { default }
|
||||||
|
|
||||||
inline fun <reified E : Enum<E>> ItemProvider.enum(default: E, key: Name? = null): ReadOnlyProperty<Any?, E> =
|
public inline fun <reified E : Enum<E>> ItemProvider.enum(default: E, key: Name? = null): ReadOnlyProperty<Any?, E> =
|
||||||
item(key).convert(MetaConverter.enum()) { default }
|
item(key).convert(MetaConverter.enum()) { default }
|
||||||
|
|
||||||
fun ItemProvider.string(key: Name? = null, default: () -> String): ReadOnlyProperty<Any?, String> =
|
public fun ItemProvider.string(key: Name? = null, default: () -> String): ReadOnlyProperty<Any?, String> =
|
||||||
item(key).convert(MetaConverter.string, default)
|
item(key).convert(MetaConverter.string, default)
|
||||||
|
|
||||||
fun ItemProvider.boolean(key: Name? = null, default: () -> Boolean): ReadOnlyProperty<Any?, Boolean> =
|
public fun ItemProvider.boolean(key: Name? = null, default: () -> Boolean): ReadOnlyProperty<Any?, Boolean> =
|
||||||
item(key).convert(MetaConverter.boolean, default)
|
item(key).convert(MetaConverter.boolean, default)
|
||||||
|
|
||||||
fun ItemProvider.number(key: Name? = null, default: () -> Number): ReadOnlyProperty<Any?, Number> =
|
public fun ItemProvider.number(key: Name? = null, default: () -> Number): ReadOnlyProperty<Any?, Number> =
|
||||||
item(key).convert(MetaConverter.number, default)
|
item(key).convert(MetaConverter.number, default)
|
||||||
|
@ -15,7 +15,7 @@ import kotlinx.serialization.json.*
|
|||||||
/**
|
/**
|
||||||
* @param descriptor reserved for custom serialization in future
|
* @param descriptor reserved for custom serialization in future
|
||||||
*/
|
*/
|
||||||
fun Value.toJson(descriptor: ValueDescriptor? = null): JsonElement {
|
public fun Value.toJson(descriptor: ValueDescriptor? = null): JsonElement {
|
||||||
return if (isList()) {
|
return if (isList()) {
|
||||||
JsonArray(list.map { it.toJson() })
|
JsonArray(list.map { it.toJson() })
|
||||||
} else {
|
} else {
|
||||||
@ -82,11 +82,11 @@ private fun Meta.toJsonWithIndex(descriptor: NodeDescriptor?, indexValue: String
|
|||||||
return JsonObject(elementMap)
|
return JsonObject(elementMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Meta.toJson(descriptor: NodeDescriptor? = null): JsonObject = toJsonWithIndex(descriptor, null)
|
public fun Meta.toJson(descriptor: NodeDescriptor? = null): JsonObject = toJsonWithIndex(descriptor, null)
|
||||||
|
|
||||||
fun JsonObject.toMeta(descriptor: NodeDescriptor? = null): JsonMeta = JsonMeta(this, descriptor)
|
public fun JsonObject.toMeta(descriptor: NodeDescriptor? = null): JsonMeta = JsonMeta(this, descriptor)
|
||||||
|
|
||||||
fun JsonPrimitive.toValue(descriptor: ValueDescriptor?): Value {
|
public fun JsonPrimitive.toValue(descriptor: ValueDescriptor?): Value {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
JsonNull -> Null
|
JsonNull -> Null
|
||||||
else -> {
|
else -> {
|
||||||
@ -99,7 +99,7 @@ fun JsonPrimitive.toValue(descriptor: ValueDescriptor?): Value {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem<JsonMeta> = when (this) {
|
public fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem<JsonMeta> = when (this) {
|
||||||
is JsonPrimitive -> {
|
is JsonPrimitive -> {
|
||||||
val value = this.toValue(descriptor as? ValueDescriptor)
|
val value = this.toValue(descriptor as? ValueDescriptor)
|
||||||
MetaItem.ValueItem(value)
|
MetaItem.ValueItem(value)
|
||||||
@ -129,7 +129,7 @@ fun JsonElement.toMetaItem(descriptor: ItemDescriptor? = null): MetaItem<JsonMet
|
|||||||
/**
|
/**
|
||||||
* A meta wrapping json object
|
* A meta wrapping json object
|
||||||
*/
|
*/
|
||||||
class JsonMeta(val json: JsonObject, val descriptor: NodeDescriptor? = null) : MetaBase() {
|
public class JsonMeta(private val json: JsonObject, private val descriptor: NodeDescriptor? = null) : MetaBase() {
|
||||||
|
|
||||||
private fun buildItems(): Map<NameToken, MetaItem<JsonMeta>> {
|
private fun buildItems(): Map<NameToken, MetaItem<JsonMeta>> {
|
||||||
val map = LinkedHashMap<NameToken, MetaItem<JsonMeta>>()
|
val map = LinkedHashMap<NameToken, MetaItem<JsonMeta>>()
|
||||||
@ -173,10 +173,10 @@ class JsonMeta(val json: JsonObject, val descriptor: NodeDescriptor? = null) : M
|
|||||||
|
|
||||||
override val items: Map<NameToken, MetaItem<JsonMeta>> by lazy(::buildItems)
|
override val items: Map<NameToken, MetaItem<JsonMeta>> by lazy(::buildItems)
|
||||||
|
|
||||||
companion object {
|
public companion object {
|
||||||
/**
|
/**
|
||||||
* A key representing top-level json array of nodes, which could not be directly represented by a meta node
|
* A key representing top-level json array of nodes, which could not be directly represented by a meta node
|
||||||
*/
|
*/
|
||||||
const val JSON_ARRAY_KEY = "@jsonArray"
|
public const val JSON_ARRAY_KEY: String = "@jsonArray"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -7,9 +7,9 @@ import hep.dataforge.names.NameToken
|
|||||||
* A meta laminate consisting of multiple immutable meta layers. For mutable front layer, use [Scheme].
|
* A meta laminate consisting of multiple immutable meta layers. For mutable front layer, use [Scheme].
|
||||||
* If [layers] list contains a [Laminate] it is flat-mapped.
|
* If [layers] list contains a [Laminate] it is flat-mapped.
|
||||||
*/
|
*/
|
||||||
class Laminate(layers: List<Meta>) : MetaBase() {
|
public class Laminate(layers: List<Meta>) : MetaBase() {
|
||||||
|
|
||||||
val layers: List<Meta> = layers.flatMap {
|
public val layers: List<Meta> = layers.flatMap {
|
||||||
if (it is Laminate) {
|
if (it is Laminate) {
|
||||||
it.layers
|
it.layers
|
||||||
} else {
|
} else {
|
||||||
@ -17,7 +17,7 @@ class Laminate(layers: List<Meta>) : MetaBase() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(vararg layers: Meta?) : this(layers.filterNotNull())
|
public constructor(vararg layers: Meta?) : this(layers.filterNotNull())
|
||||||
|
|
||||||
override val items: Map<NameToken, MetaItem<Meta>> by lazy {
|
override val items: Map<NameToken, MetaItem<Meta>> by lazy {
|
||||||
layers.map { it.items.keys }.flatten().associateWith { key ->
|
layers.map { it.items.keys }.flatten().associateWith { key ->
|
||||||
@ -28,21 +28,21 @@ class Laminate(layers: List<Meta>) : MetaBase() {
|
|||||||
/**
|
/**
|
||||||
* Generate sealed meta using [mergeRule]
|
* Generate sealed meta using [mergeRule]
|
||||||
*/
|
*/
|
||||||
fun merge(): SealedMeta {
|
public fun merge(): SealedMeta {
|
||||||
val items = layers.map { it.items.keys }.flatten().associateWith { key ->
|
val items = layers.map { it.items.keys }.flatten().associateWith { key ->
|
||||||
layers.asSequence().map { it.items[key] }.filterNotNull().merge()
|
layers.asSequence().map { it.items[key] }.filterNotNull().merge()
|
||||||
}
|
}
|
||||||
return SealedMeta(items)
|
return SealedMeta(items)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
public companion object {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default rule which always uses the first found item in sequence alongside with its children.
|
* The default rule which always uses the first found item in sequence alongside with its children.
|
||||||
*
|
*
|
||||||
* TODO add picture
|
* TODO add picture
|
||||||
*/
|
*/
|
||||||
val replaceRule: (Sequence<MetaItem<*>>) -> MetaItem<SealedMeta> = { it.first().seal() }
|
public val replaceRule: (Sequence<MetaItem<*>>) -> MetaItem<SealedMeta> = { it.first().seal() }
|
||||||
|
|
||||||
private fun Sequence<MetaItem<*>>.merge(): MetaItem<SealedMeta> {
|
private fun Sequence<MetaItem<*>>.merge(): MetaItem<SealedMeta> {
|
||||||
return when {
|
return when {
|
||||||
@ -76,14 +76,14 @@ class Laminate(layers: List<Meta>) : MetaBase() {
|
|||||||
* The values a replaced but meta children are joined
|
* The values a replaced but meta children are joined
|
||||||
* TODO add picture
|
* TODO add picture
|
||||||
*/
|
*/
|
||||||
val mergeRule: (Sequence<MetaItem<*>>) -> MetaItem<SealedMeta> = { it.merge() }
|
public val mergeRule: (Sequence<MetaItem<*>>) -> MetaItem<SealedMeta> = { it.merge() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performance optimized version of get method
|
* Performance optimized version of get method
|
||||||
*/
|
*/
|
||||||
fun Laminate.getFirst(name: Name): MetaItem<*>? {
|
public fun Laminate.getFirst(name: Name): MetaItem<*>? {
|
||||||
layers.forEach { layer ->
|
layers.forEach { layer ->
|
||||||
layer[name]?.let { return it }
|
layer[name]?.let { return it }
|
||||||
}
|
}
|
||||||
@ -93,11 +93,11 @@ fun Laminate.getFirst(name: Name): MetaItem<*>? {
|
|||||||
/**
|
/**
|
||||||
* Create a new [Laminate] adding given layer to the top
|
* Create a new [Laminate] adding given layer to the top
|
||||||
*/
|
*/
|
||||||
fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
|
public fun Laminate.withTop(meta: Meta): Laminate = Laminate(listOf(meta) + layers)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new [Laminate] adding given layer to the bottom
|
* Create a new [Laminate] adding given layer to the bottom
|
||||||
*/
|
*/
|
||||||
fun Laminate.withBottom(meta: Meta): Laminate = Laminate(layers + meta)
|
public fun Laminate.withBottom(meta: Meta): Laminate = Laminate(layers + meta)
|
||||||
|
|
||||||
//TODO add custom rules for Laminate merge
|
//TODO add custom rules for Laminate merge
|
||||||
|
@ -5,6 +5,7 @@ import hep.dataforge.meta.MetaItem.NodeItem
|
|||||||
import hep.dataforge.meta.MetaItem.ValueItem
|
import hep.dataforge.meta.MetaItem.ValueItem
|
||||||
import hep.dataforge.names.*
|
import hep.dataforge.names.*
|
||||||
import hep.dataforge.values.*
|
import hep.dataforge.values.*
|
||||||
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.KSerializer
|
import kotlinx.serialization.KSerializer
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.Serializer
|
import kotlinx.serialization.Serializer
|
||||||
@ -19,18 +20,19 @@ import kotlinx.serialization.encoding.Encoder
|
|||||||
* * a [NodeItem] (node)
|
* * a [NodeItem] (node)
|
||||||
*/
|
*/
|
||||||
@Serializable
|
@Serializable
|
||||||
sealed class MetaItem<out M : Meta> {
|
public sealed class MetaItem<out M : Meta> {
|
||||||
|
|
||||||
abstract override fun equals(other: Any?): Boolean
|
abstract override fun equals(other: Any?): Boolean
|
||||||
|
|
||||||
abstract override fun hashCode(): Int
|
abstract override fun hashCode(): Int
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class ValueItem(val value: Value) : MetaItem<Nothing>() {
|
public class ValueItem(public val value: Value) : MetaItem<Nothing>() {
|
||||||
override fun toString(): String = value.toString()
|
override fun toString(): String = value.toString()
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
@Serializer(ValueItem::class)
|
@Serializer(ValueItem::class)
|
||||||
companion object : KSerializer<ValueItem> {
|
public companion object : KSerializer<ValueItem> {
|
||||||
override val descriptor: SerialDescriptor get() = ValueSerializer.descriptor
|
override val descriptor: SerialDescriptor get() = ValueSerializer.descriptor
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): ValueItem = ValueItem(ValueSerializer.deserialize(decoder))
|
override fun deserialize(decoder: Decoder): ValueItem = ValueItem(ValueSerializer.deserialize(decoder))
|
||||||
@ -50,12 +52,13 @@ sealed class MetaItem<out M : Meta> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class NodeItem<M : Meta>(@Serializable(MetaSerializer::class) val node: M) : MetaItem<M>() {
|
public class NodeItem<M : Meta>(@Serializable(MetaSerializer::class) 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
|
//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 toString(): String = node.toString()
|
||||||
|
|
||||||
|
@OptIn(ExperimentalSerializationApi::class)
|
||||||
@Serializer(NodeItem::class)
|
@Serializer(NodeItem::class)
|
||||||
companion object : KSerializer<NodeItem<out Meta>> {
|
public companion object : KSerializer<NodeItem<out Meta>> {
|
||||||
override val descriptor: SerialDescriptor get() = MetaSerializer.descriptor
|
override val descriptor: SerialDescriptor get() = MetaSerializer.descriptor
|
||||||
|
|
||||||
override fun deserialize(decoder: Decoder): NodeItem<*> = NodeItem(MetaSerializer.deserialize(decoder))
|
override fun deserialize(decoder: Decoder): NodeItem<*> = NodeItem(MetaSerializer.deserialize(decoder))
|
||||||
@ -70,8 +73,8 @@ sealed class MetaItem<out M : Meta> {
|
|||||||
override fun hashCode(): Int = node.hashCode()
|
override fun hashCode(): Int = node.hashCode()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
public companion object {
|
||||||
fun of(arg: Any?): MetaItem<*> {
|
public fun of(arg: Any?): MetaItem<*> {
|
||||||
return when (arg) {
|
return when (arg) {
|
||||||
null -> ValueItem(Null)
|
null -> ValueItem(Null)
|
||||||
is MetaItem<*> -> arg
|
is MetaItem<*> -> arg
|
||||||
@ -82,19 +85,19 @@ sealed class MetaItem<out M : Meta> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Value.asMetaItem() = ValueItem(this)
|
public fun Value.asMetaItem(): ValueItem = ValueItem(this)
|
||||||
fun <M:Meta> M.asMetaItem() = NodeItem(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.
|
* 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.
|
* Meaning that two states with the same meta are equal.
|
||||||
*/
|
*/
|
||||||
interface MetaRepr {
|
public interface MetaRepr {
|
||||||
fun toMeta(): Meta
|
public fun toMeta(): Meta
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ItemProvider{
|
public interface ItemProvider{
|
||||||
fun getItem(name: Name): MetaItem<*>?
|
public fun getItem(name: Name): MetaItem<*>?
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -104,11 +107,11 @@ interface ItemProvider{
|
|||||||
*
|
*
|
||||||
* * Same name siblings are supported via elements with the same [Name] but different queries
|
* * Same name siblings are supported via elements with the same [Name] but different queries
|
||||||
*/
|
*/
|
||||||
interface Meta : MetaRepr, ItemProvider {
|
public interface Meta : MetaRepr, ItemProvider {
|
||||||
/**
|
/**
|
||||||
* Top level items of meta tree
|
* Top level items of meta tree
|
||||||
*/
|
*/
|
||||||
val items: Map<NameToken, MetaItem<*>>
|
public val items: Map<NameToken, MetaItem<*>>
|
||||||
|
|
||||||
override fun getItem(name: Name): MetaItem<*>? {
|
override fun getItem(name: Name): MetaItem<*>? {
|
||||||
if (name.isEmpty()) return NodeItem(this)
|
if (name.isEmpty()) return NodeItem(this)
|
||||||
@ -129,15 +132,15 @@ interface Meta : MetaRepr, ItemProvider {
|
|||||||
|
|
||||||
override fun toString(): String
|
override fun toString(): String
|
||||||
|
|
||||||
companion object {
|
public companion object {
|
||||||
const val TYPE = "meta"
|
public const val TYPE: String = "meta"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A key for single value node
|
* A key for single value node
|
||||||
*/
|
*/
|
||||||
const val VALUE_KEY = "@value"
|
public const val VALUE_KEY: String = "@value"
|
||||||
|
|
||||||
val EMPTY: Meta = object: MetaBase() {
|
public val EMPTY: Meta = object: MetaBase() {
|
||||||
override val items: Map<NameToken, MetaItem<*>> = emptyMap()
|
override val items: Map<NameToken, MetaItem<*>> = emptyMap()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,19 +153,19 @@ interface Meta : MetaRepr, ItemProvider {
|
|||||||
*
|
*
|
||||||
* If [name] is empty return current [Meta] as a [NodeItem]
|
* If [name] is empty return current [Meta] as a [NodeItem]
|
||||||
*/
|
*/
|
||||||
operator fun Meta?.get(name: Name): MetaItem<*>? = this?.getItem(name)
|
public operator fun Meta?.get(name: Name): MetaItem<*>? = this?.getItem(name)
|
||||||
|
|
||||||
operator fun Meta?.get(token: NameToken): MetaItem<*>? = this?.items?.get(token)
|
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]
|
* Parse [Name] from [key] using full name notation and pass it to [Meta.get]
|
||||||
*/
|
*/
|
||||||
operator fun Meta?.get(key: String): MetaItem<*>? = get(key.toName())
|
public operator fun Meta?.get(key: String): MetaItem<*>? = get(key.toName())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a sequence of [Name]-[Value] pairs
|
* Get a sequence of [Name]-[Value] pairs
|
||||||
*/
|
*/
|
||||||
fun Meta.values(): Sequence<Pair<Name, Value>> {
|
public fun Meta.values(): Sequence<Pair<Name, Value>> {
|
||||||
return items.asSequence().flatMap { (key, item) ->
|
return items.asSequence().flatMap { (key, item) ->
|
||||||
when (item) {
|
when (item) {
|
||||||
is ValueItem -> sequenceOf(key.asName() to item.value)
|
is ValueItem -> sequenceOf(key.asName() to item.value)
|
||||||
@ -174,7 +177,7 @@ fun Meta.values(): Sequence<Pair<Name, Value>> {
|
|||||||
/**
|
/**
|
||||||
* Get a sequence of all [Name]-[MetaItem] pairs for all items including nodes
|
* Get a sequence of all [Name]-[MetaItem] pairs for all items including nodes
|
||||||
*/
|
*/
|
||||||
fun Meta.sequence(): Sequence<Pair<Name, MetaItem<*>>> {
|
public fun Meta.sequence(): Sequence<Pair<Name, MetaItem<*>>> {
|
||||||
return sequence {
|
return sequence {
|
||||||
items.forEach { (key, item) ->
|
items.forEach { (key, item) ->
|
||||||
yield(key.asName() to item)
|
yield(key.asName() to item)
|
||||||
@ -187,33 +190,33 @@ fun Meta.sequence(): Sequence<Pair<Name, MetaItem<*>>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun Meta.iterator(): Iterator<Pair<Name, MetaItem<*>>> = sequence().iterator()
|
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
|
* A meta node that ensures that all of its descendants has at least the same type
|
||||||
*/
|
*/
|
||||||
interface MetaNode<out M : MetaNode<M>> : Meta {
|
public interface MetaNode<out M : MetaNode<M>> : Meta {
|
||||||
override val items: Map<NameToken, MetaItem<M>>
|
override val items: Map<NameToken, MetaItem<M>>
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The same as [Meta.get], but with specific node type
|
* The same as [Meta.get], but with specific node type
|
||||||
*/
|
*/
|
||||||
operator fun <M : MetaNode<M>> M?.get(name: Name): MetaItem<M>? = if( this == null) {
|
public operator fun <M : MetaNode<M>> M?.get(name: Name): MetaItem<M>? = if( this == null) {
|
||||||
null
|
null
|
||||||
} else {
|
} else {
|
||||||
@Suppress("UNCHECKED_CAST", "ReplaceGetOrSet")
|
@Suppress("UNCHECKED_CAST", "ReplaceGetOrSet")
|
||||||
(this as Meta).get(name) as MetaItem<M>? // Do not change
|
(this as Meta).get(name) as MetaItem<M>? // Do not change
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun <M : MetaNode<M>> M?.get(key: String): MetaItem<M>? = this[key.toName()]
|
public operator fun <M : MetaNode<M>> M?.get(key: String): MetaItem<M>? = this[key.toName()]
|
||||||
|
|
||||||
operator fun <M : MetaNode<M>> M?.get(key: NameToken): MetaItem<M>? = this[key.asName()]
|
public operator fun <M : MetaNode<M>> M?.get(key: NameToken): MetaItem<M>? = this[key.asName()]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Equals, hashcode and to string for any meta
|
* Equals, hashcode and to string for any meta
|
||||||
*/
|
*/
|
||||||
abstract class MetaBase : Meta {
|
public abstract class MetaBase : Meta {
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean = if (other is Meta) {
|
override fun equals(other: Any?): Boolean = if (other is Meta) {
|
||||||
this.items == other.items
|
this.items == other.items
|
||||||
@ -229,24 +232,24 @@ abstract class MetaBase : Meta {
|
|||||||
/**
|
/**
|
||||||
* Equals and hash code implementation for meta node
|
* Equals and hash code implementation for meta node
|
||||||
*/
|
*/
|
||||||
abstract class AbstractMetaNode<M : MetaNode<M>> : MetaNode<M>, MetaBase()
|
public abstract class AbstractMetaNode<M : MetaNode<M>> : MetaNode<M>, MetaBase()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The meta implementation which is guaranteed to be immutable.
|
* The meta implementation which is guaranteed to be immutable.
|
||||||
*
|
*
|
||||||
* If the argument is possibly mutable node, it is copied on creation
|
* If the argument is possibly mutable node, it is copied on creation
|
||||||
*/
|
*/
|
||||||
class SealedMeta internal constructor(
|
public class SealedMeta internal constructor(
|
||||||
override val items: Map<NameToken, MetaItem<SealedMeta>>
|
override val items: Map<NameToken, MetaItem<SealedMeta>>
|
||||||
) : AbstractMetaNode<SealedMeta>()
|
) : AbstractMetaNode<SealedMeta>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate sealed node from [this]. If it is already sealed return it as is
|
* Generate sealed node from [this]. If it is already sealed return it as is
|
||||||
*/
|
*/
|
||||||
fun Meta.seal(): SealedMeta = this as? SealedMeta ?: SealedMeta(items.mapValues { entry -> entry.value.seal() })
|
public fun Meta.seal(): SealedMeta = this as? SealedMeta ?: SealedMeta(items.mapValues { entry -> entry.value.seal() })
|
||||||
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
fun MetaItem<*>.seal(): MetaItem<SealedMeta> = when (this) {
|
public fun MetaItem<*>.seal(): MetaItem<SealedMeta> = when (this) {
|
||||||
is ValueItem -> this
|
is ValueItem -> this
|
||||||
is NodeItem -> NodeItem(node.seal())
|
is NodeItem -> NodeItem(node.seal())
|
||||||
}
|
}
|
||||||
@ -254,32 +257,32 @@ fun MetaItem<*>.seal(): MetaItem<SealedMeta> = when (this) {
|
|||||||
/**
|
/**
|
||||||
* Unsafe methods to access values and nodes directly from [MetaItem]
|
* Unsafe methods to access values and nodes directly from [MetaItem]
|
||||||
*/
|
*/
|
||||||
val MetaItem<*>?.value: Value?
|
public val MetaItem<*>?.value: Value?
|
||||||
get() = (this as? ValueItem)?.value
|
get() = (this as? ValueItem)?.value
|
||||||
?: (this?.node?.get(VALUE_KEY) as? ValueItem)?.value
|
?: (this?.node?.get(VALUE_KEY) as? ValueItem)?.value
|
||||||
|
|
||||||
val MetaItem<*>?.string get() = value?.string
|
public val MetaItem<*>?.string: String? get() = value?.string
|
||||||
val MetaItem<*>?.boolean get() = value?.boolean
|
public val MetaItem<*>?.boolean: Boolean? get() = value?.boolean
|
||||||
val MetaItem<*>?.number get() = value?.number
|
public val MetaItem<*>?.number: Number? get() = value?.number
|
||||||
val MetaItem<*>?.double get() = number?.toDouble()
|
public val MetaItem<*>?.double: Double? get() = number?.toDouble()
|
||||||
val MetaItem<*>?.float get() = number?.toFloat()
|
public val MetaItem<*>?.float: Float? get() = number?.toFloat()
|
||||||
val MetaItem<*>?.int get() = number?.toInt()
|
public val MetaItem<*>?.int: Int? get() = number?.toInt()
|
||||||
val MetaItem<*>?.long get() = number?.toLong()
|
public val MetaItem<*>?.long: Long? get() = number?.toLong()
|
||||||
val MetaItem<*>?.short get() = number?.toShort()
|
public val MetaItem<*>?.short: Short? get() = number?.toShort()
|
||||||
|
|
||||||
inline fun <reified E : Enum<E>> MetaItem<*>?.enum(): E? = if (this is ValueItem && this.value is EnumValue<*>) {
|
public inline fun <reified E : Enum<E>> MetaItem<*>?.enum(): E? = if (this is ValueItem && this.value is EnumValue<*>) {
|
||||||
this.value.value as E
|
this.value.value as E
|
||||||
} else {
|
} else {
|
||||||
string?.let { enumValueOf<E>(it) }
|
string?.let { enumValueOf<E>(it) }
|
||||||
}
|
}
|
||||||
|
|
||||||
val MetaItem<*>.stringList get() = value?.list?.map { it.string }
|
public val MetaItem<*>.stringList: List<String>? get() = value?.list?.map { it.string }
|
||||||
|
|
||||||
val <M : Meta> MetaItem<M>?.node: M?
|
public val <M : Meta> MetaItem<M>?.node: M?
|
||||||
get() = when (this) {
|
get() = when (this) {
|
||||||
null -> null
|
null -> null
|
||||||
is ValueItem -> null//error("Trying to interpret value meta item as node item")
|
is ValueItem -> null//error("Trying to interpret value meta item as node item")
|
||||||
is NodeItem -> node
|
is NodeItem -> node
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Meta.isEmpty() = this === Meta.EMPTY || this.items.isEmpty()
|
public fun Meta.isEmpty(): Boolean = this === Meta.EMPTY || this.items.isEmpty()
|
@ -4,19 +4,19 @@ plugins {
|
|||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
sourceSets {
|
sourceSets {
|
||||||
val commonMain by getting {
|
commonMain {
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":dataforge-workspace"))
|
api(project(":dataforge-workspace"))
|
||||||
implementation(kotlin("scripting-common"))
|
implementation(kotlin("scripting-common"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val jvmMain by getting {
|
jvmMain{
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation(kotlin("scripting-jvm-host"))
|
implementation(kotlin("scripting-jvm-host"))
|
||||||
implementation(kotlin("scripting-jvm"))
|
implementation(kotlin("scripting-jvm"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val jvmTest by getting {
|
jvmTest {
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation("ch.qos.logback:logback-classic:1.2.3")
|
implementation("ch.qos.logback:logback-classic:1.2.3")
|
||||||
}
|
}
|
||||||
|
@ -1,4 +0,0 @@
|
|||||||
package hep.dataforge.scripting
|
|
||||||
|
|
||||||
internal object Placeholder {
|
|
||||||
}
|
|
@ -13,15 +13,18 @@ import kotlin.script.experimental.jvm.dependenciesFromCurrentContext
|
|||||||
import kotlin.script.experimental.jvm.jvm
|
import kotlin.script.experimental.jvm.jvm
|
||||||
import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
|
import kotlin.script.experimental.jvmhost.BasicJvmScriptingHost
|
||||||
|
|
||||||
object Builders {
|
public object Builders {
|
||||||
|
|
||||||
fun buildWorkspace(source: SourceCode, context: Context = Global): Workspace {
|
private fun buildWorkspace(source: SourceCode, context: Context = Global): Workspace {
|
||||||
val builder = SimpleWorkspaceBuilder(context)
|
val builder = SimpleWorkspaceBuilder(context)
|
||||||
|
|
||||||
val workspaceScriptConfiguration = ScriptCompilationConfiguration {
|
val workspaceScriptConfiguration = ScriptCompilationConfiguration {
|
||||||
baseClass(Any::class)
|
// baseClass(Any::class)
|
||||||
implicitReceivers(WorkspaceBuilder::class)
|
implicitReceivers(WorkspaceBuilder::class)
|
||||||
defaultImports("hep.dataforge.workspace.*")
|
defaultImports(
|
||||||
|
"hep.dataforge.meta.*",
|
||||||
|
"hep.dataforge.workspace.*"
|
||||||
|
)
|
||||||
jvm {
|
jvm {
|
||||||
dependenciesFromCurrentContext(wholeClasspath = true)
|
dependenciesFromCurrentContext(wholeClasspath = true)
|
||||||
}
|
}
|
||||||
@ -49,7 +52,7 @@ object Builders {
|
|||||||
return builder.build()
|
return builder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun buildWorkspace(file: File): Workspace = buildWorkspace(file.toScriptSource())
|
public fun buildWorkspace(file: File): Workspace = buildWorkspace(file.toScriptSource())
|
||||||
|
|
||||||
fun buildWorkspace(string: String): Workspace = buildWorkspace(string.toScriptSource())
|
public fun buildWorkspace(string: String): Workspace = buildWorkspace(string.toScriptSource())
|
||||||
}
|
}
|
@ -4,7 +4,7 @@ plugins {
|
|||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
sourceSets {
|
sourceSets {
|
||||||
val commonMain by getting{
|
commonMain{
|
||||||
dependencies {
|
dependencies {
|
||||||
api(project(":dataforge-context"))
|
api(project(":dataforge-context"))
|
||||||
api(project(":dataforge-data"))
|
api(project(":dataforge-data"))
|
||||||
|
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6.1-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
2
gradlew
vendored
2
gradlew
vendored
@ -130,7 +130,7 @@ fi
|
|||||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||||
|
|
||||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||||
|
|
||||||
# We build the pattern for arguments to be converted via cygpath
|
# We build the pattern for arguments to be converted via cygpath
|
||||||
|
21
gradlew.bat
vendored
21
gradlew.bat
vendored
@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
|||||||
|
|
||||||
set JAVA_EXE=java.exe
|
set JAVA_EXE=java.exe
|
||||||
%JAVA_EXE% -version >NUL 2>&1
|
%JAVA_EXE% -version >NUL 2>&1
|
||||||
if "%ERRORLEVEL%" == "0" goto init
|
if "%ERRORLEVEL%" == "0" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||||
@ -54,7 +54,7 @@ goto fail
|
|||||||
set JAVA_HOME=%JAVA_HOME:"=%
|
set JAVA_HOME=%JAVA_HOME:"=%
|
||||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||||
|
|
||||||
if exist "%JAVA_EXE%" goto init
|
if exist "%JAVA_EXE%" goto execute
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||||
@ -64,21 +64,6 @@ echo location of your Java installation.
|
|||||||
|
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:init
|
|
||||||
@rem Get command-line arguments, handling Windows variants
|
|
||||||
|
|
||||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
|
||||||
|
|
||||||
:win9xME_args
|
|
||||||
@rem Slurp the command line arguments.
|
|
||||||
set CMD_LINE_ARGS=
|
|
||||||
set _SKIP=2
|
|
||||||
|
|
||||||
:win9xME_args_slurp
|
|
||||||
if "x%~1" == "x" goto execute
|
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
@ -86,7 +71,7 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
|||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
@ -5,12 +5,20 @@ pluginManagement {
|
|||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
maven("https://dl.bintray.com/kotlin/kotlin-eap")
|
maven("https://dl.bintray.com/kotlin/kotlin-eap")
|
||||||
maven("https://dl.bintray.com/kotlin/kotlinx")
|
maven("https://dl.bintray.com/kotlin/kotlinx")
|
||||||
maven("https://dl.bintray.com/mipt-npm/scientifik")
|
|
||||||
maven("https://dl.bintray.com/mipt-npm/kscience")
|
maven("https://dl.bintray.com/mipt-npm/kscience")
|
||||||
maven("https://dl.bintray.com/mipt-npm/dev")
|
maven("https://dl.bintray.com/mipt-npm/dev")
|
||||||
}
|
}
|
||||||
|
|
||||||
val toolsVersion = "0.6.0"
|
val toolsVersion = "0.6.0"
|
||||||
|
val kotlinVersion = "1.4.0"
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
kotlin("jvm") version kotlinVersion
|
||||||
|
id("scientifik.mpp") version toolsVersion
|
||||||
|
id("scientifik.jvm") version toolsVersion
|
||||||
|
id("scientifik.js") version toolsVersion
|
||||||
|
id("scientifik.publish") version toolsVersion
|
||||||
|
}
|
||||||
|
|
||||||
resolutionStrategy {
|
resolutionStrategy {
|
||||||
eachPlugin {
|
eachPlugin {
|
||||||
|
Loading…
Reference in New Issue
Block a user