Json meta format fix
This commit is contained in:
parent
9fd89a5b60
commit
ce0e5d4f24
@ -3,6 +3,7 @@ package hep.dataforge.meta.io
|
||||
import hep.dataforge.meta.Meta
|
||||
import hep.dataforge.meta.MetaItem
|
||||
import hep.dataforge.names.NameToken
|
||||
import hep.dataforge.names.toName
|
||||
import hep.dataforge.values.*
|
||||
import kotlinx.io.core.Input
|
||||
import kotlinx.io.core.Output
|
||||
@ -22,10 +23,10 @@ object JsonMetaFormat : MetaFormat {
|
||||
val str = input.readText()
|
||||
val json = Json.plain.parseJson(str)
|
||||
|
||||
if(json is JsonObject) {
|
||||
if (json is JsonObject) {
|
||||
return json.toMeta()
|
||||
} else {
|
||||
TODO("non-object root")
|
||||
TODO("Non-object root not supported")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -51,33 +52,46 @@ fun Meta.toJson(): JsonObject {
|
||||
}
|
||||
|
||||
|
||||
fun JsonElement.toMetaItem() = when (this) {
|
||||
is JsonPrimitive -> MetaItem.ValueItem<JsonMeta>(this.toValue())
|
||||
is JsonObject -> MetaItem.NodeItem(this.toMeta())
|
||||
is JsonArray -> {
|
||||
if (this.all { it is JsonPrimitive }) {
|
||||
val value = ListValue(this.map { (it as JsonPrimitive).toValue() })
|
||||
MetaItem.ValueItem<JsonMeta>(value)
|
||||
} else {
|
||||
TODO("mixed nodes json")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun JsonObject.toMeta() = JsonMeta(this)
|
||||
|
||||
private fun JsonPrimitive.toValue(): Value {
|
||||
class JsonMeta(val json: JsonObject) : Meta {
|
||||
|
||||
private fun JsonPrimitive.toValue(): Value {
|
||||
return when (this) {
|
||||
JsonNull -> Null
|
||||
else -> this.content.parseValue() // Optimize number and boolean parsing
|
||||
}
|
||||
}
|
||||
|
||||
class JsonMeta(val json: JsonObject) : Meta {
|
||||
override val items: Map<NameToken, MetaItem<out Meta>> by lazy {
|
||||
json.mapKeys { NameToken(it.key) }.mapValues { entry ->
|
||||
entry.value.toMetaItem()
|
||||
}
|
||||
|
||||
private operator fun MutableMap<String, MetaItem<JsonMeta>>.set(key: String, value: JsonElement) = when (value) {
|
||||
is JsonPrimitive -> this[key] = MetaItem.ValueItem(value.toValue())
|
||||
is JsonObject -> this[key] = MetaItem.NodeItem(value.toMeta())
|
||||
is JsonArray -> {
|
||||
when {
|
||||
value.all { it is JsonPrimitive } -> {
|
||||
val listValue = ListValue(
|
||||
value.map {
|
||||
//We already checked that all values are primitives
|
||||
(it as JsonPrimitive).toValue()
|
||||
}
|
||||
)
|
||||
this[key] = MetaItem.ValueItem(listValue)
|
||||
}
|
||||
else -> value.forEachIndexed { index, jsonElement ->
|
||||
when (jsonElement) {
|
||||
is JsonObject -> this["$key[$index]"] = MetaItem.NodeItem(JsonMeta(jsonElement))
|
||||
is JsonPrimitive -> this["$key[$index]"] = MetaItem.ValueItem(jsonElement.toValue())
|
||||
is JsonArray -> TODO("Nested arrays not supported")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override val items: Map<NameToken, MetaItem<JsonMeta>> by lazy {
|
||||
val map = HashMap<String, MetaItem<JsonMeta>>()
|
||||
json.forEach { (key, value) -> map[key] = value }
|
||||
map.mapKeys { it.key.toName().first()!! }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,10 +21,8 @@
|
||||
*/
|
||||
package hep.dataforge.descriptors
|
||||
|
||||
import hep.dataforge.Named
|
||||
import hep.dataforge.meta.*
|
||||
import hep.dataforge.names.Name
|
||||
import java.util.*
|
||||
import hep.dataforge.names.toName
|
||||
|
||||
/**
|
||||
* Descriptor for meta node. Could contain additional information for viewing
|
||||
@ -32,7 +30,14 @@ import java.util.*
|
||||
*
|
||||
* @author Alexander Nozik
|
||||
*/
|
||||
open class NodeDescriptor(val meta: Meta) : MetaRepr {
|
||||
class NodeDescriptor(override val config: Config) : Specification {
|
||||
|
||||
/**
|
||||
* The name of this node
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
var name: String by string { error("Anonymous descriptors are not allowed") }
|
||||
|
||||
/**
|
||||
* True if multiple children with this nodes name are allowed. Anonymous
|
||||
@ -40,104 +45,48 @@ open class NodeDescriptor(val meta: Meta) : MetaRepr {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
val multiple: Boolean by meta.boolean(false)
|
||||
var multiple: Boolean by boolean(false)
|
||||
|
||||
/**
|
||||
* True if the node is required
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
val required: Boolean by meta.boolean(false)
|
||||
var required: Boolean by boolean(false)
|
||||
|
||||
/**
|
||||
* The node description
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
open val info: String by meta.string("")
|
||||
var info: String? by string()
|
||||
|
||||
/**
|
||||
* A list of tags for this node. Tags used to customize node usage
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
val tags: List<String> by customValue(def = emptyList()) { it.list.map { it.string } }
|
||||
|
||||
/**
|
||||
* The name of this node
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
override val name: String by stringValue(def = meta.name)
|
||||
var tags: List<String> by value().map { value ->
|
||||
value?.list?.map { it.string } ?: emptyList()
|
||||
}
|
||||
|
||||
/**
|
||||
* The list of value descriptors
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
fun valueDescriptors(): Map<String, ValueDescriptor> {
|
||||
val map = HashMap<String, ValueDescriptor>()
|
||||
if (meta.hasMeta("value")) {
|
||||
for (valueNode in meta.getMetaList("value")) {
|
||||
val vd = ValueDescriptor(valueNode)
|
||||
map[vd.name] = vd
|
||||
}
|
||||
}
|
||||
return map
|
||||
}
|
||||
|
||||
/**
|
||||
* The child node descriptor for given name. Name syntax is supported.
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
fun getNodeDescriptor(name: String): NodeDescriptor? {
|
||||
return getNodeDescriptor(Name.of(name))
|
||||
}
|
||||
|
||||
fun getNodeDescriptor(name: Name): NodeDescriptor? {
|
||||
return if (name.length == 1) {
|
||||
childrenDescriptors()[name.unescaped]
|
||||
} else {
|
||||
getNodeDescriptor(name.cutLast())?.getNodeDescriptor(name.last)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The value descriptor for given value name. Name syntax is supported.
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
fun getValueDescriptor(name: String): ValueDescriptor? {
|
||||
return getValueDescriptor(Name.of(name))
|
||||
}
|
||||
|
||||
fun getValueDescriptor(name: Name): ValueDescriptor? {
|
||||
return if (name.length == 1) {
|
||||
valueDescriptors()[name.unescaped]
|
||||
} else {
|
||||
getNodeDescriptor(name.cutLast())?.getValueDescriptor(name.last)
|
||||
}
|
||||
val values: Map<String, ValueDescriptor>
|
||||
get() = config.getAll("value".toName()).entries.associate { (name, node) ->
|
||||
name to ValueDescriptor.wrap(node.node ?: error("Value descriptor must be a node"))
|
||||
}
|
||||
|
||||
/**
|
||||
* The map of children node descriptors
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
fun childrenDescriptors(): Map<String, NodeDescriptor> {
|
||||
val map = HashMap<String, NodeDescriptor>()
|
||||
if (meta.hasMeta("node")) {
|
||||
for (node in meta.getMetaList("node")) {
|
||||
val nd = NodeDescriptor(node)
|
||||
map[nd.name] = nd
|
||||
}
|
||||
}
|
||||
return map
|
||||
val nodes: Map<String, NodeDescriptor>
|
||||
get() = config.getAll("node".toName()).entries.associate { (name, node) ->
|
||||
name to NodeDescriptor.wrap(node.node ?: error("Node descriptor must be a node"))
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check if this node has default
|
||||
*
|
||||
@ -173,15 +122,14 @@ open class NodeDescriptor(val meta: Meta) : MetaRepr {
|
||||
*/
|
||||
val key: String by stringValue(def = "")
|
||||
|
||||
override fun toMeta(): Meta {
|
||||
return meta
|
||||
}
|
||||
|
||||
fun builder(): DescriptorBuilder = DescriptorBuilder(this.name, Configuration(this.meta))
|
||||
|
||||
//override val descriptor: NodeDescriptor = empty("descriptor")
|
||||
|
||||
companion object {
|
||||
companion object : SpecificationCompanion<NodeDescriptor> {
|
||||
|
||||
override fun wrap(config: Config): NodeDescriptor = NodeDescriptor(config)
|
||||
|
||||
fun empty(nodeName: String): NodeDescriptor {
|
||||
return NodeDescriptor(Meta.buildEmpty(nodeName))
|
||||
|
@ -0,0 +1,21 @@
|
||||
package hep.dataforge.meta
|
||||
|
||||
|
||||
|
||||
|
||||
fun Meta.toDynamic(): dynamic {
|
||||
fun MetaItem<*>.toDynamic(): dynamic = when (this) {
|
||||
is MetaItem.ValueItem -> this.value.value.asDynamic()
|
||||
is MetaItem.NodeItem -> this.node.toDynamic()
|
||||
}
|
||||
|
||||
val res = js("{}")
|
||||
this.items.entries.groupBy { it.key.body }.forEach { (key, value) ->
|
||||
val list = value.map { it.value }
|
||||
res[key] = when (list.size) {
|
||||
1 -> list.first().toDynamic()
|
||||
else -> list.map { it.toDynamic() }
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
Loading…
Reference in New Issue
Block a user