Fixed array representation in DynamicMeta

This commit is contained in:
Alexander Nozik 2019-10-29 18:20:05 +03:00
parent 728da96eff
commit 04e9601def
2 changed files with 59 additions and 11 deletions

View File

@ -3,18 +3,27 @@ package hep.dataforge.meta
import hep.dataforge.names.NameToken import hep.dataforge.names.NameToken
import hep.dataforge.values.Null import hep.dataforge.values.Null
import hep.dataforge.values.Value import hep.dataforge.values.Value
import hep.dataforge.values.isList
//TODO add Meta wrapper for dynamic //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 * Represent or copy this [Meta] to dynamic object to be passed to JS libraries
*/ */
fun Meta.toDynamic(): dynamic { fun Meta.toDynamic(): dynamic {
if(this is DynamicMeta) return this.obj if (this is DynamicMeta) return this.obj
fun MetaItem<*>.toDynamic(): dynamic = when (this) { 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() 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 = private fun isArray(@Suppress("UNUSED_PARAMETER") obj: dynamic): Boolean =
js("Array.isArray(obj)") as Boolean js("Array.isArray(obj)") as Boolean
private fun isPrimitive(obj: dynamic): Boolean =
(jsTypeOf(obj) != "object")
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
private fun asItem(obj: dynamic): MetaItem<DynamicMeta>? { private fun asItem(obj: dynamic): MetaItem<DynamicMeta>? {
if (obj == null) return MetaItem.ValueItem(Null) return when {
return when (jsTypeOf(obj as? Any)) { obj == null -> MetaItem.ValueItem(Null)
"boolean" -> MetaItem.ValueItem(Value.of(obj as Boolean)) isArray(obj) && (obj as Array<Any?>).all { isPrimitive(it) } -> MetaItem.ValueItem(Value.of(obj as Array<Any?>))
"number" -> MetaItem.ValueItem(Value.of(obj as Number)) else -> when (jsTypeOf(obj)) {
"string" -> MetaItem.ValueItem(Value.of(obj as String)) "boolean" -> MetaItem.ValueItem(Value.of(obj as Boolean))
"object" -> MetaItem.NodeItem(DynamicMeta(obj)) "number" -> MetaItem.ValueItem(Value.of(obj as Number))
else -> null "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<String, Pair<NameToken, MetaItem<DynamicMeta>>> { key -> get() = keys().flatMap<String, Pair<NameToken, MetaItem<DynamicMeta>>> { key ->
val value = obj[key] ?: return@flatMap emptyList() val value = obj[key] ?: return@flatMap emptyList()
if (isArray(value)) { if (isArray(value)) {
return@flatMap (value as Array<dynamic>) val array = value as Array<Any?>
.mapIndexedNotNull() { index, it -> 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 val item = asItem(it) ?: return@mapIndexedNotNull null
NameToken(key, index.toString()) to item NameToken(key, index.toString()) to item
} }
}
} else { } else {
val item = asItem(value) ?: return@flatMap emptyList() val item = asItem(value) ?: return@flatMap emptyList()
listOf(NameToken(key) to item) listOf(NameToken(key) to item)

View File

@ -2,6 +2,7 @@ package hep.dataforge.meta
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertTrue
class DynamicMetaTest { class DynamicMetaTest {
@ -19,6 +20,34 @@ class DynamicMetaTest {
val meta = DynamicMeta(d) val meta = DynamicMeta(d)
assertEquals(true, meta["ob.booleanNode"].boolean) assertEquals(true, meta["ob.booleanNode"].boolean)
assertEquals(2, meta["array[1]"].int) 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<String>
assertTrue { keys.contains("ob") }
assertEquals(18, dynamic.ob.childNode)
assertEquals<Meta>(meta, DynamicMeta(dynamic))
} }
} }