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.JsonObject
import com.github.cliftonlabs.json_simple.Jsoner import com.github.cliftonlabs.json_simple.Jsoner
import hep.dataforge.meta.* import hep.dataforge.meta.*
import hep.dataforge.names.toName
import kotlinx.io.core.* import kotlinx.io.core.*
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.InputStreamReader import java.io.InputStreamReader
@ -97,12 +98,18 @@ private fun MetaBuilder.appendValue(key: String, value: Any?) {
when (value) { when (value) {
is JsonObject -> this[key] = value.toMeta() is JsonObject -> this[key] = value.toMeta()
is JsonArray -> { is JsonArray -> {
value.forEach { if (value.none { it is JsonObject }) {
if (it is JsonArray) { //If all values are primitives or arrays
this[key] = it.toListValue() this[key] = value.toListValue()
} else { } 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 Number -> this[key] = NumberValue(value)

View File

@ -35,6 +35,8 @@ interface Meta {
} }
} }
/* Get operations*/
/** /**
* Fast [String]-based accessor for item map * 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] 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()) 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 * 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 * 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>() 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 * Generate sealed node from [this]. If it is already sealed return it as is
*/ */
@ -132,4 +147,6 @@ val <M : Meta> MetaItem<M>.node: M
*/ */
interface Metoid { interface Metoid {
val meta: Meta val meta: Meta
} }
fun Value.toMeta() = buildMeta { Meta.VALUE_KEY to this }

View File

@ -54,7 +54,7 @@ abstract class MutableMetaNode<M : MutableMetaNode<M>> : MetaNode<M>(), MutableM
oldItem?.node?.removeListener(this) oldItem?.node?.removeListener(this)
} else { } else {
_items[key] = newItem _items[key] = newItem
if(newItem is MetaItem.NodeItem) { if (newItem is MetaItem.NodeItem) {
newItem.node.onChange(this) { name, oldChild, newChild -> newItem.node.onChange(this) { name, oldChild, newChild ->
itemChanged(key + name, oldChild, newChild) itemChanged(key + name, oldChild, newChild)
} }
@ -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 : 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) operator fun <M : MutableMeta<M>> M.set(token: NameToken, item: MetaItem<M>?) = set(token.toName(), item)
/** /**
* Universal set method * 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 tokens = name.tokens.toMutableList()
val last = tokens.last() val last = tokens.last()
metas.forEachIndexed { index, meta -> items.forEachIndexed { index, meta ->
val indexedToken = NameToken(last.body, last.query + queryFactory(index)) val indexedToken = NameToken(last.body, last.query + queryFactory(index))
tokens[tokens.lastIndex] = indexedToken tokens[tokens.lastIndex] = indexedToken
set(Name(tokens), meta) 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) 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() 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)) 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)) fun cutLast(): Name = Name(tokens.dropLast(1))