Name revolution
This commit is contained in:
parent
4a76063093
commit
8763d63e28
@ -11,6 +11,7 @@
|
||||
- Build tools 0.10.0
|
||||
- Relaxed type restriction on `MetaConverter`. Now nullables are available.
|
||||
- **Huge API-breaking refactoring of Meta**. Meta now can hava both value and children.
|
||||
- **API breaking** `String.toName()` is replaced by `Name.parse()`
|
||||
|
||||
### Deprecated
|
||||
- Direct use of `Config`
|
||||
|
@ -4,7 +4,7 @@ plugins {
|
||||
|
||||
allprojects {
|
||||
group = "space.kscience"
|
||||
version = "0.5.0-dev-3"
|
||||
version = "0.5.0-dev-4"
|
||||
}
|
||||
|
||||
subprojects {
|
||||
|
@ -7,8 +7,9 @@ import space.kscience.dataforge.meta.toMutableMeta
|
||||
import space.kscience.dataforge.misc.DFBuilder
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.NameToken
|
||||
import space.kscience.dataforge.names.asName
|
||||
import space.kscience.dataforge.names.plus
|
||||
import space.kscience.dataforge.names.toName
|
||||
import kotlin.collections.component1
|
||||
import kotlin.collections.component2
|
||||
import kotlin.collections.set
|
||||
@ -30,7 +31,7 @@ public class ContextBuilder internal constructor(
|
||||
}
|
||||
|
||||
public fun name(string: String) {
|
||||
this.name = string.toName()
|
||||
this.name = Name.parse(string)
|
||||
}
|
||||
|
||||
@OptIn(DFExperimental::class)
|
||||
@ -63,7 +64,7 @@ public class ContextBuilder internal constructor(
|
||||
}
|
||||
|
||||
public fun build(): Context {
|
||||
val contextName = name ?: "@auto[${hashCode().toUInt().toString(16)}]".toName()
|
||||
val contextName = name ?: NameToken("@auto",hashCode().toUInt().toString(16)).asName()
|
||||
val plugins = HashMap<PluginTag, Plugin>()
|
||||
|
||||
fun addPlugin(factory: PluginFactory<*>, meta: Meta) {
|
||||
|
@ -6,7 +6,6 @@ import space.kscience.dataforge.meta.MetaRepr
|
||||
import space.kscience.dataforge.misc.Named
|
||||
import space.kscience.dataforge.misc.Type
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.toName
|
||||
import space.kscience.dataforge.provider.Provider
|
||||
|
||||
/**
|
||||
@ -31,7 +30,7 @@ public interface Plugin : Named, ContextAware, Provider, MetaRepr {
|
||||
/**
|
||||
* The name of this plugin ignoring version and group
|
||||
*/
|
||||
override val name: Name get() = tag.name.toName()
|
||||
override val name: Name get() = Name.parse(tag.name)
|
||||
|
||||
/**
|
||||
* Plugin dependencies which are required to attach this plugin. Plugin
|
||||
|
@ -1,14 +1,14 @@
|
||||
package space.kscience.dataforge.properties
|
||||
|
||||
|
||||
import space.kscience.dataforge.meta.ObservableMeta
|
||||
import space.kscience.dataforge.meta.Scheme
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.startsWith
|
||||
import space.kscience.dataforge.names.toName
|
||||
import kotlin.reflect.KMutableProperty1
|
||||
|
||||
@DFExperimental
|
||||
public fun <P : ObservableMeta, T : Any> P.property(property: KMutableProperty1<P, T?>): Property<T?> =
|
||||
public fun <S : Scheme, T : Any> S.property(property: KMutableProperty1<S, T?>): Property<T?> =
|
||||
object : Property<T?> {
|
||||
override var value: T?
|
||||
get() = property.get(this@property)
|
||||
@ -17,15 +17,15 @@ public fun <P : ObservableMeta, T : Any> P.property(property: KMutableProperty1<
|
||||
}
|
||||
|
||||
override fun onChange(owner: Any?, callback: (T?) -> Unit) {
|
||||
this@property.onChange(this) { name ->
|
||||
if (name.startsWith(property.name.toName())) {
|
||||
this@property.meta.onChange(this) { name ->
|
||||
if (name.startsWith(Name.parse(property.name))) {
|
||||
callback(property.get(this@property))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun removeChangeListener(owner: Any?) {
|
||||
this@property.removeListener(this@property)
|
||||
this@property.meta.removeListener(this@property)
|
||||
}
|
||||
|
||||
}
|
@ -16,7 +16,6 @@
|
||||
package space.kscience.dataforge.provider
|
||||
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.toName
|
||||
import kotlin.jvm.JvmInline
|
||||
|
||||
/**
|
||||
@ -63,7 +62,7 @@ public data class PathToken(val name: Name, val target: String? = null) {
|
||||
public const val TARGET_SEPARATOR: String = "::"
|
||||
public fun parse(token: String): PathToken {
|
||||
val target = token.substringBefore(TARGET_SEPARATOR, "")
|
||||
val name = token.substringAfter(TARGET_SEPARATOR).toName()
|
||||
val name = Name.parse(token.substringAfter(TARGET_SEPARATOR))
|
||||
if (target.contains("[")) TODO("target separators in queries are not supported")
|
||||
return PathToken(name, target)
|
||||
}
|
||||
|
@ -2,7 +2,6 @@ package space.kscience.dataforge.context
|
||||
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.appendLeft
|
||||
import space.kscience.dataforge.names.toName
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@ -12,17 +11,16 @@ class ContextTest {
|
||||
override val tag get() = PluginTag("test")
|
||||
|
||||
override fun content(target: String): Map<Name, Any> {
|
||||
return when(target){
|
||||
"test" -> listOf("a", "b", "c.d").associate { it.toName() to it.toName() }
|
||||
return when (target) {
|
||||
"test" -> listOf("a", "b", "c.d").associate { Name.parse(it) to Name.parse(it) }
|
||||
else -> emptyMap()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testPluginManager() {
|
||||
val context = Global.buildContext{
|
||||
val context = Global.buildContext {
|
||||
name("test")
|
||||
plugin(DummyPlugin())
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ internal class TestScheme : Scheme() {
|
||||
}
|
||||
|
||||
@DFExperimental
|
||||
class ItemPropertiesTest {
|
||||
class MetaPropertiesTest {
|
||||
@Test
|
||||
fun testBinding() {
|
||||
val scheme = TestScheme.empty()
|
@ -11,7 +11,6 @@ import space.kscience.dataforge.misc.DFBuilder
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.dataforge.misc.DFInternal
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.toName
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
|
||||
@ -95,7 +94,7 @@ internal class ReduceAction<T : Any, R : Any>(
|
||||
|
||||
val groupMeta = group.meta
|
||||
|
||||
val env = ActionEnv(groupName.toName(), groupMeta, meta)
|
||||
val env = ActionEnv(Name.parse(groupName), groupMeta, meta)
|
||||
@OptIn(DFInternal::class) val res: Data<R> = dataFlow.reduceToData(
|
||||
outputType,
|
||||
meta = groupMeta
|
||||
|
@ -12,7 +12,6 @@ import space.kscience.dataforge.meta.toMutableMeta
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.dataforge.misc.DFInternal
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.toName
|
||||
import kotlin.collections.set
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.typeOf
|
||||
@ -36,7 +35,7 @@ public class SplitBuilder<T : Any, R : Any>(public val name: Name, public val me
|
||||
* @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
|
||||
fragments[Name.parse(name)] = rule
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,4 +115,4 @@ public suspend inline fun <reified T : Any> ActiveDataTree<T>.emit(
|
||||
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))
|
||||
): Unit = emit(Name.parse(name), ActiveDataTree(typeOf<T>(), block))
|
||||
|
@ -8,7 +8,6 @@ import space.kscience.dataforge.meta.MutableMeta
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.plus
|
||||
import space.kscience.dataforge.names.toName
|
||||
import kotlin.reflect.KType
|
||||
|
||||
public interface DataSetBuilder<in T : Any> {
|
||||
@ -39,17 +38,17 @@ public interface DataSetBuilder<in T : Any> {
|
||||
/**
|
||||
* Append data to node
|
||||
*/
|
||||
public suspend infix fun String.put(data: Data<T>): Unit = emit(toName(), data)
|
||||
public suspend infix fun String.put(data: Data<T>): Unit = emit(Name.parse(this), data)
|
||||
|
||||
/**
|
||||
* Append node
|
||||
*/
|
||||
public suspend infix fun String.put(dataSet: DataSet<T>): Unit = emit(toName(), dataSet)
|
||||
public suspend infix fun String.put(dataSet: DataSet<T>): Unit = emit(Name.parse(this), dataSet)
|
||||
|
||||
/**
|
||||
* Build and append node
|
||||
*/
|
||||
public suspend infix fun String.put(block: suspend DataSetBuilder<T>.() -> Unit): Unit = emit(toName(), block)
|
||||
public suspend infix fun String.put(block: suspend DataSetBuilder<T>.() -> Unit): Unit = emit(Name.parse(this), block)
|
||||
}
|
||||
|
||||
private class SubSetBuilder<in T : Any>(
|
||||
@ -77,15 +76,15 @@ public suspend fun <T : Any> DataSetBuilder<T>.emit(name: Name, block: suspend D
|
||||
|
||||
|
||||
public suspend fun <T : Any> DataSetBuilder<T>.emit(name: String, data: Data<T>) {
|
||||
emit(name.toName(), data)
|
||||
emit(Name.parse(name), data)
|
||||
}
|
||||
|
||||
public suspend fun <T : Any> DataSetBuilder<T>.emit(name: String, set: DataSet<T>) {
|
||||
this.emit(name.toName(), set)
|
||||
this.emit(Name.parse(name), set)
|
||||
}
|
||||
|
||||
public suspend fun <T : Any> DataSetBuilder<T>.emit(name: String, block: suspend DataSetBuilder<T>.() -> Unit): Unit =
|
||||
this@emit.emit(name.toName(), block)
|
||||
this@emit.emit(Name.parse(name), block)
|
||||
|
||||
public suspend fun <T : Any> DataSetBuilder<T>.emit(data: NamedData<T>) {
|
||||
emit(data.name, data.data)
|
||||
@ -115,17 +114,25 @@ public suspend inline fun <reified T : Any> DataSetBuilder<T>.produce(
|
||||
/**
|
||||
* 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 =
|
||||
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 =
|
||||
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,
|
||||
mutableMeta: MutableMeta.() -> Unit,
|
||||
): Unit = emit(name.toName(), Data.static(data, Meta(mutableMeta)))
|
||||
): Unit = emit(Name.parse(name), Data.static(data, Meta(mutableMeta)))
|
||||
|
||||
/**
|
||||
* Update data with given node data and meta with node meta.
|
||||
|
@ -57,7 +57,7 @@ public interface DataTree<out T : Any> : DataSet<T> {
|
||||
}
|
||||
}
|
||||
|
||||
public suspend fun <T: Any> DataSet<T>.getData(name: String): Data<T>? = getData(name.toName())
|
||||
public suspend fun <T: Any> DataSet<T>.getData(name: String): Data<T>? = getData(Name.parse(name))
|
||||
|
||||
/**
|
||||
* Get a [DataTreeItem] with given [name] or null if the item does not exist
|
||||
|
@ -5,7 +5,10 @@ import kotlinx.coroutines.flow.filter
|
||||
import kotlinx.coroutines.flow.map
|
||||
import kotlinx.coroutines.flow.mapNotNull
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.dataforge.names.*
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.isEmpty
|
||||
import space.kscience.dataforge.names.plus
|
||||
import space.kscience.dataforge.names.removeHeadOrNull
|
||||
import kotlin.reflect.KType
|
||||
|
||||
|
||||
@ -64,7 +67,7 @@ public fun <T : Any> DataSet<T>.branch(branchName: Name): DataSet<T> = if (branc
|
||||
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())
|
||||
public fun <T : Any> DataSet<T>.branch(branchName: String): DataSet<T> = this@branch.branch(Name.parse(branchName))
|
||||
|
||||
@DFExperimental
|
||||
public suspend fun <T : Any> DataSet<T>.rootData(): Data<T>? = getData(Name.EMPTY)
|
||||
|
@ -6,7 +6,6 @@ import kotlinx.coroutines.flow.map
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.matches
|
||||
import space.kscience.dataforge.names.toName
|
||||
import kotlin.reflect.KType
|
||||
import kotlin.reflect.full.isSubtypeOf
|
||||
import kotlin.reflect.typeOf
|
||||
@ -61,4 +60,4 @@ public suspend fun <R : Any> DataSet<*>.selectOne(type: KType, name: Name): 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())
|
||||
selectOne(typeOf<R>(), Name.parse(name))
|
@ -3,7 +3,7 @@ package space.kscience.dataforge.data
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.flow.collect
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.dataforge.names.toName
|
||||
import space.kscience.dataforge.names.asName
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@ -72,7 +72,7 @@ internal class DataTreeBuilderTest {
|
||||
}
|
||||
}
|
||||
val rootNode = ActiveDataTree<Int> {
|
||||
setAndObserve("sub".toName(), subNode)
|
||||
setAndObserve("sub".asName(), subNode)
|
||||
}
|
||||
|
||||
launch {
|
||||
|
@ -10,12 +10,11 @@ import space.kscience.dataforge.io.PartDescriptor.Companion.SEPARATOR_KEY
|
||||
import space.kscience.dataforge.meta.*
|
||||
import space.kscience.dataforge.names.asName
|
||||
import space.kscience.dataforge.names.plus
|
||||
import space.kscience.dataforge.names.toName
|
||||
|
||||
private class PartDescriptor : Scheme() {
|
||||
var offset by int(0)
|
||||
var size by int(0)
|
||||
var partMeta by item("meta".toName())
|
||||
var partMeta by item("meta".asName())
|
||||
|
||||
companion object : SchemeSpec<PartDescriptor>(::PartDescriptor) {
|
||||
val MULTIPART_KEY = ENVELOPE_NODE_KEY + "multipart"
|
||||
|
@ -10,7 +10,7 @@ import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.get
|
||||
import space.kscience.dataforge.meta.string
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.toName
|
||||
|
||||
import kotlin.native.concurrent.ThreadLocal
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
@ -23,7 +23,7 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
|
||||
|
||||
public fun <T : Any> resolveIOFormat(item: Meta, type: KClass<out T>): IOFormat<T>? {
|
||||
val key = item.string ?: item[NAME_KEY]?.string ?: error("Format name not defined")
|
||||
val name = key.toName()
|
||||
val name = Name.parse(key)
|
||||
return ioFormatFactories.find { it.name == name }?.let {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
if (it.type != type) error("Format type ${it.type} is not the same as requested type $type")
|
||||
@ -52,7 +52,7 @@ public class IOPlugin(meta: Meta) : AbstractPlugin(meta) {
|
||||
public fun resolveEnvelopeFormat(item: Meta): EnvelopeFormat? {
|
||||
val name = item.string ?: item[NAME_KEY]?.string ?: error("Envelope format name not defined")
|
||||
val meta = item[META_KEY] ?: Meta.EMPTY
|
||||
return resolveEnvelopeFormat(name.toName(), meta)
|
||||
return resolveEnvelopeFormat(Name.parse(name), meta)
|
||||
}
|
||||
|
||||
override fun content(target: String): Map<Name, Any> {
|
||||
|
@ -10,7 +10,7 @@ import space.kscience.dataforge.meta.get
|
||||
import space.kscience.dataforge.meta.string
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.plus
|
||||
import space.kscience.dataforge.names.toName
|
||||
|
||||
|
||||
/**
|
||||
* A streaming-friendly envelope format with a short binary tag.
|
||||
@ -121,7 +121,7 @@ public class TaggedEnvelopeFormat(
|
||||
override fun invoke(meta: Meta, context: Context): EnvelopeFormat {
|
||||
val io = context.io
|
||||
|
||||
val metaFormatName = meta["name"].string?.toName() ?: JsonMetaFormat.name
|
||||
val metaFormatName = meta["name"].string?.let { Name.parse(it) } ?: JsonMetaFormat.name
|
||||
//Check if appropriate factory exists
|
||||
io.metaFormatFactories.find { it.name == metaFormatName } ?: error("Meta format could not be resolved")
|
||||
|
||||
|
@ -7,7 +7,6 @@ import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.MetaSerializer
|
||||
import space.kscience.dataforge.meta.seal
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.toName
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
@ -43,7 +42,7 @@ class MetaSerializerTest {
|
||||
|
||||
@Test
|
||||
fun testNameSerialization() {
|
||||
val name = "a.b.c".toName()
|
||||
val name = Name.parse("a.b.c")
|
||||
val string = JSON_PRETTY.encodeToString(Name.serializer(), name)
|
||||
val restored = JSON_PLAIN.decodeFromString(Name.serializer(), string)
|
||||
assertEquals(name, restored)
|
||||
|
@ -16,6 +16,13 @@ public interface MetaRepr {
|
||||
public fun toMeta(): Meta
|
||||
}
|
||||
|
||||
/**
|
||||
* A container for meta nodes
|
||||
*/
|
||||
public fun interface MetaProvider {
|
||||
public fun getMeta(name: Name): Meta?
|
||||
}
|
||||
|
||||
/**
|
||||
* A meta node
|
||||
* TODO add documentation
|
||||
@ -23,10 +30,12 @@ public interface MetaRepr {
|
||||
*/
|
||||
@Type(Meta.TYPE)
|
||||
@Serializable(MetaSerializer::class)
|
||||
public interface Meta : MetaRepr {
|
||||
public interface Meta : MetaRepr, MetaProvider {
|
||||
public val value: Value?
|
||||
public val items: Map<NameToken, Meta>
|
||||
|
||||
override fun getMeta(name: Name): Meta? = find(name)
|
||||
|
||||
override fun toMeta(): Meta = this
|
||||
|
||||
override fun toString(): String
|
||||
@ -66,6 +75,12 @@ public interface Meta : MetaRepr {
|
||||
public fun toString(meta: Meta): String = json.encodeToString(MetaSerializer, meta)
|
||||
|
||||
public val EMPTY: Meta = SealedMeta(null, emptyMap())
|
||||
|
||||
private tailrec fun Meta.find(name: Name): Meta? = if (name.isEmpty()) {
|
||||
this
|
||||
} else {
|
||||
items[name.firstOrNull()!!]?.find(name.cutFirst())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -82,16 +97,12 @@ public operator fun Meta.get(token: NameToken): Meta? = items[token]
|
||||
*
|
||||
* If [name] is empty return current [Meta]
|
||||
*/
|
||||
public tailrec operator fun Meta.get(name: Name): Meta? = if (name.isEmpty()) {
|
||||
this
|
||||
} else {
|
||||
get(name.firstOrNull()!!)?.get(name.cutFirst())
|
||||
}
|
||||
public operator fun Meta.get(name: Name): Meta? = getMeta(name)
|
||||
|
||||
/**
|
||||
* Parse [Name] from [key] using full name notation and pass it to [Meta.get]
|
||||
*/
|
||||
public operator fun Meta.get(key: String): Meta? = this[key.toName()]
|
||||
public operator fun Meta.get(key: String): Meta? = this[Name.parse(key)]
|
||||
|
||||
/**
|
||||
* Get all items matching given name. The index of the last element, if present is used as a [Regex],
|
||||
@ -155,7 +166,7 @@ public tailrec operator fun <M : TypedMeta<M>> TypedMeta<M>.get(name: Name): M?
|
||||
/**
|
||||
* Parse [Name] from [key] using full name notation and pass it to [TypedMeta.get]
|
||||
*/
|
||||
public operator fun <M : TypedMeta<M>> TypedMeta<M>.get(key: String): M? = this[key.toName()]
|
||||
public operator fun <M : TypedMeta<M>> TypedMeta<M>.get(key: String): M? = this[Name.parse(key)]
|
||||
|
||||
|
||||
/**
|
||||
@ -197,7 +208,7 @@ public fun Meta.isEmpty(): Boolean = this === Meta.EMPTY || (value == null && it
|
||||
public fun <M : TypedMeta<M>> TypedMeta<M>.getIndexed(name: Name): Map<String?, M> =
|
||||
(this as Meta).getIndexed(name) as Map<String?, M>
|
||||
|
||||
public fun <M : TypedMeta<M>> TypedMeta<M>.getIndexed(name: String): Map<String?, Meta> = getIndexed(name.toName())
|
||||
public fun <M : TypedMeta<M>> TypedMeta<M>.getIndexed(name: String): Map<String?, Meta> = getIndexed(Name.parse(name))
|
||||
|
||||
|
||||
public val Meta?.string: String? get() = this?.value?.string
|
||||
|
@ -10,8 +10,8 @@ import kotlin.properties.ReadOnlyProperty
|
||||
|
||||
public typealias MetaDelegate = ReadOnlyProperty<Any?, Meta?>
|
||||
|
||||
public fun Meta.item(key: Name? = null): MetaDelegate = ReadOnlyProperty { _, property ->
|
||||
get(key ?: property.name.asName())
|
||||
public fun MetaProvider.item(key: Name? = null): MetaDelegate = ReadOnlyProperty { _, property ->
|
||||
getMeta(key ?: property.name.asName())
|
||||
}
|
||||
|
||||
//TODO add caching for sealed nodes
|
||||
@ -50,62 +50,62 @@ public fun <R> MetaDelegate.convert(
|
||||
/**
|
||||
* A property delegate that uses custom key
|
||||
*/
|
||||
public fun Meta.value(key: Name? = null): ReadOnlyProperty<Any?, Value?> =
|
||||
public fun MetaProvider.value(key: Name? = null): ReadOnlyProperty<Any?, Value?> =
|
||||
item(key).convert(MetaConverter.value)
|
||||
|
||||
public fun Meta.string(key: Name? = null): ReadOnlyProperty<Any?, String?> =
|
||||
public fun MetaProvider.string(key: Name? = null): ReadOnlyProperty<Any?, String?> =
|
||||
item(key).convert(MetaConverter.string)
|
||||
|
||||
public fun Meta.boolean(key: Name? = null): ReadOnlyProperty<Any?, Boolean?> =
|
||||
public fun MetaProvider.boolean(key: Name? = null): ReadOnlyProperty<Any?, Boolean?> =
|
||||
item(key).convert(MetaConverter.boolean)
|
||||
|
||||
public fun Meta.number(key: Name? = null): ReadOnlyProperty<Any?, Number?> =
|
||||
public fun MetaProvider.number(key: Name? = null): ReadOnlyProperty<Any?, Number?> =
|
||||
item(key).convert(MetaConverter.number)
|
||||
|
||||
public fun Meta.double(key: Name? = null): ReadOnlyProperty<Any?, Double?> =
|
||||
public fun MetaProvider.double(key: Name? = null): ReadOnlyProperty<Any?, Double?> =
|
||||
item(key).convert(MetaConverter.double)
|
||||
|
||||
public fun Meta.float(key: Name? = null): ReadOnlyProperty<Any?, Float?> =
|
||||
public fun MetaProvider.float(key: Name? = null): ReadOnlyProperty<Any?, Float?> =
|
||||
item(key).convert(MetaConverter.float)
|
||||
|
||||
public fun Meta.int(key: Name? = null): ReadOnlyProperty<Any?, Int?> =
|
||||
public fun MetaProvider.int(key: Name? = null): ReadOnlyProperty<Any?, Int?> =
|
||||
item(key).convert(MetaConverter.int)
|
||||
|
||||
public fun Meta.long(key: Name? = null): ReadOnlyProperty<Any?, Long?> =
|
||||
public fun MetaProvider.long(key: Name? = null): ReadOnlyProperty<Any?, Long?> =
|
||||
item(key).convert(MetaConverter.long)
|
||||
|
||||
public fun Meta.node(key: Name? = null): ReadOnlyProperty<Any?, Meta?> =
|
||||
public fun MetaProvider.node(key: Name? = null): ReadOnlyProperty<Any?, Meta?> =
|
||||
item(key).convert(MetaConverter.meta)
|
||||
|
||||
public fun Meta.string(default: String, key: Name? = null): ReadOnlyProperty<Any?, String> =
|
||||
public fun MetaProvider.string(default: String, key: Name? = null): ReadOnlyProperty<Any?, String> =
|
||||
item(key).convert(MetaConverter.string) { default }
|
||||
|
||||
public fun Meta.boolean(default: Boolean, key: Name? = null): ReadOnlyProperty<Any?, Boolean> =
|
||||
public fun MetaProvider.boolean(default: Boolean, key: Name? = null): ReadOnlyProperty<Any?, Boolean> =
|
||||
item(key).convert(MetaConverter.boolean) { default }
|
||||
|
||||
public fun Meta.number(default: Number, key: Name? = null): ReadOnlyProperty<Any?, Number> =
|
||||
public fun MetaProvider.number(default: Number, key: Name? = null): ReadOnlyProperty<Any?, Number> =
|
||||
item(key).convert(MetaConverter.number) { default }
|
||||
|
||||
public fun Meta.double(default: Double, key: Name? = null): ReadOnlyProperty<Any?, Double> =
|
||||
public fun MetaProvider.double(default: Double, key: Name? = null): ReadOnlyProperty<Any?, Double> =
|
||||
item(key).convert(MetaConverter.double) { default }
|
||||
|
||||
public fun Meta.float(default: Float, key: Name? = null): ReadOnlyProperty<Any?, Float> =
|
||||
public fun MetaProvider.float(default: Float, key: Name? = null): ReadOnlyProperty<Any?, Float> =
|
||||
item(key).convert(MetaConverter.float) { default }
|
||||
|
||||
public fun Meta.int(default: Int, key: Name? = null): ReadOnlyProperty<Any?, Int> =
|
||||
public fun MetaProvider.int(default: Int, key: Name? = null): ReadOnlyProperty<Any?, Int> =
|
||||
item(key).convert(MetaConverter.int) { default }
|
||||
|
||||
public fun Meta.long(default: Long, key: Name? = null): ReadOnlyProperty<Any?, Long> =
|
||||
public fun MetaProvider.long(default: Long, key: Name? = null): ReadOnlyProperty<Any?, Long> =
|
||||
item(key).convert(MetaConverter.long) { default }
|
||||
|
||||
public inline fun <reified E : Enum<E>> Meta.enum(default: E, key: Name? = null): ReadOnlyProperty<Any?, E> =
|
||||
public inline fun <reified E : Enum<E>> MetaProvider.enum(default: E, key: Name? = null): ReadOnlyProperty<Any?, E> =
|
||||
item(key).convert(MetaConverter.enum()) { default }
|
||||
|
||||
public fun Meta.string(key: Name? = null, default: () -> String): ReadOnlyProperty<Any?, String> =
|
||||
public fun MetaProvider.string(key: Name? = null, default: () -> String): ReadOnlyProperty<Any?, String> =
|
||||
item(key).convert(MetaConverter.string, default)
|
||||
|
||||
public fun Meta.boolean(key: Name? = null, default: () -> Boolean): ReadOnlyProperty<Any?, Boolean> =
|
||||
public fun MetaProvider.boolean(key: Name? = null, default: () -> Boolean): ReadOnlyProperty<Any?, Boolean> =
|
||||
item(key).convert(MetaConverter.boolean, default)
|
||||
|
||||
public fun Meta.number(key: Name? = null, default: () -> Number): ReadOnlyProperty<Any?, Number> =
|
||||
public fun MetaProvider.number(key: Name? = null, default: () -> Number): ReadOnlyProperty<Any?, Number> =
|
||||
item(key).convert(MetaConverter.number, default)
|
||||
|
@ -16,13 +16,17 @@ import kotlin.jvm.Synchronized
|
||||
@DslMarker
|
||||
public annotation class MetaBuilder
|
||||
|
||||
public interface MutableMetaProvider : MetaProvider {
|
||||
public fun setMeta(name: Name, node: Meta?)
|
||||
}
|
||||
|
||||
/**
|
||||
* Mutable variant of [Meta]
|
||||
* TODO documentation
|
||||
*/
|
||||
@Serializable(MutableMetaSerializer::class)
|
||||
@MetaBuilder
|
||||
public interface MutableMeta : Meta {
|
||||
public interface MutableMeta : Meta, MutableMetaProvider {
|
||||
|
||||
override val items: Map<NameToken, MutableMeta>
|
||||
|
||||
@ -36,6 +40,14 @@ public interface MutableMeta : Meta {
|
||||
*/
|
||||
public operator fun set(name: Name, meta: Meta)
|
||||
|
||||
override fun setMeta(name: Name, node: Meta?) {
|
||||
if (node == null) {
|
||||
remove(name)
|
||||
} else {
|
||||
set(name, node)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a node at a given [name] if it is present
|
||||
*/
|
||||
@ -85,47 +97,47 @@ public interface MutableMeta : Meta {
|
||||
}
|
||||
|
||||
public infix fun String.put(meta: Meta) {
|
||||
toName() put meta
|
||||
Name.parse(this) put meta
|
||||
}
|
||||
|
||||
public infix fun String.put(value: Value?) {
|
||||
set(toName(), value)
|
||||
set(Name.parse(this), value)
|
||||
}
|
||||
|
||||
public infix fun String.put(string: String) {
|
||||
set(toName(), string.asValue())
|
||||
set(Name.parse(this), string.asValue())
|
||||
}
|
||||
|
||||
public infix fun String.put(number: Number) {
|
||||
set(toName(), number.asValue())
|
||||
set(Name.parse(this), number.asValue())
|
||||
}
|
||||
|
||||
public infix fun String.put(boolean: Boolean) {
|
||||
set(toName(), boolean.asValue())
|
||||
set(Name.parse(this), boolean.asValue())
|
||||
}
|
||||
|
||||
public infix fun String.put(enum: Enum<*>) {
|
||||
set(toName(), EnumValue(enum))
|
||||
set(Name.parse(this), EnumValue(enum))
|
||||
}
|
||||
|
||||
public infix fun String.put(array: DoubleArray) {
|
||||
set(toName(), array.asValue())
|
||||
set(Name.parse(this), array.asValue())
|
||||
}
|
||||
|
||||
public infix fun String.put(repr: MetaRepr) {
|
||||
toName() put repr.toMeta()
|
||||
Name.parse(this) put repr.toMeta()
|
||||
}
|
||||
|
||||
public infix fun String.put(iterable: Iterable<Meta>) {
|
||||
setIndexed(toName(), iterable)
|
||||
setIndexed(Name.parse(this), iterable)
|
||||
}
|
||||
|
||||
public infix fun String.put(builder: MutableMeta.() -> Unit) {
|
||||
set(toName(), MutableMeta(builder))
|
||||
set(Name.parse(this), MutableMeta(builder))
|
||||
}
|
||||
}
|
||||
|
||||
public fun MutableMeta.getOrCreate(string: String): MutableMeta = getOrCreate(string.toName())
|
||||
public fun MutableMeta.getOrCreate(key: String): MutableMeta = getOrCreate(Name.parse(key))
|
||||
|
||||
@Serializable(MutableMetaSerializer::class)
|
||||
public interface MutableTypedMeta<M : MutableTypedMeta<M>> : TypedMeta<M>, MutableMeta {
|
||||
@ -138,47 +150,37 @@ public interface MutableTypedMeta<M : MutableTypedMeta<M>> : TypedMeta<M>, Mutab
|
||||
override fun getOrCreate(name: Name): M
|
||||
}
|
||||
|
||||
public fun <M : MutableTypedMeta<M>> M.getOrCreate(string: String): M = getOrCreate(string.toName())
|
||||
public fun <M : MutableTypedMeta<M>> M.getOrCreate(key: String): M = getOrCreate(Name.parse(key))
|
||||
|
||||
public fun MutableMeta.remove(name: String){
|
||||
remove(name.toName())
|
||||
public fun MutableMeta.remove(key: String) {
|
||||
remove(Name.parse(key))
|
||||
}
|
||||
|
||||
// node setters
|
||||
|
||||
public operator fun MutableMeta.set(name: NameToken, value: Meta): Unit = set(name.asName(), value)
|
||||
public operator fun MutableMeta.set(name: Name, meta: Meta?): Unit {
|
||||
if (meta == null) {
|
||||
remove(name)
|
||||
} else {
|
||||
set(name, meta)
|
||||
}
|
||||
}
|
||||
|
||||
public operator fun MutableMeta.set(key: String, meta: Meta?): Unit {
|
||||
set(key.toName(), meta)
|
||||
}
|
||||
public operator fun MutableMetaProvider.set(Key: NameToken, value: Meta): Unit = setMeta(Key.asName(), value)
|
||||
public operator fun MutableMetaProvider.set(key: String, value: Meta): Unit = setMeta(Name.parse(key), value)
|
||||
|
||||
//value setters
|
||||
|
||||
public operator fun MutableMeta.set(name: NameToken, value: Value?): Unit = set(name.asName(), value)
|
||||
public operator fun MutableMeta.set(key: String, value: Value?): Unit = set(key.toName(), value)
|
||||
public operator fun MutableMeta.set(key: String, value: Value?): Unit = set(Name.parse(key), value)
|
||||
|
||||
public operator fun MutableMeta.set(name: Name, value: String): Unit = set(name, value.asValue())
|
||||
public operator fun MutableMeta.set(name: NameToken, value: String): Unit = set(name.asName(), value.asValue())
|
||||
public operator fun MutableMeta.set(key: String, value: String): Unit = set(key.toName(), value.asValue())
|
||||
public operator fun MutableMeta.set(key: String, value: String): Unit = set(Name.parse(key), value.asValue())
|
||||
|
||||
public operator fun MutableMeta.set(name: Name, value: Boolean): Unit = set(name, value.asValue())
|
||||
public operator fun MutableMeta.set(name: NameToken, value: Boolean): Unit = set(name.asName(), value.asValue())
|
||||
public operator fun MutableMeta.set(key: String, value: Boolean): Unit = set(key.toName(), value.asValue())
|
||||
public operator fun MutableMeta.set(key: String, value: Boolean): Unit = set(Name.parse(key), value.asValue())
|
||||
|
||||
public operator fun MutableMeta.set(name: Name, value: Number): Unit = set(name, value.asValue())
|
||||
public operator fun MutableMeta.set(name: NameToken, value: Number): Unit = set(name.asName(), value.asValue())
|
||||
public operator fun MutableMeta.set(key: String, value: Number): Unit = set(key.toName(), value.asValue())
|
||||
public operator fun MutableMeta.set(key: String, value: Number): Unit = set(Name.parse(key), value.asValue())
|
||||
|
||||
public operator fun MutableMeta.set(name: Name, value: List<Value>): Unit = set(name, value.asValue())
|
||||
public operator fun MutableMeta.set(name: NameToken, value: List<Value>): Unit = set(name.asName(), value.asValue())
|
||||
public operator fun MutableMeta.set(key: String, value: List<Value>): Unit = set(key.toName(), value.asValue())
|
||||
public operator fun MutableMeta.set(key: String, value: List<Value>): Unit = set(Name.parse(key), value.asValue())
|
||||
|
||||
//public fun MutableMeta.set(key: String, index: String, value: Value?): Unit =
|
||||
// set(key.toName().withIndex(index), value)
|
||||
@ -218,8 +220,8 @@ public fun MutableMeta.setIndexed(
|
||||
public operator fun MutableMeta.set(name: Name, metas: Iterable<Meta>): Unit =
|
||||
setIndexed(name, metas)
|
||||
|
||||
public operator fun MutableMeta.set(name: String, metas: Iterable<Meta>): Unit =
|
||||
setIndexed(name.toName(), metas)
|
||||
public operator fun MutableMeta.set(key: String, metas: Iterable<Meta>): Unit =
|
||||
setIndexed(Name.parse(key), metas)
|
||||
|
||||
|
||||
/**
|
||||
@ -396,13 +398,13 @@ public fun MutableMeta.append(name: Name, meta: Meta) {
|
||||
}
|
||||
|
||||
@DFExperimental
|
||||
public fun MutableMeta.append(name: String, meta: Meta): Unit = append(name.toName(), meta)
|
||||
public fun MutableMeta.append(key: String, meta: Meta): Unit = append(Name.parse(key), meta)
|
||||
|
||||
@DFExperimental
|
||||
public fun MutableMeta.append(name: Name, value: Value): Unit = append(name, Meta(value))
|
||||
|
||||
@DFExperimental
|
||||
public fun MutableMeta.append(name: String, value: Value): Unit = append(name.toName(), value)
|
||||
public fun MutableMeta.append(key: String, value: Value): Unit = append(Name.parse(key), value)
|
||||
|
||||
///**
|
||||
// * Apply existing node with given [builder] or create a new element with it.
|
||||
@ -443,8 +445,9 @@ public inline fun Meta.copy(block: MutableMeta.() -> Unit = {}): Meta =
|
||||
toMutableMeta().apply(block)
|
||||
|
||||
|
||||
private class MutableMetaWithDefault(val source: MutableMeta, val default: Meta, val name: Name) :
|
||||
MutableMeta by source {
|
||||
private class MutableMetaWithDefault(
|
||||
val source: MutableMeta, val default: Meta, val name: Name
|
||||
) : MutableMeta by source {
|
||||
override val items: Map<NameToken, MutableMeta>
|
||||
get() = (source.items.keys + default.items.keys).associateWith {
|
||||
MutableMetaWithDefault(source, default, name + it)
|
||||
@ -456,6 +459,8 @@ private class MutableMetaWithDefault(val source: MutableMeta, val default: Meta,
|
||||
source[name] = value
|
||||
}
|
||||
|
||||
override fun getMeta(name: Name): Meta? = source.getMeta(name) ?: default.getMeta(name)
|
||||
|
||||
override fun toString(): String = Meta.toString(this)
|
||||
override fun equals(other: Any?): Boolean = Meta.equals(this, other as? Meta)
|
||||
override fun hashCode(): Int = Meta.hashCode(this)
|
||||
|
@ -11,14 +11,14 @@ import kotlin.reflect.KProperty
|
||||
|
||||
public typealias MutableMetaDelegate = ReadWriteProperty<Any?, Meta?>
|
||||
|
||||
public fun MutableMeta.item(key: Name? = null): MutableMetaDelegate = object : MutableMetaDelegate {
|
||||
public fun MutableMetaProvider.item(key: Name? = null): MutableMetaDelegate = object : MutableMetaDelegate {
|
||||
override fun getValue(thisRef: Any?, property: KProperty<*>): Meta? {
|
||||
return get(key ?: property.name.asName())
|
||||
return getMeta(key ?: property.name.asName())
|
||||
}
|
||||
|
||||
override fun setValue(thisRef: Any?, property: KProperty<*>, value: Meta?) {
|
||||
val name = key ?: property.name.asName()
|
||||
set(name, value)
|
||||
setMeta(name, value)
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,40 +74,40 @@ public fun <R> MutableMetaDelegate.convert(
|
||||
/**
|
||||
* A property delegate that uses custom key
|
||||
*/
|
||||
public fun MutableMeta.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
|
||||
public fun MutableMetaProvider.value(key: Name? = null): ReadWriteProperty<Any?, Value?> =
|
||||
item(key).convert(MetaConverter.value)
|
||||
|
||||
public fun MutableMeta.string(key: Name? = null): ReadWriteProperty<Any?, String?> =
|
||||
public fun MutableMetaProvider.string(key: Name? = null): ReadWriteProperty<Any?, String?> =
|
||||
item(key).convert(MetaConverter.string)
|
||||
|
||||
public fun MutableMeta.boolean(key: Name? = null): ReadWriteProperty<Any?, Boolean?> =
|
||||
public fun MutableMetaProvider.boolean(key: Name? = null): ReadWriteProperty<Any?, Boolean?> =
|
||||
item(key).convert(MetaConverter.boolean)
|
||||
|
||||
public fun MutableMeta.number(key: Name? = null): ReadWriteProperty<Any?, Number?> =
|
||||
public fun MutableMetaProvider.number(key: Name? = null): ReadWriteProperty<Any?, Number?> =
|
||||
item(key).convert(MetaConverter.number)
|
||||
|
||||
public fun MutableMeta.string(default: String, key: Name? = null): ReadWriteProperty<Any?, String> =
|
||||
public fun MutableMetaProvider.string(default: String, key: Name? = null): ReadWriteProperty<Any?, String> =
|
||||
item(key).convert(MetaConverter.string) { default }
|
||||
|
||||
public fun MutableMeta.boolean(default: Boolean, key: Name? = null): ReadWriteProperty<Any?, Boolean> =
|
||||
public fun MutableMetaProvider.boolean(default: Boolean, key: Name? = null): ReadWriteProperty<Any?, Boolean> =
|
||||
item(key).convert(MetaConverter.boolean) { default }
|
||||
|
||||
public fun MutableMeta.number(default: Number, key: Name? = null): ReadWriteProperty<Any?, Number> =
|
||||
public fun MutableMetaProvider.number(default: Number, key: Name? = null): ReadWriteProperty<Any?, Number> =
|
||||
item(key).convert(MetaConverter.number) { default }
|
||||
|
||||
public fun MutableMeta.value(key: Name? = null, default: () -> Value): ReadWriteProperty<Any?, Value> =
|
||||
public fun MutableMetaProvider.value(key: Name? = null, default: () -> Value): ReadWriteProperty<Any?, Value> =
|
||||
item(key).convert(MetaConverter.value, default)
|
||||
|
||||
public fun MutableMeta.string(key: Name? = null, default: () -> String): ReadWriteProperty<Any?, String> =
|
||||
public fun MutableMetaProvider.string(key: Name? = null, default: () -> String): ReadWriteProperty<Any?, String> =
|
||||
item(key).convert(MetaConverter.string, default)
|
||||
|
||||
public fun MutableMeta.boolean(key: Name? = null, default: () -> Boolean): ReadWriteProperty<Any?, Boolean> =
|
||||
public fun MutableMetaProvider.boolean(key: Name? = null, default: () -> Boolean): ReadWriteProperty<Any?, Boolean> =
|
||||
item(key).convert(MetaConverter.boolean, default)
|
||||
|
||||
public fun MutableMeta.number(key: Name? = null, default: () -> Number): ReadWriteProperty<Any?, Number> =
|
||||
public fun MutableMetaProvider.number(key: Name? = null, default: () -> Number): ReadWriteProperty<Any?, Number> =
|
||||
item(key).convert(MetaConverter.number, default)
|
||||
|
||||
public inline fun <reified E : Enum<E>> MutableMeta.enum(
|
||||
public inline fun <reified E : Enum<E>> MutableMetaProvider.enum(
|
||||
default: E,
|
||||
key: Name? = null,
|
||||
): ReadWriteProperty<Any?, E> =
|
||||
@ -115,37 +115,37 @@ public inline fun <reified E : Enum<E>> MutableMeta.enum(
|
||||
|
||||
/* Number delegates */
|
||||
|
||||
public fun MutableMeta.int(key: Name? = null): ReadWriteProperty<Any?, Int?> =
|
||||
public fun MutableMetaProvider.int(key: Name? = null): ReadWriteProperty<Any?, Int?> =
|
||||
item(key).convert(MetaConverter.int)
|
||||
|
||||
public fun MutableMeta.double(key: Name? = null): ReadWriteProperty<Any?, Double?> =
|
||||
public fun MutableMetaProvider.double(key: Name? = null): ReadWriteProperty<Any?, Double?> =
|
||||
item(key).convert(MetaConverter.double)
|
||||
|
||||
public fun MutableMeta.long(key: Name? = null): ReadWriteProperty<Any?, Long?> =
|
||||
public fun MutableMetaProvider.long(key: Name? = null): ReadWriteProperty<Any?, Long?> =
|
||||
item(key).convert(MetaConverter.long)
|
||||
|
||||
public fun MutableMeta.float(key: Name? = null): ReadWriteProperty<Any?, Float?> =
|
||||
public fun MutableMetaProvider.float(key: Name? = null): ReadWriteProperty<Any?, Float?> =
|
||||
item(key).convert(MetaConverter.float)
|
||||
|
||||
|
||||
/* Safe number delegates*/
|
||||
|
||||
public fun MutableMeta.int(default: Int, key: Name? = null): ReadWriteProperty<Any?, Int> =
|
||||
public fun MutableMetaProvider.int(default: Int, key: Name? = null): ReadWriteProperty<Any?, Int> =
|
||||
item(key).convert(MetaConverter.int) { default }
|
||||
|
||||
public fun MutableMeta.double(default: Double, key: Name? = null): ReadWriteProperty<Any?, Double> =
|
||||
public fun MutableMetaProvider.double(default: Double, key: Name? = null): ReadWriteProperty<Any?, Double> =
|
||||
item(key).convert(MetaConverter.double) { default }
|
||||
|
||||
public fun MutableMeta.long(default: Long, key: Name? = null): ReadWriteProperty<Any?, Long> =
|
||||
public fun MutableMetaProvider.long(default: Long, key: Name? = null): ReadWriteProperty<Any?, Long> =
|
||||
item(key).convert(MetaConverter.long) { default }
|
||||
|
||||
public fun MutableMeta.float(default: Float, key: Name? = null): ReadWriteProperty<Any?, Float> =
|
||||
public fun MutableMetaProvider.float(default: Float, key: Name? = null): ReadWriteProperty<Any?, Float> =
|
||||
item(key).convert(MetaConverter.float) { default }
|
||||
|
||||
|
||||
/* Extra delegates for special cases */
|
||||
|
||||
public fun MutableMeta.stringList(
|
||||
public fun MutableMetaProvider.stringList(
|
||||
vararg default: String,
|
||||
key: Name? = null,
|
||||
): ReadWriteProperty<Any?, List<String>> = item(key).convert(
|
||||
@ -153,14 +153,14 @@ public fun MutableMeta.stringList(
|
||||
writer = { Meta(it.map { str -> str.asValue() }.asValue()) }
|
||||
)
|
||||
|
||||
public fun MutableMeta.stringList(
|
||||
public fun MutableMetaProvider.stringList(
|
||||
key: Name? = null,
|
||||
): ReadWriteProperty<Any?, List<String>?> = item(key).convert(
|
||||
reader = { it?.stringList },
|
||||
writer = { it?.map { str -> str.asValue() }?.asValue()?.let { Meta(it) } }
|
||||
)
|
||||
|
||||
public fun MutableMeta.numberList(
|
||||
public fun MutableMetaProvider.numberList(
|
||||
vararg default: Number,
|
||||
key: Name? = null,
|
||||
): ReadWriteProperty<Any?, List<Number>> = item(key).convert(
|
||||
@ -171,7 +171,7 @@ public fun MutableMeta.numberList(
|
||||
/* A special delegate for double arrays */
|
||||
|
||||
|
||||
public fun MutableMeta.doubleArray(
|
||||
public fun MutableMetaProvider.doubleArray(
|
||||
vararg default: Double,
|
||||
key: Name? = null,
|
||||
): ReadWriteProperty<Any?, DoubleArray> = item(key).convert(
|
||||
@ -179,7 +179,7 @@ public fun MutableMeta.doubleArray(
|
||||
writer = { Meta(DoubleArrayValue(it)) }
|
||||
)
|
||||
|
||||
public fun <T> MutableMeta.listValue(
|
||||
public fun <T> MutableMetaProvider.listValue(
|
||||
key: Name? = null,
|
||||
writer: (T) -> Value = { Value.of(it) },
|
||||
reader: (Value) -> T,
|
||||
|
@ -1,9 +1,6 @@
|
||||
package space.kscience.dataforge.meta
|
||||
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.NameToken
|
||||
import space.kscience.dataforge.names.asName
|
||||
import space.kscience.dataforge.names.startsWith
|
||||
import space.kscience.dataforge.names.*
|
||||
import space.kscience.dataforge.values.Value
|
||||
import kotlin.jvm.Synchronized
|
||||
import kotlin.reflect.KProperty1
|
||||
@ -57,6 +54,8 @@ private class ObservableMetaWrapper(
|
||||
override val items: Map<NameToken, ObservableMetaWrapper>
|
||||
get() = origin.items.mapValues { ObservableMetaWrapper(it.value) }
|
||||
|
||||
override fun getMeta(name: Name): Meta? = origin.getMeta(name)
|
||||
|
||||
override var value: Value?
|
||||
get() = origin.value
|
||||
set(value) {
|
||||
@ -86,7 +85,10 @@ private class ObservableMetaWrapper(
|
||||
}
|
||||
|
||||
override fun attach(name: Name, node: ObservableMutableMeta) {
|
||||
TODO("Not yet implemented")
|
||||
set(name, node)
|
||||
node.onChange(this) { changeName ->
|
||||
setMeta(name + changeName, node[changeName])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,14 +106,14 @@ public fun MutableMeta.asObservable(): ObservableMutableMeta =
|
||||
*
|
||||
* Optional [owner] property is used for
|
||||
*/
|
||||
public fun <O : ObservableMeta, T> O.useProperty(
|
||||
property: KProperty1<O, T>,
|
||||
public fun <S : Scheme, T> S.useProperty(
|
||||
property: KProperty1<S, T>,
|
||||
owner: Any? = null,
|
||||
callBack: O.(T) -> Unit,
|
||||
callBack: S.(T) -> Unit,
|
||||
) {
|
||||
//Pass initial value.
|
||||
callBack(property.get(this))
|
||||
onChange(owner) { name ->
|
||||
meta.onChange(owner) { name ->
|
||||
if (name.startsWith(property.name.asName())) {
|
||||
callBack(property.get(this@useProperty))
|
||||
}
|
||||
|
@ -2,35 +2,24 @@ package space.kscience.dataforge.meta
|
||||
|
||||
import space.kscience.dataforge.meta.descriptors.*
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.NameToken
|
||||
import space.kscience.dataforge.values.Value
|
||||
|
||||
/**
|
||||
* A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [Specification].
|
||||
* Default item provider and [NodeDescriptor] are optional
|
||||
* Default item provider and [MetaDescriptor] are optional
|
||||
*/
|
||||
public open class Scheme(
|
||||
source: MutableMeta = MutableMeta()
|
||||
) : Described, MutableMeta, ObservableMeta, Meta by source {
|
||||
public open class Scheme : Described, MetaRepr, MutableMetaProvider {
|
||||
|
||||
private var source = source.asObservable()
|
||||
public var meta: ObservableMutableMeta = MutableMeta()
|
||||
private set
|
||||
|
||||
final override var descriptor: MetaDescriptor? = null
|
||||
internal set
|
||||
|
||||
override var value: Value?
|
||||
get() = source.value
|
||||
set(value) {
|
||||
source.value = value
|
||||
}
|
||||
|
||||
override val items: Map<NameToken, MutableMeta> get() = source.items
|
||||
|
||||
internal fun wrap(
|
||||
items: MutableMeta,
|
||||
preserveDefault: Boolean = false
|
||||
) {
|
||||
this.source = (if (preserveDefault) items.withDefault(this.source) else items).asObservable()
|
||||
meta = (if (preserveDefault) items.withDefault(meta.seal()) else items).asObservable()
|
||||
}
|
||||
|
||||
/**
|
||||
@ -41,35 +30,17 @@ public open class Scheme(
|
||||
return descriptor?.validate(meta) ?: true
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a configurable property
|
||||
*/
|
||||
override fun set(name: Name, meta: Meta) {
|
||||
val oldItem = source[name]
|
||||
if (oldItem != meta) {
|
||||
if (validate(name, meta)) {
|
||||
source[name] = meta
|
||||
} else {
|
||||
error("Validation failed for property $name with value $meta")
|
||||
}
|
||||
override fun getMeta(name: Name): Meta? = meta.getMeta(name)
|
||||
|
||||
override fun setMeta(name: Name, node: Meta?) {
|
||||
if (validate(name, meta)) {
|
||||
meta.setMeta(name, node)
|
||||
} else {
|
||||
error("Validation failed for node $node at $name")
|
||||
}
|
||||
}
|
||||
|
||||
override fun toMeta(): Laminate = Laminate(source, descriptor?.defaultNode)
|
||||
|
||||
override fun remove(name: Name) {
|
||||
source.remove(name)
|
||||
}
|
||||
|
||||
override fun getOrCreate(name: Name): MutableMeta = source.getOrCreate(name)
|
||||
|
||||
override fun onChange(owner: Any?, callback: Meta.(name: Name) -> Unit) {
|
||||
source.onChange(owner ?: this, callback)
|
||||
}
|
||||
|
||||
override fun removeListener(owner: Any?) {
|
||||
source.removeListener(owner ?: this)
|
||||
}
|
||||
override fun toMeta(): Laminate = Laminate(meta, descriptor?.defaultNode)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -77,6 +77,11 @@ public fun <T : Scheme> MutableMeta.spec(
|
||||
}
|
||||
}
|
||||
|
||||
public fun <T : Scheme> Scheme.spec(
|
||||
spec: Specification<T>,
|
||||
key: Name? = null,
|
||||
): ReadWriteProperty<Any?, T> = meta.spec(spec, key)
|
||||
|
||||
/**
|
||||
* A delegate that uses a [Specification] to wrap a list of child providers.
|
||||
* If children are mutable, the changes in list elements are reflected on them.
|
||||
|
@ -43,7 +43,7 @@ public operator fun MetaDescriptor.get(name: Name): MetaDescriptor? = when (name
|
||||
else -> get(name.firstOrNull()!!.asName())?.get(name.cutFirst())
|
||||
}
|
||||
|
||||
public operator fun MetaDescriptor.get(name: String): MetaDescriptor? = get(name.toName())
|
||||
public operator fun MetaDescriptor.get(name: String): MetaDescriptor? = get(Name.parse(name))
|
||||
|
||||
/**
|
||||
* A node constructed of default values for this descriptor and its children
|
||||
|
@ -4,10 +4,22 @@ import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.MutableMeta
|
||||
import space.kscience.dataforge.meta.get
|
||||
import space.kscience.dataforge.meta.set
|
||||
import space.kscience.dataforge.names.*
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.cutFirst
|
||||
import space.kscience.dataforge.names.first
|
||||
import space.kscience.dataforge.names.length
|
||||
import space.kscience.dataforge.values.Value
|
||||
import space.kscience.dataforge.values.ValueType
|
||||
import space.kscience.dataforge.values.asValue
|
||||
import kotlin.collections.List
|
||||
import kotlin.collections.MutableMap
|
||||
import kotlin.collections.emptyList
|
||||
import kotlin.collections.getOrPut
|
||||
import kotlin.collections.hashMapOf
|
||||
import kotlin.collections.listOf
|
||||
import kotlin.collections.map
|
||||
import kotlin.collections.mapValues
|
||||
import kotlin.collections.set
|
||||
|
||||
public class MetaDescriptorBuilder {
|
||||
public var info: String? = null
|
||||
@ -67,7 +79,7 @@ public class MetaDescriptorBuilder {
|
||||
}
|
||||
|
||||
public fun MetaDescriptorBuilder.item(name: String, block: MetaDescriptorBuilder.() -> Unit) {
|
||||
item(name.toName(), block)
|
||||
item(Name.parse(name), block)
|
||||
}
|
||||
|
||||
public fun MetaDescriptor(block: MetaDescriptorBuilder.() -> Unit): MetaDescriptor =
|
||||
@ -94,7 +106,7 @@ public fun MetaDescriptorBuilder.value(
|
||||
vararg additionalTypes: ValueType,
|
||||
block: MetaDescriptorBuilder.() -> Unit
|
||||
) {
|
||||
value(name.toName(), type, additionalTypes = additionalTypes, block)
|
||||
value(Name.parse(name), type, additionalTypes = additionalTypes, block)
|
||||
}
|
||||
|
||||
/**
|
||||
@ -108,7 +120,7 @@ public fun MetaDescriptorBuilder.node(name: Name, block: MetaDescriptorBuilder.(
|
||||
}
|
||||
|
||||
public fun MetaDescriptorBuilder.node(name: String, block: MetaDescriptorBuilder.() -> Unit) {
|
||||
node(name.toName(), block)
|
||||
node(Name.parse(name), block)
|
||||
}
|
||||
|
||||
public inline fun <reified E : Enum<E>> MetaDescriptorBuilder.enum(
|
||||
|
@ -3,7 +3,7 @@ package space.kscience.dataforge.meta
|
||||
import space.kscience.dataforge.meta.descriptors.MetaDescriptor
|
||||
import space.kscience.dataforge.meta.descriptors.get
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.dataforge.names.toName
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.values.ListValue
|
||||
import space.kscience.dataforge.values.Value
|
||||
|
||||
@ -28,7 +28,7 @@ public fun Meta.toMap(descriptor: MetaDescriptor? = null): Map<String, Any?> = b
|
||||
|
||||
/**
|
||||
* Convert map of maps to meta. This method will recognize [Meta], [Map]<String,Any?> and [List] of all mentioned above as value.
|
||||
* All other values will be converted to values.
|
||||
* All other values will be converted to [Value].
|
||||
*/
|
||||
@DFExperimental
|
||||
public fun Map<String, Any?>.toMeta(descriptor: MetaDescriptor? = null): Meta = Meta {
|
||||
@ -45,7 +45,7 @@ public fun Map<String, Any?>.toMeta(descriptor: MetaDescriptor? = null): Meta =
|
||||
if (items.all { it.isLeaf }) {
|
||||
set(key, ListValue(items.map { it.value!! }))
|
||||
} else {
|
||||
setIndexedItems(key.toName(), value.map { toMeta(it) })
|
||||
setIndexedItems(Name.parse(key), value.map { toMeta(it) })
|
||||
}
|
||||
} else {
|
||||
set(key, toMeta(value))
|
||||
|
@ -42,7 +42,7 @@ public data class KeepTransformationRule(val selector: (Name) -> Boolean) :
|
||||
meta.nodeSequence().map { it.first }.filter(selector)
|
||||
|
||||
override fun transformItem(name: Name, item: Meta?, target: MutableMeta) {
|
||||
if (selector(name)) target.set(name, item)
|
||||
if (selector(name)) target.setMeta(name, item)
|
||||
}
|
||||
}
|
||||
|
||||
@ -174,7 +174,7 @@ public class MetaTransformationBuilder {
|
||||
public fun keep(regex: String) {
|
||||
transformations.add(
|
||||
RegexItemTransformationRule(regex.toRegex()) { name, _, Meta ->
|
||||
set(name, Meta)
|
||||
setMeta(name, Meta)
|
||||
})
|
||||
}
|
||||
|
||||
@ -184,7 +184,7 @@ public class MetaTransformationBuilder {
|
||||
public fun move(from: Name, to: Name, operation: (Meta?) -> Meta? = { it }) {
|
||||
transformations.add(
|
||||
SingleItemTransformationRule(from) { _, item ->
|
||||
set(to, operation(item))
|
||||
setMeta(to, operation(item))
|
||||
}
|
||||
)
|
||||
}
|
||||
|
@ -47,6 +47,61 @@ public class Name(public val tokens: List<NameToken>) {
|
||||
public val MATCH_ALL_TOKEN: NameToken = NameToken("**")
|
||||
|
||||
public val EMPTY: Name = Name(emptyList())
|
||||
|
||||
/**
|
||||
* Convert a [String] to name parsing it and extracting name tokens and index syntax.
|
||||
* This operation is rather heavy so it should be used with care in high performance code.
|
||||
*/
|
||||
public fun parse(string: String): Name{
|
||||
if (string.isBlank()) return Name.EMPTY
|
||||
val tokens = sequence {
|
||||
var bodyBuilder = StringBuilder()
|
||||
var queryBuilder = StringBuilder()
|
||||
var bracketCount: Int = 0
|
||||
var escape: Boolean = false
|
||||
fun queryOn() = bracketCount > 0
|
||||
|
||||
for (it in string) {
|
||||
when {
|
||||
escape -> {
|
||||
if (queryOn()) {
|
||||
queryBuilder.append(it)
|
||||
} else {
|
||||
bodyBuilder.append(it)
|
||||
}
|
||||
escape = false
|
||||
}
|
||||
it == '\\' -> {
|
||||
escape = true
|
||||
}
|
||||
queryOn() -> {
|
||||
when (it) {
|
||||
'[' -> bracketCount++
|
||||
']' -> bracketCount--
|
||||
}
|
||||
if (queryOn()) queryBuilder.append(it)
|
||||
}
|
||||
else -> when (it) {
|
||||
'.' -> {
|
||||
val query = if (queryBuilder.isEmpty()) null else queryBuilder.toString()
|
||||
yield(NameToken(bodyBuilder.toString(), query))
|
||||
bodyBuilder = StringBuilder()
|
||||
queryBuilder = StringBuilder()
|
||||
}
|
||||
'[' -> bracketCount++
|
||||
']' -> error("Syntax error: closing bracket ] not have not matching open bracket")
|
||||
else -> {
|
||||
if (queryBuilder.isNotEmpty()) error("Syntax error: only name end and name separator are allowed after index")
|
||||
bodyBuilder.append(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val query = if (queryBuilder.isEmpty()) null else queryBuilder.toString()
|
||||
yield(NameToken(bodyBuilder.toString(), query))
|
||||
}
|
||||
return Name(tokens.toList())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,61 +135,6 @@ public fun Name.firstOrNull(): NameToken? = tokens.firstOrNull()
|
||||
public fun Name.first(): NameToken = tokens.first()
|
||||
|
||||
|
||||
/**
|
||||
* Convert a [String] to name parsing it and extracting name tokens and index syntax.
|
||||
* This operation is rather heavy so it should be used with care in high performance code.
|
||||
*/
|
||||
public fun String.toName(): Name {
|
||||
if (isBlank()) return Name.EMPTY
|
||||
val tokens = sequence {
|
||||
var bodyBuilder = StringBuilder()
|
||||
var queryBuilder = StringBuilder()
|
||||
var bracketCount: Int = 0
|
||||
var escape: Boolean = false
|
||||
fun queryOn() = bracketCount > 0
|
||||
|
||||
for (it in this@toName) {
|
||||
when {
|
||||
escape -> {
|
||||
if (queryOn()) {
|
||||
queryBuilder.append(it)
|
||||
} else {
|
||||
bodyBuilder.append(it)
|
||||
}
|
||||
escape = false
|
||||
}
|
||||
it == '\\' -> {
|
||||
escape = true
|
||||
}
|
||||
queryOn() -> {
|
||||
when (it) {
|
||||
'[' -> bracketCount++
|
||||
']' -> bracketCount--
|
||||
}
|
||||
if (queryOn()) queryBuilder.append(it)
|
||||
}
|
||||
else -> when (it) {
|
||||
'.' -> {
|
||||
val query = if (queryBuilder.isEmpty()) null else queryBuilder.toString()
|
||||
yield(NameToken(bodyBuilder.toString(), query))
|
||||
bodyBuilder = StringBuilder()
|
||||
queryBuilder = StringBuilder()
|
||||
}
|
||||
'[' -> bracketCount++
|
||||
']' -> error("Syntax error: closing bracket ] not have not matching open bracket")
|
||||
else -> {
|
||||
if (queryBuilder.isNotEmpty()) error("Syntax error: only name end and name separator are allowed after index")
|
||||
bodyBuilder.append(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
val query = if (queryBuilder.isEmpty()) null else queryBuilder.toString()
|
||||
yield(NameToken(bodyBuilder.toString(), query))
|
||||
}
|
||||
return Name(tokens.toList())
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the [String] to a [Name] by simply wrapping it in a single name token without parsing.
|
||||
* The input string could contain dots and braces, but they are just escaped, not parsed.
|
||||
@ -145,7 +145,7 @@ public operator fun NameToken.plus(other: Name): Name = Name(listOf(this) + othe
|
||||
|
||||
public operator fun Name.plus(other: Name): Name = Name(this.tokens + other.tokens)
|
||||
|
||||
public operator fun Name.plus(other: String): Name = this + other.toName()
|
||||
public operator fun Name.plus(other: String): Name = this + Name.parse(other)
|
||||
|
||||
public operator fun Name.plus(other: NameToken): Name = Name(tokens + other)
|
||||
|
||||
@ -174,8 +174,8 @@ public fun Name.withIndex(index: String): Name {
|
||||
* Fast [String]-based accessor for item map
|
||||
*/
|
||||
public operator fun <T> Map<NameToken, T>.get(body: String, query: String? = null): T? = get(NameToken(body, query))
|
||||
public operator fun <T> Map<Name, T>.get(name: String): T? = get(name.toName())
|
||||
public operator fun <T> MutableMap<Name, T>.set(name: String, value: T): Unit = set(name.toName(), value)
|
||||
public operator fun <T> Map<Name, T>.get(name: String): T? = get(Name.parse(name))
|
||||
public operator fun <T> MutableMap<Name, T>.set(name: String, value: T): Unit = set(Name.parse(name), value)
|
||||
|
||||
/* Name comparison operations */
|
||||
|
||||
|
@ -12,7 +12,7 @@ public object NameSerializer : KSerializer<Name> {
|
||||
PrimitiveSerialDescriptor("space.kscience.dataforge.names.Name", PrimitiveKind.STRING)
|
||||
|
||||
override fun deserialize(decoder: Decoder): Name {
|
||||
return decoder.decodeString().toName()
|
||||
return Name.parse(decoder.decodeString())
|
||||
}
|
||||
|
||||
override fun serialize(encoder: Encoder, value: Name) {
|
||||
@ -25,7 +25,7 @@ public object NameTokenSerializer: KSerializer<NameToken> {
|
||||
PrimitiveSerialDescriptor("space.kscience.dataforge.names.NameToken", PrimitiveKind.STRING)
|
||||
|
||||
override fun deserialize(decoder: Decoder): NameToken {
|
||||
return decoder.decodeString().toName().firstOrNull()!!
|
||||
return Name.parse(decoder.decodeString()).firstOrNull()!!
|
||||
}
|
||||
|
||||
override fun serialize(
|
||||
|
@ -44,4 +44,4 @@ public fun Name.matches(pattern: Name): Boolean = when {
|
||||
}
|
||||
|
||||
@OptIn(DFExperimental::class)
|
||||
public fun Name.matches(pattern: String): Boolean = matches(pattern.toName())
|
||||
public fun Name.matches(pattern: String): Boolean = matches(Name.parse(pattern))
|
@ -30,7 +30,7 @@ class MetaDelegateTest {
|
||||
fun delegateTest() {
|
||||
|
||||
val testObject = TestScheme.empty()
|
||||
testObject.set("myValue","theString".asValue())
|
||||
testObject.meta["myValue"] = "theString".asValue()
|
||||
testObject.enumValue = TestEnum.NO
|
||||
|
||||
testObject.inner = InnerScheme { innerValue = "ddd" }
|
||||
|
@ -10,7 +10,7 @@ import kotlin.test.assertTrue
|
||||
class NameMatchTest {
|
||||
@Test
|
||||
fun matchWildCards() {
|
||||
val theName = "a.b.c.d".toName()
|
||||
val theName = Name.parse("a.b.c.d")
|
||||
assertTrue { theName.matches("a.b.**") }
|
||||
assertTrue { theName.matches("a.*.c.**") }
|
||||
assertTrue { theName.matches("**.d") }
|
||||
@ -22,7 +22,7 @@ class NameMatchTest {
|
||||
|
||||
@Test
|
||||
fun matchPattern() {
|
||||
val theName = "a[dd+2].b[13].c.d[\"d\"]".toName()
|
||||
val theName = Name.parse("a[dd+2].b[13].c.d[\"d\"]")
|
||||
assertTrue { theName.matches("a[.*].b[.*].c[.*].d[.*]") }
|
||||
assertTrue { theName.matches("a[.*].b[.*].c.d[.*]") }
|
||||
assertFalse { theName.matches("a[.*].b[.*].*.d") }
|
||||
|
@ -9,7 +9,7 @@ class NameSerializationTest {
|
||||
|
||||
@Test
|
||||
fun testNameSerialization() {
|
||||
val name = "aaa.bbb.ccc".toName()
|
||||
val name = Name.parse("aaa.bbb.ccc")
|
||||
val json = Json.encodeToJsonElement(Name.serializer(), name)
|
||||
println(json)
|
||||
val reconstructed = Json.decodeFromJsonElement(Name.serializer(), json)
|
||||
|
@ -8,22 +8,22 @@ import kotlin.test.assertTrue
|
||||
class NameTest {
|
||||
@Test
|
||||
fun simpleName() {
|
||||
val name = "token1.token2.token3".toName()
|
||||
val name = Name.parse("token1.token2.token3")
|
||||
assertEquals("token2", name[1].toString())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun equalityTest() {
|
||||
val name1 = "token1.token2[2].token3".toName()
|
||||
val name2 = "token1".toName() + "token2[2].token3"
|
||||
val name1 = Name.parse("token1.token2[2].token3")
|
||||
val name2 = "token1".asName() + "token2[2].token3"
|
||||
assertEquals(name1, name2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun comparisonTest(){
|
||||
val name1 = "token1.token2.token3".toName()
|
||||
val name2 = "token1.token2".toName()
|
||||
val name3 = "token3".toName()
|
||||
val name1 = Name.parse("token1.token2.token3")
|
||||
val name2 = Name.parse("token1.token2")
|
||||
val name3 = Name.parse("token3")
|
||||
assertTrue { name1.startsWith(name2) }
|
||||
assertTrue { name1.endsWith(name3) }
|
||||
assertFalse { name1.startsWith(name3) }
|
||||
@ -31,11 +31,11 @@ class NameTest {
|
||||
|
||||
@Test
|
||||
fun escapeTest(){
|
||||
val escapedName = "token\\.one.token2".toName()
|
||||
val escapedName = Name.parse("token\\.one.token2")
|
||||
val unescapedName = "token\\.one.token2".asName()
|
||||
|
||||
assertEquals(2, escapedName.length)
|
||||
assertEquals(1, unescapedName.length)
|
||||
assertEquals(escapedName, escapedName.toString().toName())
|
||||
assertEquals(escapedName, Name.parse(escapedName.toString()))
|
||||
}
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
package space.kscience.dataforge.meta
|
||||
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.dataforge.names.NameToken
|
||||
import space.kscience.dataforge.values.Value
|
||||
import space.kscience.dataforge.values.asValue
|
||||
@ -8,7 +7,6 @@ import space.kscience.dataforge.values.isList
|
||||
|
||||
|
||||
//TODO add Meta wrapper for dynamic
|
||||
@DFExperimental
|
||||
public fun Value.toDynamic(): dynamic {
|
||||
return if (isList()) {
|
||||
list.map { it.toDynamic() }.toTypedArray().asDynamic()
|
||||
@ -20,7 +18,6 @@ public fun Value.toDynamic(): dynamic {
|
||||
/**
|
||||
* Represent or copy this [Meta] to dynamic object to be passed to JS libraries
|
||||
*/
|
||||
@DFExperimental
|
||||
public fun Meta.toDynamic(): dynamic {
|
||||
if (this is DynamicMeta) return this.obj
|
||||
if(items.isEmpty()) return value?.toDynamic()
|
||||
@ -36,7 +33,6 @@ public fun Meta.toDynamic(): dynamic {
|
||||
return res
|
||||
}
|
||||
|
||||
@DFExperimental
|
||||
public class DynamicMeta(internal val obj: dynamic) : TypedMeta<DynamicMeta> {
|
||||
private fun keys(): Array<String> = js("Object").keys(obj) as Array<String>
|
||||
|
||||
|
@ -5,7 +5,6 @@ import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.meta.MutableMeta
|
||||
import space.kscience.dataforge.misc.Type
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.toName
|
||||
import space.kscience.dataforge.provider.Provider
|
||||
|
||||
|
||||
@ -28,7 +27,7 @@ public interface Workspace : ContextAware, Provider {
|
||||
|
||||
override fun content(target: String): Map<Name, Any> {
|
||||
return when (target) {
|
||||
"target", Meta.TYPE -> targets.mapKeys { it.key.toName() }
|
||||
"target", Meta.TYPE -> targets.mapKeys { Name.parse(it.key)}
|
||||
Task.TYPE -> tasks
|
||||
//Data.TYPE -> data.flow().toMap()
|
||||
else -> emptyMap()
|
||||
@ -50,10 +49,10 @@ public interface Workspace : ContextAware, Provider {
|
||||
}
|
||||
|
||||
public suspend fun Workspace.produce(task: String, target: String): TaskResult<*> =
|
||||
produce(task.toName(), targets[target] ?: error("Target with key $target not found in $this"))
|
||||
produce(Name.parse(task), targets[target] ?: error("Target with key $target not found in $this"))
|
||||
|
||||
public suspend fun Workspace.produce(task: String, meta: Meta): TaskResult<*> =
|
||||
produce(task.toName(), meta)
|
||||
produce(Name.parse(task), meta)
|
||||
|
||||
public suspend fun Workspace.produce(task: String, block: MutableMeta.() -> Unit = {}): TaskResult<*> =
|
||||
produce(task, Meta(block))
|
||||
|
@ -14,7 +14,6 @@ import space.kscience.dataforge.meta.descriptors.MetaDescriptorBuilder
|
||||
import space.kscience.dataforge.misc.DFBuilder
|
||||
import space.kscience.dataforge.misc.DFExperimental
|
||||
import space.kscience.dataforge.names.Name
|
||||
import space.kscience.dataforge.names.toName
|
||||
import kotlin.properties.PropertyDelegateProvider
|
||||
import kotlin.properties.ReadOnlyProperty
|
||||
|
||||
@ -29,13 +28,13 @@ public inline fun <reified T : Any> TaskContainer.registerTask(
|
||||
name: String,
|
||||
noinline descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {},
|
||||
noinline builder: suspend TaskResultBuilder<T>.() -> Unit,
|
||||
): Unit = registerTask(name.toName(), Task(MetaDescriptor(descriptorBuilder), builder))
|
||||
): Unit = registerTask(Name.parse(name), Task(MetaDescriptor(descriptorBuilder), builder))
|
||||
|
||||
public inline fun <reified T : Any> TaskContainer.task(
|
||||
noinline descriptorBuilder: MetaDescriptorBuilder.() -> Unit = {},
|
||||
noinline builder: suspend TaskResultBuilder<T>.() -> Unit,
|
||||
): PropertyDelegateProvider<Any?, ReadOnlyProperty<Any?, TaskReference<T>>> = PropertyDelegateProvider { _, property ->
|
||||
val taskName = property.name.toName()
|
||||
val taskName = Name.parse(property.name)
|
||||
val task = Task(MetaDescriptor(descriptorBuilder), builder)
|
||||
registerTask(taskName, task)
|
||||
ReadOnlyProperty { _, _ -> TaskReference(taskName, task) }
|
||||
|
@ -7,7 +7,6 @@ import space.kscience.dataforge.context.PluginFactory
|
||||
import space.kscience.dataforge.context.PluginTag
|
||||
import space.kscience.dataforge.data.*
|
||||
import space.kscience.dataforge.meta.Meta
|
||||
import space.kscience.dataforge.names.toName
|
||||
import kotlin.reflect.KClass
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
@ -25,7 +24,7 @@ class DataPropagationTestPlugin : WorkspacePlugin() {
|
||||
|
||||
|
||||
val singleData by task<Int> {
|
||||
workspace.data.select<Int>().getData("myData[12]".toName())?.let {
|
||||
workspace.data.select<Int>().getData("myData[12]")?.let {
|
||||
emit("result", it)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user