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.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<DynamicMeta>? {
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<Any?>).all { isPrimitive(it) } -> MetaItem.ValueItem(Value.of(obj as Array<Any?>))
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<String, Pair<NameToken, MetaItem<DynamicMeta>>> { key ->
val value = obj[key] ?: return@flatMap emptyList()
if (isArray(value)) {
return@flatMap (value as Array<dynamic>)
.mapIndexedNotNull() { index, it ->
val array = value as Array<Any?>
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)

View File

@ -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<String>
assertTrue { keys.contains("ob") }
assertEquals(18, dynamic.ob.childNode)
assertEquals<Meta>(meta, DynamicMeta(dynamic))
}
}