Fix IO after refactoring
This commit is contained in:
parent
52a3c8bc6f
commit
8a8484172c
@ -105,11 +105,13 @@ class FrontMatterEnvelopeFormat(
|
|||||||
override fun readPartial(input: Input): PartialEnvelope =
|
override fun readPartial(input: Input): PartialEnvelope =
|
||||||
default.readPartial(input)
|
default.readPartial(input)
|
||||||
|
|
||||||
override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta): Unit =
|
override fun Output.writeEnvelope(
|
||||||
default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
|
envelope: Envelope,
|
||||||
|
metaFormatFactory: MetaFormatFactory,
|
||||||
|
formatMeta: Meta,
|
||||||
|
): Unit = default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
|
||||||
|
|
||||||
override fun readObject(input: Input): Envelope =
|
override fun readObject(input: Input): Envelope = default.readObject(input)
|
||||||
default.readObject(input)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -30,7 +30,7 @@ public interface IOFormat<T : Any> : MetaRepr {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun <T : Any> Input.readWith(format: IOFormat<T>): T = format.run { readObject(this@readWith) }
|
public fun <T : Any> Input.readWith(format: IOFormat<T>): T = format.readObject(this@readWith)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read given binary as object using given format
|
* Read given binary as object using given format
|
||||||
|
@ -12,7 +12,7 @@ import hep.dataforge.meta.toJson
|
|||||||
import hep.dataforge.meta.toMetaItem
|
import hep.dataforge.meta.toMetaItem
|
||||||
import kotlinx.io.Input
|
import kotlinx.io.Input
|
||||||
import kotlinx.io.Output
|
import kotlinx.io.Output
|
||||||
import kotlinx.io.readByteArray
|
import kotlinx.io.text.readUtf8String
|
||||||
import kotlinx.io.text.writeUtf8String
|
import kotlinx.io.text.writeUtf8String
|
||||||
import kotlinx.serialization.json.Json
|
import kotlinx.serialization.json.Json
|
||||||
import kotlinx.serialization.json.JsonObject
|
import kotlinx.serialization.json.JsonObject
|
||||||
@ -24,7 +24,7 @@ public class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat
|
|||||||
|
|
||||||
override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?) {
|
override fun writeMeta(output: Output, meta: Meta, descriptor: NodeDescriptor?) {
|
||||||
val jsonObject = meta.toJson(descriptor)
|
val jsonObject = meta.toJson(descriptor)
|
||||||
output.writeUtf8String(this.json.encodeToString(JsonObject.serializer(), jsonObject))
|
output.writeUtf8String(json.encodeToString(JsonObject.serializer(), jsonObject))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun toMeta(): Meta = Meta {
|
override fun toMeta(): Meta = Meta {
|
||||||
@ -32,7 +32,7 @@ public class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta {
|
override fun readMeta(input: Input, descriptor: NodeDescriptor?): Meta {
|
||||||
val str = input.readByteArray().decodeToString()
|
val str = input.readUtf8String()//readByteArray().decodeToString()
|
||||||
val jsonElement = json.parseToJsonElement(str)
|
val jsonElement = json.parseToJsonElement(str)
|
||||||
val item = jsonElement.toMetaItem(descriptor)
|
val item = jsonElement.toMetaItem(descriptor)
|
||||||
return item.node ?: Meta.EMPTY
|
return item.node ?: Meta.EMPTY
|
||||||
|
@ -18,7 +18,7 @@ import kotlinx.io.*
|
|||||||
*/
|
*/
|
||||||
public class TaggedEnvelopeFormat(
|
public class TaggedEnvelopeFormat(
|
||||||
public val io: IOPlugin,
|
public val io: IOPlugin,
|
||||||
public val version: VERSION = VERSION.DF02
|
public val version: VERSION = VERSION.DF02,
|
||||||
) : EnvelopeFormat {
|
) : EnvelopeFormat {
|
||||||
|
|
||||||
// private val metaFormat = io.metaFormat(metaFormatKey)
|
// private val metaFormat = io.metaFormat(metaFormatKey)
|
||||||
@ -67,11 +67,7 @@ public class TaggedEnvelopeFormat(
|
|||||||
val metaFormat = io.resolveMetaFormat(tag.metaFormatKey)
|
val metaFormat = io.resolveMetaFormat(tag.metaFormatKey)
|
||||||
?: error("Meta format with key ${tag.metaFormatKey} not found")
|
?: error("Meta format with key ${tag.metaFormatKey} not found")
|
||||||
|
|
||||||
val meta: Meta = input.limit(tag.metaSize.toInt()).run {
|
val meta: Meta = metaFormat.readObject(input.limit(tag.metaSize.toInt()))
|
||||||
metaFormat.run {
|
|
||||||
readObject(input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val data = input.readBinary(tag.dataSize.toInt())
|
val data = input.readBinary(tag.dataSize.toInt())
|
||||||
|
|
||||||
@ -84,11 +80,8 @@ public class TaggedEnvelopeFormat(
|
|||||||
val metaFormat = io.resolveMetaFormat(tag.metaFormatKey)
|
val metaFormat = io.resolveMetaFormat(tag.metaFormatKey)
|
||||||
?: error("Meta format with key ${tag.metaFormatKey} not found")
|
?: error("Meta format with key ${tag.metaFormatKey} not found")
|
||||||
|
|
||||||
val meta: Meta = input.limit(tag.metaSize.toInt()).run {
|
val meta: Meta = metaFormat.readObject(input.limit(tag.metaSize.toInt()))
|
||||||
metaFormat.run {
|
|
||||||
readObject(input)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return PartialEnvelope(meta, version.tagSize + tag.metaSize, tag.dataSize)
|
return PartialEnvelope(meta, version.tagSize + tag.metaSize, tag.dataSize)
|
||||||
}
|
}
|
||||||
@ -96,7 +89,7 @@ public class TaggedEnvelopeFormat(
|
|||||||
private data class Tag(
|
private data class Tag(
|
||||||
val metaFormatKey: Short,
|
val metaFormatKey: Short,
|
||||||
val metaSize: UInt,
|
val metaSize: UInt,
|
||||||
val dataSize: ULong
|
val dataSize: ULong,
|
||||||
)
|
)
|
||||||
|
|
||||||
public enum class VERSION(public val tagSize: UInt) {
|
public enum class VERSION(public val tagSize: UInt) {
|
||||||
@ -165,13 +158,13 @@ public class TaggedEnvelopeFormat(
|
|||||||
override fun readPartial(input: Input): PartialEnvelope =
|
override fun readPartial(input: Input): PartialEnvelope =
|
||||||
default.run { readPartial(input) }
|
default.run { readPartial(input) }
|
||||||
|
|
||||||
override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta): Unit =
|
override fun Output.writeEnvelope(
|
||||||
default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
|
envelope: Envelope,
|
||||||
|
metaFormatFactory: MetaFormatFactory,
|
||||||
override fun readObject(input: Input): Envelope =
|
formatMeta: Meta,
|
||||||
default.run { readObject(input) }
|
): Unit = default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
|
||||||
|
|
||||||
|
|
||||||
|
override fun readObject(input: Input): Envelope = default.readObject(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -20,7 +20,7 @@ import kotlin.collections.set
|
|||||||
*/
|
*/
|
||||||
public class TaglessEnvelopeFormat(
|
public class TaglessEnvelopeFormat(
|
||||||
public val io: IOPlugin,
|
public val io: IOPlugin,
|
||||||
public val meta: Meta = Meta.EMPTY
|
public val meta: Meta = Meta.EMPTY,
|
||||||
) : EnvelopeFormat {
|
) : EnvelopeFormat {
|
||||||
|
|
||||||
private val metaStart = meta[META_START_PROPERTY].string ?: DEFAULT_META_START
|
private val metaStart = meta[META_START_PROPERTY].string ?: DEFAULT_META_START
|
||||||
@ -85,13 +85,9 @@ public class TaglessEnvelopeFormat(
|
|||||||
val metaFormat = properties[META_TYPE_PROPERTY]?.let { io.resolveMetaFormat(it) } ?: JsonMetaFormat
|
val metaFormat = properties[META_TYPE_PROPERTY]?.let { io.resolveMetaFormat(it) } ?: JsonMetaFormat
|
||||||
val metaSize = properties[META_LENGTH_PROPERTY]?.toInt()
|
val metaSize = properties[META_LENGTH_PROPERTY]?.toInt()
|
||||||
meta = if (metaSize != null) {
|
meta = if (metaSize != null) {
|
||||||
input.limit(metaSize).run {
|
metaFormat.readObject(input.limit(metaSize))
|
||||||
metaFormat.run { readObject(input) }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
metaFormat.run {
|
metaFormat.readObject(input)
|
||||||
readObject(input)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -150,9 +146,7 @@ public class TaglessEnvelopeFormat(
|
|||||||
val metaSize = properties[META_LENGTH_PROPERTY]?.toInt()
|
val metaSize = properties[META_LENGTH_PROPERTY]?.toInt()
|
||||||
meta = if (metaSize != null) {
|
meta = if (metaSize != null) {
|
||||||
offset += metaSize.toUInt()
|
offset += metaSize.toUInt()
|
||||||
input.limit(metaSize).run {
|
metaFormat.readObject(input.limit(metaSize))
|
||||||
metaFormat.run { readObject(input) }
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
error("Can't partially read an envelope with undefined meta size")
|
error("Can't partially read an envelope with undefined meta size")
|
||||||
}
|
}
|
||||||
@ -203,11 +197,13 @@ public class TaglessEnvelopeFormat(
|
|||||||
override fun readPartial(input: Input): PartialEnvelope =
|
override fun readPartial(input: Input): PartialEnvelope =
|
||||||
default.run { readPartial(input) }
|
default.run { readPartial(input) }
|
||||||
|
|
||||||
override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta): Unit =
|
override fun Output.writeEnvelope(
|
||||||
default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
|
envelope: Envelope,
|
||||||
|
metaFormatFactory: MetaFormatFactory,
|
||||||
|
formatMeta: Meta,
|
||||||
|
): Unit = default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
|
||||||
|
|
||||||
override fun readObject(input: Input): Envelope =
|
override fun readObject(input: Input): Envelope = default.readObject(input)
|
||||||
default.run { readObject(input) }
|
|
||||||
|
|
||||||
override fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat? {
|
override fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat? {
|
||||||
return try {
|
return try {
|
||||||
|
@ -23,9 +23,9 @@ class EnvelopeFormatTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testTaggedFormat(){
|
fun testTaggedFormat(){
|
||||||
TaggedEnvelopeFormat.run {
|
TaggedEnvelopeFormat.run {
|
||||||
val byteArray = this.toByteArray(envelope)
|
val byteArray = writeToByteArray(envelope)
|
||||||
//println(byteArray.decodeToString())
|
//println(byteArray.decodeToString())
|
||||||
val res = readByteArray(byteArray)
|
val res = readFromByteArray(byteArray)
|
||||||
assertEquals(envelope.meta,res.meta)
|
assertEquals(envelope.meta,res.meta)
|
||||||
val double = res.data?.read {
|
val double = res.data?.read {
|
||||||
readDouble()
|
readDouble()
|
||||||
@ -37,9 +37,9 @@ class EnvelopeFormatTest {
|
|||||||
@Test
|
@Test
|
||||||
fun testTaglessFormat(){
|
fun testTaglessFormat(){
|
||||||
TaglessEnvelopeFormat.run {
|
TaglessEnvelopeFormat.run {
|
||||||
val byteArray = toByteArray(envelope)
|
val byteArray = writeToByteArray(envelope)
|
||||||
//println(byteArray.decodeToString())
|
//println(byteArray.decodeToString())
|
||||||
val res = readByteArray(byteArray)
|
val res = readFromByteArray(byteArray)
|
||||||
assertEquals(envelope.meta,res.meta)
|
assertEquals(envelope.meta,res.meta)
|
||||||
val double = res.data?.read {
|
val double = res.data?.read {
|
||||||
readDouble()
|
readDouble()
|
||||||
|
@ -1,13 +1,19 @@
|
|||||||
package hep.dataforge.io
|
package hep.dataforge.io
|
||||||
|
|
||||||
import hep.dataforge.meta.*
|
import hep.dataforge.meta.Meta
|
||||||
|
import hep.dataforge.meta.MetaItem
|
||||||
|
import hep.dataforge.meta.MetaSerializer
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.toName
|
import hep.dataforge.names.toName
|
||||||
import kotlinx.serialization.ExperimentalSerializationApi
|
import kotlinx.serialization.ExperimentalSerializationApi
|
||||||
import kotlinx.serialization.cbor.Cbor
|
import kotlinx.serialization.cbor.Cbor
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
import kotlin.test.assertEquals
|
import kotlin.test.assertEquals
|
||||||
|
|
||||||
|
val JSON_PRETTY: Json = Json { prettyPrint = true; useArrayPolymorphism = true }
|
||||||
|
val JSON_PLAIN: Json = Json { prettyPrint = false; useArrayPolymorphism = true }
|
||||||
|
|
||||||
class MetaSerializerTest {
|
class MetaSerializerTest {
|
||||||
val meta = Meta {
|
val meta = Meta {
|
||||||
"a" put 22
|
"a" put 22
|
||||||
|
@ -3,5 +3,5 @@ package hep.dataforge.io
|
|||||||
import kotlinx.io.ByteArrayInput
|
import kotlinx.io.ByteArrayInput
|
||||||
import kotlinx.io.use
|
import kotlinx.io.use
|
||||||
|
|
||||||
fun <T : Any> IOFormat<T>.toByteArray(obj: T): ByteArray = buildByteArray { writeObject(this, obj) }
|
fun <T : Any> IOFormat<T>.writeToByteArray(obj: T): ByteArray = buildByteArray { writeObject(this, obj) }
|
||||||
fun <T : Any> IOFormat<T>.readByteArray(array: ByteArray): T = ByteArrayInput(array).use { readObject(it) }
|
fun <T : Any> IOFormat<T>.readFromByteArray(array: ByteArray): T = ByteArrayInput(array).use { readObject(it) }
|
@ -66,7 +66,11 @@ public inline fun <reified T : Any> IOPlugin.resolveIOFormat(): IOFormat<T>? {
|
|||||||
* Read file containing meta using given [formatOverride] or file extension to infer meta type.
|
* Read file containing meta using given [formatOverride] or file extension to infer meta type.
|
||||||
* If [path] is a directory search for file starting with `meta` in it
|
* If [path] is a directory search for file starting with `meta` in it
|
||||||
*/
|
*/
|
||||||
public fun IOPlugin.readMetaFile(path: Path, formatOverride: MetaFormat? = null, descriptor: NodeDescriptor? = null): Meta {
|
public fun IOPlugin.readMetaFile(
|
||||||
|
path: Path,
|
||||||
|
formatOverride: MetaFormat? = null,
|
||||||
|
descriptor: NodeDescriptor? = null,
|
||||||
|
): Meta {
|
||||||
if (!Files.exists(path)) error("Meta file $path does not exist")
|
if (!Files.exists(path)) error("Meta file $path does not exist")
|
||||||
|
|
||||||
val actualPath: Path = if (Files.isDirectory(path)) {
|
val actualPath: Path = if (Files.isDirectory(path)) {
|
||||||
@ -93,7 +97,7 @@ public fun IOPlugin.writeMetaFile(
|
|||||||
path: Path,
|
path: Path,
|
||||||
meta: Meta,
|
meta: Meta,
|
||||||
metaFormat: MetaFormatFactory = JsonMetaFormat,
|
metaFormat: MetaFormatFactory = JsonMetaFormat,
|
||||||
descriptor: NodeDescriptor? = null
|
descriptor: NodeDescriptor? = null,
|
||||||
) {
|
) {
|
||||||
val actualPath = if (Files.isDirectory(path)) {
|
val actualPath = if (Files.isDirectory(path)) {
|
||||||
path.resolve("@" + metaFormat.name.toString())
|
path.resolve("@" + metaFormat.name.toString())
|
||||||
@ -146,14 +150,15 @@ public val IOPlugin.Companion.DATA_FILE_NAME: String get() = "@data"
|
|||||||
public fun IOPlugin.readEnvelopeFile(
|
public fun IOPlugin.readEnvelopeFile(
|
||||||
path: Path,
|
path: Path,
|
||||||
readNonEnvelopes: Boolean = false,
|
readNonEnvelopes: Boolean = false,
|
||||||
formatPeeker: IOPlugin.(Path) -> EnvelopeFormat? = IOPlugin::peekBinaryFormat
|
formatPeeker: IOPlugin.(Path) -> EnvelopeFormat? = IOPlugin::peekBinaryFormat,
|
||||||
): Envelope? {
|
): Envelope? {
|
||||||
if (!Files.exists(path)) return null
|
if (!Files.exists(path)) return null
|
||||||
|
|
||||||
//read two-files directory
|
//read two-files directory
|
||||||
if (Files.isDirectory(path)) {
|
if (Files.isDirectory(path)) {
|
||||||
val metaFile = Files.list(path).asSequence()
|
val metaFile = Files.list(path).asSequence().singleOrNull {
|
||||||
.singleOrNull { it.fileName.toString().startsWith(IOPlugin.META_FILE_NAME) }
|
it.fileName.toString().startsWith(IOPlugin.META_FILE_NAME)
|
||||||
|
}
|
||||||
|
|
||||||
val meta = if (metaFile == null) {
|
val meta = if (metaFile == null) {
|
||||||
Meta.EMPTY
|
Meta.EMPTY
|
||||||
@ -196,7 +201,7 @@ public fun IOPlugin.writeEnvelopeFile(
|
|||||||
path: Path,
|
path: Path,
|
||||||
envelope: Envelope,
|
envelope: Envelope,
|
||||||
envelopeFormat: EnvelopeFormat = TaggedEnvelopeFormat,
|
envelopeFormat: EnvelopeFormat = TaggedEnvelopeFormat,
|
||||||
metaFormat: MetaFormatFactory? = null
|
metaFormat: MetaFormatFactory? = null,
|
||||||
) {
|
) {
|
||||||
path.rewrite {
|
path.rewrite {
|
||||||
with(envelopeFormat) {
|
with(envelopeFormat) {
|
||||||
@ -212,7 +217,7 @@ public fun IOPlugin.writeEnvelopeFile(
|
|||||||
fun IOPlugin.writeEnvelopeDirectory(
|
fun IOPlugin.writeEnvelopeDirectory(
|
||||||
path: Path,
|
path: Path,
|
||||||
envelope: Envelope,
|
envelope: Envelope,
|
||||||
metaFormat: MetaFormatFactory = JsonMetaFormat
|
metaFormat: MetaFormatFactory = JsonMetaFormat,
|
||||||
) {
|
) {
|
||||||
if (!Files.exists(path)) {
|
if (!Files.exists(path)) {
|
||||||
Files.createDirectories(path)
|
Files.createDirectories(path)
|
||||||
|
@ -4,7 +4,7 @@ import hep.dataforge.context.Global
|
|||||||
import hep.dataforge.io.Envelope
|
import hep.dataforge.io.Envelope
|
||||||
import hep.dataforge.io.Responder
|
import hep.dataforge.io.Responder
|
||||||
import hep.dataforge.io.TaggedEnvelopeFormat
|
import hep.dataforge.io.TaggedEnvelopeFormat
|
||||||
import hep.dataforge.io.toByteArray
|
import hep.dataforge.io.writeToByteArray
|
||||||
import kotlinx.coroutines.GlobalScope
|
import kotlinx.coroutines.GlobalScope
|
||||||
import kotlinx.coroutines.runBlocking
|
import kotlinx.coroutines.runBlocking
|
||||||
import kotlinx.io.writeDouble
|
import kotlinx.io.writeDouble
|
||||||
@ -18,7 +18,7 @@ import kotlin.time.ExperimentalTime
|
|||||||
@ExperimentalStdlibApi
|
@ExperimentalStdlibApi
|
||||||
object EchoResponder : Responder {
|
object EchoResponder : Responder {
|
||||||
override suspend fun respond(request: Envelope): Envelope {
|
override suspend fun respond(request: Envelope): Envelope {
|
||||||
val string = TaggedEnvelopeFormat().run { toByteArray(request).decodeToString() }
|
val string = TaggedEnvelopeFormat().run { writeToByteArray(request).decodeToString() }
|
||||||
println("ECHO:")
|
println("ECHO:")
|
||||||
println(string)
|
println(string)
|
||||||
return request
|
return request
|
||||||
|
@ -4,6 +4,7 @@ package hep.dataforge.meta
|
|||||||
|
|
||||||
import hep.dataforge.meta.JsonMeta.Companion.JSON_ARRAY_KEY
|
import hep.dataforge.meta.JsonMeta.Companion.JSON_ARRAY_KEY
|
||||||
import hep.dataforge.meta.descriptors.ItemDescriptor
|
import hep.dataforge.meta.descriptors.ItemDescriptor
|
||||||
|
import hep.dataforge.meta.descriptors.ItemDescriptor.Companion.DEFAULT_INDEX_KEY
|
||||||
import hep.dataforge.meta.descriptors.NodeDescriptor
|
import hep.dataforge.meta.descriptors.NodeDescriptor
|
||||||
import hep.dataforge.meta.descriptors.ValueDescriptor
|
import hep.dataforge.meta.descriptors.ValueDescriptor
|
||||||
import hep.dataforge.names.NameToken
|
import hep.dataforge.names.NameToken
|
||||||
@ -75,7 +76,7 @@ private fun Meta.toJsonWithIndex(descriptor: NodeDescriptor?, indexValue: String
|
|||||||
|
|
||||||
|
|
||||||
if (indexValue != null) {
|
if (indexValue != null) {
|
||||||
val indexKey = descriptor?.indexKey ?: NodeDescriptor.DEFAULT_INDEX_KEY
|
val indexKey = descriptor?.indexKey ?: DEFAULT_INDEX_KEY
|
||||||
elementMap[indexKey] = JsonPrimitive(indexValue)
|
elementMap[indexKey] = JsonPrimitive(indexValue)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +159,7 @@ public class JsonMeta(private val json: JsonObject, private val descriptor: Node
|
|||||||
)
|
)
|
||||||
map[key] = MetaItem.ValueItem(listValue)
|
map[key] = MetaItem.ValueItem(listValue)
|
||||||
} else value.forEachIndexed { index, jsonElement ->
|
} else value.forEachIndexed { index, jsonElement ->
|
||||||
val indexKey = (itemDescriptor as? NodeDescriptor)?.indexKey ?: NodeDescriptor.DEFAULT_INDEX_KEY
|
val indexKey = (itemDescriptor as? NodeDescriptor)?.indexKey ?: DEFAULT_INDEX_KEY
|
||||||
val indexValue: String = (jsonElement as? JsonObject)
|
val indexValue: String = (jsonElement as? JsonObject)
|
||||||
?.get(indexKey)?.jsonPrimitive?.contentOrNull
|
?.get(indexKey)?.jsonPrimitive?.contentOrNull
|
||||||
?: index.toString() //In case index is non-string, the backward transformation will be broken.
|
?: index.toString() //In case index is non-string, the backward transformation will be broken.
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
package hep.dataforge.meta
|
package hep.dataforge.meta
|
||||||
|
|
||||||
import hep.dataforge.meta.descriptors.*
|
import hep.dataforge.meta.descriptors.Described
|
||||||
|
import hep.dataforge.meta.descriptors.NodeDescriptor
|
||||||
|
import hep.dataforge.meta.descriptors.defaultItem
|
||||||
|
import hep.dataforge.meta.descriptors.get
|
||||||
import hep.dataforge.names.Name
|
import hep.dataforge.names.Name
|
||||||
import hep.dataforge.names.NameToken
|
import hep.dataforge.names.NameToken
|
||||||
import hep.dataforge.names.plus
|
import hep.dataforge.names.asName
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [Specification].
|
* A base for delegate-based or descriptor-based scheme. [Scheme] has an empty constructor to simplify usage from [Specification].
|
||||||
@ -30,21 +33,21 @@ public open class Scheme(
|
|||||||
* values if default value is unavailable.
|
* values if default value is unavailable.
|
||||||
* Values from [defaultProvider] completely replace
|
* Values from [defaultProvider] completely replace
|
||||||
*/
|
*/
|
||||||
public open val defaultLayer: Meta get() = DefaultLayer(Name.EMPTY)
|
public open val defaultLayer: Meta get() = DefaultLayer()
|
||||||
|
|
||||||
override fun toMeta(): Laminate = Laminate(config, defaultLayer)
|
override fun toMeta(): Laminate = Laminate(config, defaultLayer)
|
||||||
|
|
||||||
private inner class DefaultLayer(val path: Name) : MetaBase() {
|
private inner class DefaultLayer : MetaBase() {
|
||||||
override val items: Map<NameToken, MetaItem<*>> =
|
override val items: Map<NameToken, MetaItem<*>> = buildMap {
|
||||||
(descriptor?.get(path) as? NodeDescriptor)?.items?.entries?.associate { (key, descriptor) ->
|
descriptor?.items?.forEach { (key, itemDescriptor) ->
|
||||||
val token = NameToken(key)
|
val token = NameToken(key)
|
||||||
val fullName = path + token
|
val name = token.asName()
|
||||||
val item: MetaItem<*> = when (descriptor) {
|
val item = defaultProvider.getItem(name) ?: itemDescriptor.defaultItem()
|
||||||
is ValueDescriptor -> getDefaultItem(fullName) ?: descriptor.defaultItem()
|
if (item != null) {
|
||||||
is NodeDescriptor -> MetaItem.NodeItem(DefaultLayer(fullName))
|
put(token, item)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
token to item
|
|
||||||
} ?: emptyMap()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -82,7 +85,7 @@ public open class MetaScheme(
|
|||||||
private val meta: Meta,
|
private val meta: Meta,
|
||||||
override val descriptor: NodeDescriptor? = null,
|
override val descriptor: NodeDescriptor? = null,
|
||||||
config: Config = Config(),
|
config: Config = Config(),
|
||||||
) : Scheme(config, meta::get) {
|
) : Scheme(config, meta) {
|
||||||
override val defaultLayer: Meta get() = Laminate(meta, descriptor?.defaultItem().node)
|
override val defaultLayer: Meta get() = Laminate(meta, descriptor?.defaultItem().node)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,12 +23,6 @@ public interface Specification<T : Configurable> {
|
|||||||
*/
|
*/
|
||||||
public fun <T : Configurable> Specification<T>.update(config: Config, action: T.() -> Unit): T = wrap(config).apply(action)
|
public fun <T : Configurable> Specification<T>.update(config: Config, action: T.() -> Unit): T = wrap(config).apply(action)
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap a configuration using static meta as default
|
|
||||||
*/
|
|
||||||
public fun <T : Configurable> Specification<T>.wrap(config: Config = Config(), default: Meta = Meta.EMPTY): T =
|
|
||||||
wrap(config, default)
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrap a configuration using static meta as default
|
* Wrap a configuration using static meta as default
|
||||||
*/
|
*/
|
||||||
@ -37,7 +31,6 @@ public fun <T : Configurable> Specification<T>.wrap(source: Meta): T {
|
|||||||
return wrap(source.asConfig(), default)
|
return wrap(source.asConfig(), default)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply specified configuration to configurable
|
* Apply specified configuration to configurable
|
||||||
*/
|
*/
|
||||||
|
@ -3,11 +3,11 @@ package hep.dataforge.meta.descriptors
|
|||||||
/**
|
/**
|
||||||
* An object which provides its descriptor
|
* An object which provides its descriptor
|
||||||
*/
|
*/
|
||||||
interface Described {
|
public interface Described {
|
||||||
val descriptor: ItemDescriptor?
|
public val descriptor: ItemDescriptor?
|
||||||
|
|
||||||
companion object {
|
public companion object {
|
||||||
const val DESCRIPTOR_NODE = "@descriptor"
|
//public const val DESCRIPTOR_NODE: String = "@descriptor"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,32 +1,48 @@
|
|||||||
package hep.dataforge.meta.descriptors
|
package hep.dataforge.meta.descriptors
|
||||||
|
|
||||||
import hep.dataforge.meta.Laminate
|
import hep.dataforge.meta.Laminate
|
||||||
|
import hep.dataforge.meta.Meta
|
||||||
import hep.dataforge.meta.MetaBase
|
import hep.dataforge.meta.MetaBase
|
||||||
import hep.dataforge.meta.MetaItem
|
import hep.dataforge.meta.MetaItem
|
||||||
import hep.dataforge.names.NameToken
|
import hep.dataforge.names.NameToken
|
||||||
import hep.dataforge.values.Null
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A [Meta] that wraps a descriptor node
|
* A [Meta] that is constructed from [NodeDescriptor]
|
||||||
*/
|
*/
|
||||||
class DescriptorMeta(val descriptor: NodeDescriptor) : MetaBase() {
|
private class DescriptorMeta(val descriptor: NodeDescriptor) : Meta, MetaBase() {
|
||||||
override val items: Map<NameToken, MetaItem<*>>
|
override val items: Map<NameToken, MetaItem<*>>
|
||||||
get() = descriptor.items.entries.associate { entry ->
|
get() = buildMap {
|
||||||
NameToken(entry.key) to entry.value.defaultItem()
|
descriptor.items.forEach { (token, descriptorItem) ->
|
||||||
|
val item = descriptorItem.defaultItem()
|
||||||
|
if (item != null) {
|
||||||
|
put(NameToken(token), item)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun NodeDescriptor.buildDefaultMeta() = Laminate(default, DescriptorMeta(this))
|
/**
|
||||||
|
* Generate a laminate representing default item set generated by this descriptor
|
||||||
|
*/
|
||||||
|
public fun NodeDescriptor.defaultMeta(): Laminate = Laminate(default, DescriptorMeta(this))
|
||||||
|
|
||||||
fun NodeDescriptor.defaultItem(): MetaItem.NodeItem<*> =
|
/**
|
||||||
MetaItem.NodeItem(buildDefaultMeta())
|
* Build a default [MetaItem.NodeItem] from this node descriptor
|
||||||
|
*/
|
||||||
|
internal fun NodeDescriptor.defaultItem(): MetaItem.NodeItem<*> =
|
||||||
|
MetaItem.NodeItem(defaultMeta())
|
||||||
|
|
||||||
fun ValueDescriptor.defaultItem(): MetaItem.ValueItem = MetaItem.ValueItem(default ?: Null)
|
/**
|
||||||
|
* Build a default [MetaItem.ValueItem] from this descriptor
|
||||||
|
*/
|
||||||
|
internal fun ValueDescriptor.defaultItem(): MetaItem.ValueItem? {
|
||||||
|
return MetaItem.ValueItem(default ?: return null)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build a default [MetaItem] from descriptor.
|
* Build a default [MetaItem] from descriptor.
|
||||||
*/
|
*/
|
||||||
fun ItemDescriptor.defaultItem(): MetaItem<*> {
|
public fun ItemDescriptor.defaultItem(): MetaItem<*>? {
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is ValueDescriptor -> defaultItem()
|
is ValueDescriptor -> defaultItem()
|
||||||
is NodeDescriptor -> defaultItem()
|
is NodeDescriptor -> defaultItem()
|
||||||
|
@ -4,29 +4,26 @@ import hep.dataforge.meta.*
|
|||||||
import hep.dataforge.names.*
|
import hep.dataforge.names.*
|
||||||
import hep.dataforge.values.*
|
import hep.dataforge.values.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A common parent for [ValueDescriptor] and [NodeDescriptor]. Describes a single [MetaItem] or a group of same-name-siblings.
|
||||||
|
*/
|
||||||
@DFBuilder
|
@DFBuilder
|
||||||
sealed class ItemDescriptor(val config: Config) {
|
public sealed class ItemDescriptor(public val config: Config) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if same name siblings with this name are allowed
|
* True if same name siblings with this name are allowed
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
var multiple: Boolean by config.boolean(false)
|
public var multiple: Boolean by config.boolean(false)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The item description
|
* The item description text
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
var info: String? by config.string()
|
public var info: String? by config.string()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if the item is required
|
* True if the item is required
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
abstract var required: Boolean
|
public abstract var required: Boolean
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -34,29 +31,29 @@ sealed class ItemDescriptor(val config: Config) {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
var attributes by config.node()
|
public var attributes: Config? by config.node()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An index field by which this node is identified in case of same name siblings construct
|
||||||
|
*/
|
||||||
|
public var indexKey: String by config.string(DEFAULT_INDEX_KEY)
|
||||||
|
|
||||||
|
public companion object{
|
||||||
|
public const val DEFAULT_INDEX_KEY: String = "@index"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure attributes of the descriptor
|
* Configure attributes of the descriptor, creating an attributes node if needed.
|
||||||
*/
|
*/
|
||||||
fun ItemDescriptor.attributes(block: Config.() -> Unit) {
|
public fun ItemDescriptor.attributes(block: Config.() -> Unit) {
|
||||||
(attributes ?: Config().also { this.attributes = it }).apply(block)
|
(attributes ?: Config().also { this.attributes = it }).apply(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set specific attribute in the descriptor
|
|
||||||
*/
|
|
||||||
fun ItemDescriptor.setAttribute(name: Name, value: Any?) {
|
|
||||||
attributes {
|
|
||||||
set(name, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if given item suits the descriptor
|
* Check if given item suits the descriptor
|
||||||
*/
|
*/
|
||||||
fun ItemDescriptor.validateItem(item: MetaItem<*>?): Boolean {
|
public fun ItemDescriptor.validateItem(item: MetaItem<*>?): Boolean {
|
||||||
if (item == null) return !required
|
if (item == null) return !required
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is ValueDescriptor -> isAllowedValue(item.value ?: return false)
|
is ValueDescriptor -> isAllowedValue(item.value ?: return false)
|
||||||
@ -73,7 +70,7 @@ fun ItemDescriptor.validateItem(item: MetaItem<*>?): Boolean {
|
|||||||
* @author Alexander Nozik
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
@DFBuilder
|
@DFBuilder
|
||||||
class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
|
public class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
|
||||||
init {
|
init {
|
||||||
config[IS_NODE_KEY] = true
|
config[IS_NODE_KEY] = true
|
||||||
}
|
}
|
||||||
@ -90,14 +87,12 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
var default by config.node()
|
public var default: Config? by config.node()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An index field by which this node is identified in case of same name siblings construct
|
* The map of children item descriptors (both nodes and values)
|
||||||
*/
|
*/
|
||||||
var indexKey by config.string(DEFAULT_INDEX_KEY)
|
public val items: Map<String, ItemDescriptor>
|
||||||
|
|
||||||
val items: Map<String, ItemDescriptor>
|
|
||||||
get() = config.getIndexed(ITEM_KEY).mapValues { (_, item) ->
|
get() = config.getIndexed(ITEM_KEY).mapValues { (_, item) ->
|
||||||
val node = item.node ?: error("Node descriptor must be a node")
|
val node = item.node ?: error("Node descriptor must be a node")
|
||||||
if (node[IS_NODE_KEY].boolean == true) {
|
if (node[IS_NODE_KEY].boolean == true) {
|
||||||
@ -111,7 +106,7 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
|
|||||||
* The map of children node descriptors
|
* The map of children node descriptors
|
||||||
*/
|
*/
|
||||||
@Suppress("UNCHECKED_CAST")
|
@Suppress("UNCHECKED_CAST")
|
||||||
val nodes: Map<String, NodeDescriptor>
|
public val nodes: Map<String, NodeDescriptor>
|
||||||
get() = config.getIndexed(ITEM_KEY).entries.filter {
|
get() = config.getIndexed(ITEM_KEY).entries.filter {
|
||||||
it.value.node[IS_NODE_KEY].boolean == true
|
it.value.node[IS_NODE_KEY].boolean == true
|
||||||
}.associate { (name, item) ->
|
}.associate { (name, item) ->
|
||||||
@ -120,9 +115,9 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The list of value descriptors
|
* The list of children value descriptors
|
||||||
*/
|
*/
|
||||||
val values: Map<String, ValueDescriptor>
|
public val values: Map<String, ValueDescriptor>
|
||||||
get() = config.getIndexed(ITEM_KEY).entries.filter {
|
get() = config.getIndexed(ITEM_KEY).entries.filter {
|
||||||
it.value.node[IS_NODE_KEY].boolean != true
|
it.value.node[IS_NODE_KEY].boolean != true
|
||||||
}.associate { (name, item) ->
|
}.associate { (name, item) ->
|
||||||
@ -154,39 +149,43 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
|
|||||||
config[token] = descriptor.config
|
config[token] = descriptor.config
|
||||||
}
|
}
|
||||||
|
|
||||||
fun item(name: Name, descriptor: ItemDescriptor) {
|
public fun item(name: Name, descriptor: ItemDescriptor) {
|
||||||
buildNode(name.cutLast()).newItem(name.lastOrNull().toString(), descriptor)
|
buildNode(name.cutLast()).newItem(name.lastOrNull().toString(), descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun item(name: String, descriptor: ItemDescriptor) {
|
public fun item(name: String, descriptor: ItemDescriptor) {
|
||||||
item(name.toName(), descriptor)
|
item(name.toName(), descriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun node(name: Name, block: NodeDescriptor.() -> Unit) {
|
/**
|
||||||
|
* Create and configure a child node descriptor
|
||||||
|
*/
|
||||||
|
public fun node(name: Name, block: NodeDescriptor.() -> Unit) {
|
||||||
item(name, NodeDescriptor().apply(block))
|
item(name, NodeDescriptor().apply(block))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun node(name: String, block: NodeDescriptor.() -> Unit) {
|
public fun node(name: String, block: NodeDescriptor.() -> Unit) {
|
||||||
node(name.toName(), block)
|
node(name.toName(), block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun value(name: Name, block: ValueDescriptor.() -> Unit) {
|
/**
|
||||||
|
* Create and configure child value descriptor
|
||||||
|
*/
|
||||||
|
public fun value(name: Name, block: ValueDescriptor.() -> Unit) {
|
||||||
require(name.length >= 1) { "Name length for value descriptor must be non-empty" }
|
require(name.length >= 1) { "Name length for value descriptor must be non-empty" }
|
||||||
item(name, ValueDescriptor().apply(block))
|
item(name, ValueDescriptor().apply(block))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun value(name: String, block: ValueDescriptor.() -> Unit) {
|
public fun value(name: String, block: ValueDescriptor.() -> Unit) {
|
||||||
value(name.toName(), block)
|
value(name.toName(), block)
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
public companion object {
|
||||||
|
|
||||||
val ITEM_KEY = "item".asName()
|
internal val ITEM_KEY: Name = "item".asName()
|
||||||
val IS_NODE_KEY = "@isNode".asName()
|
internal val IS_NODE_KEY: Name = "@isNode".asName()
|
||||||
|
|
||||||
const val DEFAULT_INDEX_KEY = "@index"
|
public inline operator fun invoke(block: NodeDescriptor.() -> Unit): NodeDescriptor = NodeDescriptor().apply(block)
|
||||||
|
|
||||||
inline operator fun invoke(block: NodeDescriptor.() -> Unit) = NodeDescriptor().apply(block)
|
|
||||||
|
|
||||||
//TODO infer descriptor from spec
|
//TODO infer descriptor from spec
|
||||||
}
|
}
|
||||||
@ -195,7 +194,7 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
|
|||||||
/**
|
/**
|
||||||
* Get a descriptor item associated with given name or null if item for given name not provided
|
* Get a descriptor item associated with given name or null if item for given name not provided
|
||||||
*/
|
*/
|
||||||
operator fun ItemDescriptor.get(name: Name): ItemDescriptor? {
|
public operator fun ItemDescriptor.get(name: Name): ItemDescriptor? {
|
||||||
if (name.isEmpty()) return this
|
if (name.isEmpty()) return this
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is ValueDescriptor -> null // empty name already checked
|
is ValueDescriptor -> null // empty name already checked
|
||||||
@ -203,7 +202,7 @@ operator fun ItemDescriptor.get(name: Name): ItemDescriptor? {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun ItemDescriptor.get(name: String): ItemDescriptor? = get(name.toName())
|
public operator fun ItemDescriptor.get(name: String): ItemDescriptor? = get(name.toName())
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A descriptor for meta value
|
* A descriptor for meta value
|
||||||
@ -213,7 +212,7 @@ operator fun ItemDescriptor.get(name: String): ItemDescriptor? = get(name.toName
|
|||||||
* @author Alexander Nozik
|
* @author Alexander Nozik
|
||||||
*/
|
*/
|
||||||
@DFBuilder
|
@DFBuilder
|
||||||
class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
|
public class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if the value is required
|
* True if the value is required
|
||||||
@ -227,9 +226,9 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
var default: Value? by config.value()
|
public var default: Value? by config.value()
|
||||||
|
|
||||||
fun default(v: Any) {
|
public fun default(v: Any) {
|
||||||
this.default = Value.of(v)
|
this.default = Value.of(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,9 +237,9 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
var type: List<ValueType>? by config.listValue { ValueType.valueOf(it.string) }
|
public var type: List<ValueType>? by config.listValue { ValueType.valueOf(it.string) }
|
||||||
|
|
||||||
fun type(vararg t: ValueType) {
|
public fun type(vararg t: ValueType) {
|
||||||
this.type = listOf(*t)
|
this.type = listOf(*t)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,7 +250,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
|
|||||||
* @param value
|
* @param value
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
fun isAllowedValue(value: Value): Boolean {
|
public fun isAllowedValue(value: Value): Boolean {
|
||||||
return (type?.let { it.contains(ValueType.STRING) || it.contains(value.type) } ?: true)
|
return (type?.let { it.contains(ValueType.STRING) || it.contains(value.type) } ?: true)
|
||||||
&& (allowedValues.isEmpty() || allowedValues.contains(value))
|
&& (allowedValues.isEmpty() || allowedValues.contains(value))
|
||||||
}
|
}
|
||||||
@ -262,7 +261,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
|
|||||||
*
|
*
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
var allowedValues: List<Value> by config.item().convert(
|
public var allowedValues: List<Value> by config.item().convert(
|
||||||
reader = {
|
reader = {
|
||||||
val value = it.value
|
val value = it.value
|
||||||
when {
|
when {
|
||||||
@ -279,7 +278,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
|
|||||||
/**
|
/**
|
||||||
* Allow given list of value and forbid others
|
* Allow given list of value and forbid others
|
||||||
*/
|
*/
|
||||||
fun allow(vararg v: Any) {
|
public fun allow(vararg v: Any) {
|
||||||
this.allowedValues = v.map { Value.of(it) }
|
this.allowedValues = v.map { Value.of(it) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -287,7 +286,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
|
|||||||
/**
|
/**
|
||||||
* Merge two node descriptors into one using first one as primary
|
* Merge two node descriptors into one using first one as primary
|
||||||
*/
|
*/
|
||||||
operator fun NodeDescriptor.plus(other: NodeDescriptor): NodeDescriptor {
|
public operator fun NodeDescriptor.plus(other: NodeDescriptor): NodeDescriptor {
|
||||||
return NodeDescriptor().apply {
|
return NodeDescriptor().apply {
|
||||||
config.update(other.config)
|
config.update(other.config)
|
||||||
config.update(this@plus.config)
|
config.update(this@plus.config)
|
||||||
|
@ -36,7 +36,7 @@ class DescriptorTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDefaultMetaNode(){
|
fun testDefaultMetaNode(){
|
||||||
val meta = descriptor.buildDefaultMeta()
|
val meta = descriptor.defaultMeta()
|
||||||
assertEquals(false, meta["aNode.otherNode.otherValue"].boolean)
|
assertEquals(false, meta["aNode.otherNode.otherValue"].boolean)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +0,0 @@
|
|||||||
package hep.dataforge.meta
|
|
||||||
|
|
||||||
import kotlinx.serialization.json.Json
|
|
||||||
|
|
||||||
public val JSON_PRETTY: Json = Json { prettyPrint = true; useArrayPolymorphism = true }
|
|
||||||
public val JSON_PLAIN: Json = Json { prettyPrint = false; useArrayPolymorphism = true }
|
|
Loading…
Reference in New Issue
Block a user