From 04e9601def4f639d62063adbbe8250e8ad532bbb Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Tue, 29 Oct 2019 18:20:05 +0300 Subject: [PATCH] Fixed array representation in DynamicMeta --- .../kotlin/hep/dataforge/meta/DynamicMeta.kt | 41 ++++++++++++++----- .../hep/dataforge/meta/DynamicMetaTest.kt | 29 +++++++++++++ 2 files changed, 59 insertions(+), 11 deletions(-) diff --git a/dataforge-meta/src/jsMain/kotlin/hep/dataforge/meta/DynamicMeta.kt b/dataforge-meta/src/jsMain/kotlin/hep/dataforge/meta/DynamicMeta.kt index 694e2441..ff23a571 100644 --- a/dataforge-meta/src/jsMain/kotlin/hep/dataforge/meta/DynamicMeta.kt +++ b/dataforge-meta/src/jsMain/kotlin/hep/dataforge/meta/DynamicMeta.kt @@ -3,18 +3,27 @@ package hep.dataforge.meta import hep.dataforge.names.NameToken import hep.dataforge.values.Null import hep.dataforge.values.Value +import hep.dataforge.values.isList //TODO add Meta wrapper for dynamic +fun Value.toDynamic(): dynamic { + return if (isList()) { + list.map { it.toDynamic() }.toTypedArray().asDynamic() + } else { + value.asDynamic() + } +} + /** * Represent or copy this [Meta] to dynamic object to be passed to JS libraries */ fun Meta.toDynamic(): dynamic { - if(this is DynamicMeta) return this.obj + if (this is DynamicMeta) return this.obj fun MetaItem<*>.toDynamic(): dynamic = when (this) { - is MetaItem.ValueItem -> this.value.value.asDynamic() + is MetaItem.ValueItem -> this.value.toDynamic() is MetaItem.NodeItem -> this.node.toDynamic() } @@ -35,15 +44,21 @@ class DynamicMeta(val obj: dynamic) : MetaBase() { private fun isArray(@Suppress("UNUSED_PARAMETER") obj: dynamic): Boolean = js("Array.isArray(obj)") as Boolean + private fun isPrimitive(obj: dynamic): Boolean = + (jsTypeOf(obj) != "object") + @Suppress("UNCHECKED_CAST") private fun asItem(obj: dynamic): MetaItem? { - if (obj == null) return MetaItem.ValueItem(Null) - return when (jsTypeOf(obj as? Any)) { - "boolean" -> MetaItem.ValueItem(Value.of(obj as Boolean)) - "number" -> MetaItem.ValueItem(Value.of(obj as Number)) - "string" -> MetaItem.ValueItem(Value.of(obj as String)) - "object" -> MetaItem.NodeItem(DynamicMeta(obj)) - else -> null + return when { + obj == null -> MetaItem.ValueItem(Null) + isArray(obj) && (obj as Array).all { isPrimitive(it) } -> MetaItem.ValueItem(Value.of(obj as Array)) + else -> when (jsTypeOf(obj)) { + "boolean" -> MetaItem.ValueItem(Value.of(obj as Boolean)) + "number" -> MetaItem.ValueItem(Value.of(obj as Number)) + "string" -> MetaItem.ValueItem(Value.of(obj as String)) + "object" -> MetaItem.NodeItem(DynamicMeta(obj)) + else -> null + } } } @@ -51,11 +66,15 @@ class DynamicMeta(val obj: dynamic) : MetaBase() { get() = keys().flatMap>> { key -> val value = obj[key] ?: return@flatMap emptyList() if (isArray(value)) { - return@flatMap (value as Array) - .mapIndexedNotNull() { index, it -> + val array = value as Array + return@flatMap if (array.all { isPrimitive(it) }) { + listOf(NameToken(key) to MetaItem.ValueItem(Value.of(array))) + } else { + array.mapIndexedNotNull { index, it -> val item = asItem(it) ?: return@mapIndexedNotNull null NameToken(key, index.toString()) to item } + } } else { val item = asItem(value) ?: return@flatMap emptyList() listOf(NameToken(key) to item) diff --git a/dataforge-meta/src/jsTest/kotlin/hep/dataforge/meta/DynamicMetaTest.kt b/dataforge-meta/src/jsTest/kotlin/hep/dataforge/meta/DynamicMetaTest.kt index ce46a740..772adf06 100644 --- a/dataforge-meta/src/jsTest/kotlin/hep/dataforge/meta/DynamicMetaTest.kt +++ b/dataforge-meta/src/jsTest/kotlin/hep/dataforge/meta/DynamicMetaTest.kt @@ -2,6 +2,7 @@ package hep.dataforge.meta import kotlin.test.Test import kotlin.test.assertEquals +import kotlin.test.assertTrue class DynamicMetaTest { @@ -19,6 +20,34 @@ class DynamicMetaTest { val meta = DynamicMeta(d) assertEquals(true, meta["ob.booleanNode"].boolean) assertEquals(2, meta["array[1]"].int) + assertEquals(4, meta.items.size) + } + + @Test + fun testMetaToDynamic(){ + val meta = buildMeta { + "a" to 22 + "array" to arrayOf(1, 2, 3) + "b" to "myString" + "ob" to { + "childNode" to 18 + "booleanNode" to true + } + } + + val dynamic = meta.toDynamic() + + assertEquals(2,dynamic.array[1]) + + assertEquals(22, dynamic.a) + + val keys = js("Object.keys(dynamic)") as Array + + assertTrue { keys.contains("ob") } + + assertEquals(18, dynamic.ob.childNode) + + assertEquals(meta, DynamicMeta(dynamic)) } } \ No newline at end of file