Fixed json conversion issue for new Meta structure.

This commit is contained in:
Alexander Nozik 2018-11-03 22:15:36 +03:00
parent 3033cc6304
commit dd05897759
4 changed files with 42 additions and 15 deletions

View File

@ -4,6 +4,7 @@ import com.github.cliftonlabs.json_simple.JsonArray
import com.github.cliftonlabs.json_simple.JsonObject
import com.github.cliftonlabs.json_simple.Jsoner
import hep.dataforge.meta.*
import hep.dataforge.names.toName
import kotlinx.io.core.*
import java.io.ByteArrayInputStream
import java.io.InputStreamReader
@ -97,13 +98,19 @@ private fun MetaBuilder.appendValue(key: String, value: Any?) {
when (value) {
is JsonObject -> this[key] = value.toMeta()
is JsonArray -> {
value.forEach {
if (it is JsonArray) {
this[key] = it.toListValue()
if (value.none { it is JsonObject }) {
//If all values are primitives or arrays
this[key] = value.toListValue()
} else {
appendValue(key, it)
val list = value.map<Any, Meta> {
when(it){
is JsonObject -> it.toMeta()
is JsonArray -> it.toListValue().toMeta()
else -> Value.of(it).toMeta()
}
}
setIndexed(key.toName(),list)
}
}
is Number -> this[key] = NumberValue(value)
is Boolean -> this[key] = value

View File

@ -35,6 +35,8 @@ interface Meta {
}
}
/* Get operations*/
/**
* Fast [String]-based accessor for item map
*/
@ -51,10 +53,22 @@ operator fun Meta.get(name: Name): MetaItem<out Meta>? {
}
operator fun Meta.get(token: NameToken): MetaItem<out Meta>? = items[token]
//TODO create Java helper for meta operations
operator fun Meta.get(key: String): MetaItem<out Meta>? = get(key.toName())
/**
* Get all items matching given name.
*/
fun Meta.getByName(name: Name): Map<String, MetaItem<out Meta>> {
if (name.length == 0) error("Can't use empty name for that")
val (body, query) = name.last()!!
val regex = query.toRegex()
return (this[name.cutLast()] as? NodeItem<*>)?.node?.items
?.filter { it.key.body == body && (query.isEmpty()|| regex.matches(it.key.query)) }
?.mapKeys { it.key.query }
?: emptyMap()
}
/**
* A meta node that ensures that all of its descendants has at least the same type
*/
@ -91,6 +105,7 @@ abstract class MetaNode<M : MetaNode<M>> : Meta {
* If the argument is possibly mutable node, it is copied on creation
*/
class SealedMeta internal constructor(override val items: Map<NameToken, MetaItem<SealedMeta>>) : MetaNode<SealedMeta>()
/**
* Generate sealed node from [this]. If it is already sealed return it as is
*/
@ -133,3 +148,5 @@ val <M : Meta> MetaItem<M>.node: M
interface Metoid {
val meta: Meta
}
fun Value.toMeta() = buildMeta { Meta.VALUE_KEY to this }

View File

@ -105,7 +105,6 @@ operator fun <M : MutableMeta<M>> M.set(name: String, value: Value) = set(name.t
operator fun <M : MutableMetaNode<M>> M.set(name: String, meta: Meta) = set(name.toName(), meta)
operator fun <M : MutableMeta<M>> M.set(token: NameToken, item: MetaItem<M>?) = set(token.toName(), item)
/**
* Universal set method
*/
@ -134,16 +133,20 @@ fun <M : MutableMetaNode<M>> M.update(meta: Meta) {
}
}
// Same name siblings generation
/* Same name siblings generation */
fun <M : MutableMetaNode<M>> M.setIndexed(name: Name, metas: Iterable<Meta>, queryFactory: (Int) -> String = { it.toString() }) {
fun <M : MutableMeta<M>> M.setIndexed(name: Name, items: Iterable<MetaItem<M>>, queryFactory: (Int) -> String = { it.toString() }) {
val tokens = name.tokens.toMutableList()
val last = tokens.last()
metas.forEachIndexed { index, meta ->
items.forEachIndexed { index, meta ->
val indexedToken = NameToken(last.body, last.query + queryFactory(index))
tokens[tokens.lastIndex] = indexedToken
set(Name(tokens), meta)
}
}
fun <M : MutableMetaNode<M>> M.setIndexed(name: Name, metas: Iterable<Meta>, queryFactory: (Int) -> String = { it.toString() }) {
setIndexed(name, metas.map { wrap(name, it) }, queryFactory)
}
operator fun <M : MutableMetaNode<M>> M.set(name: Name, metas: Iterable<Meta>) = setIndexed(name, metas)

View File

@ -22,12 +22,12 @@ class Name internal constructor(val tokens: List<NameToken>) {
fun last(): NameToken? = tokens.lastOrNull()
/**
* The reminder of the name after first element is cut
* The reminder of the name after first element is cut. For empty name return itself.
*/
fun cutFirst(): Name = Name(tokens.drop(1))
/**
* The reminder of the name after last element is cut
* The reminder of the name after last element is cut. For empty name return itself.
*/
fun cutLast(): Name = Name(tokens.dropLast(1))