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.Meta
|
||||||
import hep.dataforge.meta.MetaItem
|
import hep.dataforge.meta.MetaItem
|
||||||
import hep.dataforge.names.NameToken
|
import hep.dataforge.names.NameToken
|
||||||
|
import hep.dataforge.names.toName
|
||||||
import hep.dataforge.values.*
|
import hep.dataforge.values.*
|
||||||
import kotlinx.io.core.Input
|
import kotlinx.io.core.Input
|
||||||
import kotlinx.io.core.Output
|
import kotlinx.io.core.Output
|
||||||
@ -22,10 +23,10 @@ object JsonMetaFormat : MetaFormat {
|
|||||||
val str = input.readText()
|
val str = input.readText()
|
||||||
val json = Json.plain.parseJson(str)
|
val json = Json.plain.parseJson(str)
|
||||||
|
|
||||||
if(json is JsonObject) {
|
if (json is JsonObject) {
|
||||||
return json.toMeta()
|
return json.toMeta()
|
||||||
} else {
|
} else {
|
||||||
TODO("non-object root")
|
TODO("Non-object root not supported")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -51,34 +52,47 @@ 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)
|
fun JsonObject.toMeta() = JsonMeta(this)
|
||||||
|
|
||||||
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 {
|
class JsonMeta(val json: JsonObject) : Meta {
|
||||||
override val items: Map<NameToken, MetaItem<out Meta>> by lazy {
|
|
||||||
json.mapKeys { NameToken(it.key) }.mapValues { entry ->
|
private fun JsonPrimitive.toValue(): Value {
|
||||||
entry.value.toMetaItem()
|
return when (this) {
|
||||||
|
JsonNull -> Null
|
||||||
|
else -> this.content.parseValue() // Optimize number and boolean parsing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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()!! }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class JsonMetaFormatFactory : MetaFormatFactory {
|
class JsonMetaFormatFactory : MetaFormatFactory {
|
||||||
|
@ -21,10 +21,8 @@
|
|||||||
*/
|
*/
|
||||||
package hep.dataforge.descriptors
|
package hep.dataforge.descriptors
|
||||||
|
|
||||||
import hep.dataforge.Named
|
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.*
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.toName
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Descriptor for meta node. Could contain additional information for viewing
|
* Descriptor for meta node. Could contain additional information for viewing
|
||||||
@ -32,7 +30,14 @@ import java.util.*
|
|||||||
*
|
*
|
||||||
* @author Alexander Nozik
|
* @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
|
* True if multiple children with this nodes name are allowed. Anonymous
|
||||||
@ -40,103 +45,47 @@ open class NodeDescriptor(val meta: Meta) : MetaRepr {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
val multiple: Boolean by meta.boolean(false)
|
var multiple: Boolean by boolean(false)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if the node is required
|
* True if the node is required
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
val required: Boolean by meta.boolean(false)
|
var required: Boolean by boolean(false)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The node description
|
* The node description
|
||||||
*
|
*
|
||||||
* @return
|
* @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
|
* A list of tags for this node. Tags used to customize node usage
|
||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
val tags: List<String> by customValue(def = emptyList()) { it.list.map { it.string } }
|
var tags: List<String> by value().map { value ->
|
||||||
|
value?.list?.map { it.string } ?: emptyList()
|
||||||
/**
|
}
|
||||||
* The name of this node
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
override val name: String by stringValue(def = meta.name)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of value descriptors
|
* The list of value descriptors
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
fun valueDescriptors(): Map<String, ValueDescriptor> {
|
val values: Map<String, ValueDescriptor>
|
||||||
val map = HashMap<String, ValueDescriptor>()
|
get() = config.getAll("value".toName()).entries.associate { (name, node) ->
|
||||||
if (meta.hasMeta("value")) {
|
name to ValueDescriptor.wrap(node.node ?: error("Value descriptor must be a node"))
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The map of children node descriptors
|
* The map of children node descriptors
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
fun childrenDescriptors(): Map<String, NodeDescriptor> {
|
val nodes: Map<String, NodeDescriptor>
|
||||||
val map = HashMap<String, NodeDescriptor>()
|
get() = config.getAll("node".toName()).entries.associate { (name, node) ->
|
||||||
if (meta.hasMeta("node")) {
|
name to NodeDescriptor.wrap(node.node ?: error("Node descriptor must be a node"))
|
||||||
for (node in meta.getMetaList("node")) {
|
|
||||||
val nd = NodeDescriptor(node)
|
|
||||||
map[nd.name] = nd
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return map
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if this node has default
|
* Check if this node has default
|
||||||
@ -173,15 +122,14 @@ open class NodeDescriptor(val meta: Meta) : MetaRepr {
|
|||||||
*/
|
*/
|
||||||
val key: String by stringValue(def = "")
|
val key: String by stringValue(def = "")
|
||||||
|
|
||||||
override fun toMeta(): Meta {
|
|
||||||
return meta
|
|
||||||
}
|
|
||||||
|
|
||||||
fun builder(): DescriptorBuilder = DescriptorBuilder(this.name, Configuration(this.meta))
|
fun builder(): DescriptorBuilder = DescriptorBuilder(this.name, Configuration(this.meta))
|
||||||
|
|
||||||
//override val descriptor: NodeDescriptor = empty("descriptor")
|
//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 {
|
fun empty(nodeName: String): NodeDescriptor {
|
||||||
return NodeDescriptor(Meta.buildEmpty(nodeName))
|
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