From cd4736ab5ec9fc9f3174281ecc7b7ea638b3c3c7 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Mon, 28 Oct 2019 12:35:19 +0300 Subject: [PATCH] Transformation of Meta to Map and back --- .../dataforge-io-yaml/build.gradle.kts | 9 ---- .../kotlin/hep/dataforge/meta/Builder.kt | 7 --- .../kotlin/hep/dataforge/meta/Laminate.kt | 2 - .../kotlin/hep/dataforge/meta/Meta.kt | 52 +------------------ .../kotlin/hep/dataforge/meta/annotations.kt | 11 ++++ .../kotlin/hep/dataforge/meta/mapMeta.kt | 36 +++++++++++++ .../hep/dataforge/meta/metaDelegates.kt | 19 ++++--- .../kotlin/hep/dataforge/meta/metaMatcher.kt | 51 ++++++++++++++++++ .../kotlin/hep/dataforge/meta/MetaTest.kt | 19 +++++++ settings.gradle.kts | 1 - 10 files changed, 129 insertions(+), 78 deletions(-) delete mode 100644 dataforge-io/dataforge-io-yaml/build.gradle.kts delete mode 100644 dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Builder.kt create mode 100644 dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/annotations.kt create mode 100644 dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/mapMeta.kt create mode 100644 dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt diff --git a/dataforge-io/dataforge-io-yaml/build.gradle.kts b/dataforge-io/dataforge-io-yaml/build.gradle.kts deleted file mode 100644 index 1a4af603..00000000 --- a/dataforge-io/dataforge-io-yaml/build.gradle.kts +++ /dev/null @@ -1,9 +0,0 @@ -plugins { - id("scientifik.jvm") -} - -description = "YAML meta IO" - -dependencies{ - api(project(":dataforge-io")) -} diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Builder.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Builder.kt deleted file mode 100644 index c9878c5f..00000000 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Builder.kt +++ /dev/null @@ -1,7 +0,0 @@ -package hep.dataforge.meta - -/** - * General marker for dataforge builders - */ -@DslMarker -annotation class DFBuilder \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Laminate.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Laminate.kt index b76fd46f..294140ae 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Laminate.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Laminate.kt @@ -4,8 +4,6 @@ import hep.dataforge.names.NameToken /** * A meta laminate consisting of multiple immutable meta layers. For mutable front layer, use [Styled]. - * - * */ class Laminate(layers: List) : MetaBase() { diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt index 6b7f85e9..e5aa0c45 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/Meta.kt @@ -80,27 +80,6 @@ operator fun Meta?.get(name: Name): MetaItem<*>? { operator fun Meta?.get(token: NameToken): MetaItem<*>? = this?.items?.get(token) operator fun Meta?.get(key: String): MetaItem<*>? = get(key.toName()) -/** - * Get all items matching given name. - */ -fun Meta.getAll(name: Name): Map> { - val root = when (name.length) { - 0 -> error("Can't use empty name for that") - 1 -> this - else -> (this[name.cutLast()] as? NodeItem<*>)?.node - } - - val (body, index) = name.last()!! - val regex = index.toRegex() - - return root?.items - ?.filter { it.key.body == body && (index.isEmpty() || regex.matches(it.key.index)) } - ?.mapKeys { it.key.index } - ?: emptyMap() -} - -fun Meta.getAll(name: String): Map> = getAll(name.toName()) - /** * Get a sequence of [Name]-[Value] pairs */ @@ -138,27 +117,6 @@ interface MetaNode> : Meta { override val items: Map> } -/** - * Get all items matching given name. - */ -fun > M.getAll(name: Name): Map> { - val root: MetaNode? = when (name.length) { - 0 -> error("Can't use empty name for that") - 1 -> this - else -> (this[name.cutLast()] as? NodeItem)?.node - } - - val (body, index) = name.last()!! - val regex = index.toRegex() - - return root?.items - ?.filter { it.key.body == body && (index.isEmpty() || regex.matches(it.key.index)) } - ?.mapKeys { it.key.index } - ?: emptyMap() -} - -fun > M.getAll(name: String): Map> = getAll(name.toName()) - operator fun > MetaNode?.get(name: Name): MetaItem? { if (this == null) return null return name.first()?.let { token -> @@ -229,7 +187,6 @@ object EmptyMeta : MetaBase() { /** * Unsafe methods to access values and nodes directly from [MetaItem] */ - val MetaItem<*>?.value: Value? get() = (this as? ValueItem)?.value ?: (this?.node?.get(VALUE_KEY) as? ValueItem)?.value @@ -258,11 +215,4 @@ val MetaItem?.node: M? is NodeItem -> node } -/** - * Generic meta-holder object - */ -interface Metoid { - val meta: Meta -} - -fun Meta.isEmpty() = this === EmptyMeta || this.items.isEmpty() +fun Meta.isEmpty() = this === EmptyMeta || this.items.isEmpty() \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/annotations.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/annotations.kt new file mode 100644 index 00000000..865ef800 --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/annotations.kt @@ -0,0 +1,11 @@ +package hep.dataforge.meta + +/** + * General marker for dataforge builders + */ +@DslMarker +annotation class DFBuilder + +@Experimental(level = Experimental.Level.WARNING) +@Retention(AnnotationRetention.BINARY) +annotation class DFExperimental \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/mapMeta.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/mapMeta.kt new file mode 100644 index 00000000..32cb8abd --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/mapMeta.kt @@ -0,0 +1,36 @@ +package hep.dataforge.meta + +import hep.dataforge.values.Value + +///** +// * Find all elements with given body +// */ +//private fun Meta.byBody(body: String): Map> = +// items.filter { it.key.body == body }.mapKeys { it.key.index } +// +//private fun Meta.distinctNames() = items.keys.map { it.body }.distinct() + +/** + * Convert meta to map of maps + */ +fun Meta.toMap(): Map { + return items.entries.associate { (token, item) -> + token.toString() to when (item) { + is MetaItem.NodeItem -> item.node.toMap() + is MetaItem.ValueItem -> item.value.value + } + } +} + +/** + * Convert map of maps to meta + */ +fun Map.toMeta(): Meta = buildMeta { + entries.forEach { (key, value) -> + @Suppress("UNCHECKED_CAST") + when (value) { + is Map<*, *> -> setNode(key, (value as Map).toMeta()) + else -> setValue(key, Value.of(value)) + } + } +} \ No newline at end of file diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaDelegates.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaDelegates.kt index 6bed5413..65e49da2 100644 --- a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaDelegates.kt +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaDelegates.kt @@ -28,15 +28,21 @@ class StringDelegate(val meta: Meta, private val key: String? = null, private va } } -class BooleanDelegate(val meta: Meta, private val key: String? = null, private val default: Boolean? = null) : - ReadOnlyProperty { - override fun getValue(thisRef: Metoid, property: KProperty<*>): Boolean? { +class BooleanDelegate( + val meta: Meta, + private val key: String? = null, + private val default: Boolean? = null +) : ReadOnlyProperty { + override fun getValue(thisRef: Any?, property: KProperty<*>): Boolean? { return meta[key ?: property.name]?.boolean ?: default } } -class NumberDelegate(val meta: Meta, private val key: String? = null, private val default: Number? = null) : - ReadOnlyProperty { +class NumberDelegate( + val meta: Meta, + private val key: String? = null, + private val default: Number? = null +) : ReadOnlyProperty { override fun getValue(thisRef: Any?, property: KProperty<*>): Number? { return meta[key ?: property.name]?.number ?: default } @@ -168,9 +174,6 @@ fun Meta.number(key: String? = null, default: () -> Number) = inline fun > Meta.enum(default: E, key: String? = null) = SafeEnumDelegate(this, key, default) { enumValueOf(it) } - -fun Metoid.node(key: String? = null, converter: (Meta) -> T) = ChildDelegate(meta, key, converter) - /* Read-write delegates */ class MutableValueDelegate>( diff --git a/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt new file mode 100644 index 00000000..8e2ea991 --- /dev/null +++ b/dataforge-meta/src/commonMain/kotlin/hep/dataforge/meta/metaMatcher.kt @@ -0,0 +1,51 @@ +package hep.dataforge.meta + +import hep.dataforge.names.Name +import hep.dataforge.names.toName + +/** + * Get all items matching given name. + */ +@DFExperimental +fun Meta.getAll(name: Name): Map> { + val root = when (name.length) { + 0 -> error("Can't use empty name for that") + 1 -> this + else -> (this[name.cutLast()] as? MetaItem.NodeItem<*>)?.node + } + + val (body, index) = name.last()!! + val regex = index.toRegex() + + return root?.items + ?.filter { it.key.body == body && (index.isEmpty() || regex.matches(it.key.index)) } + ?.mapKeys { it.key.index } + ?: emptyMap() +} + +@DFExperimental +fun Meta.getAll(name: String): Map> = getAll(name.toName()) + + +/** + * Get all items matching given name. + */ +@DFExperimental +fun > M.getAll(name: Name): Map> { + val root: MetaNode? = when (name.length) { + 0 -> error("Can't use empty name for that") + 1 -> this + else -> (this[name.cutLast()] as? MetaItem.NodeItem)?.node + } + + val (body, index) = name.last()!! + val regex = index.toRegex() + + return root?.items + ?.filter { it.key.body == body && (index.isEmpty() || regex.matches(it.key.index)) } + ?.mapKeys { it.key.index } + ?: emptyMap() +} + +@DFExperimental +fun > M.getAll(name: String): Map> = getAll(name.toName()) \ No newline at end of file diff --git a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaTest.kt b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaTest.kt index 7f83b0b2..7528f8d2 100644 --- a/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaTest.kt +++ b/dataforge-meta/src/commonTest/kotlin/hep/dataforge/meta/MetaTest.kt @@ -30,4 +30,23 @@ class MetaTest { }.seal() assertEquals(meta1, meta2) } + + @Test + fun metaToMap(){ + val meta = buildMeta { + "a" to 22 + "b" to { + "c" to "ddd" + } + "list" to (0..4).map { + buildMeta { + "value" to it + } + } + } + val map = meta.toMap() + val reconstructed = map.toMeta() + + assertEquals(meta,reconstructed) + } } \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle.kts index b486c03f..abf004a2 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -24,7 +24,6 @@ enableFeaturePreview("GRADLE_METADATA") include( ":dataforge-meta", ":dataforge-io", - ":dataforge-io:dataforge-io-yaml", ":dataforge-context", ":dataforge-data", ":dataforge-output",