Fix IO after refactoring

This commit is contained in:
Alexander Nozik 2020-09-08 16:04:15 +03:00
parent 52a3c8bc6f
commit 8a8484172c
18 changed files with 165 additions and 157 deletions

View File

@ -105,11 +105,13 @@ class FrontMatterEnvelopeFormat(
override fun readPartial(input: Input): PartialEnvelope =
default.readPartial(input)
override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta): Unit =
default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
override fun Output.writeEnvelope(
envelope: Envelope,
metaFormatFactory: MetaFormatFactory,
formatMeta: Meta,
): Unit = default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
override fun readObject(input: Input): Envelope =
default.readObject(input)
override fun readObject(input: Input): Envelope = default.readObject(input)
}
}

View File

@ -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

View File

@ -12,7 +12,7 @@ import hep.dataforge.meta.toJson
import hep.dataforge.meta.toMetaItem
import kotlinx.io.Input
import kotlinx.io.Output
import kotlinx.io.readByteArray
import kotlinx.io.text.readUtf8String
import kotlinx.io.text.writeUtf8String
import kotlinx.serialization.json.Json
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?) {
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 {
@ -32,7 +32,7 @@ public class JsonMetaFormat(private val json: Json = DEFAULT_JSON) : MetaFormat
}
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 item = jsonElement.toMetaItem(descriptor)
return item.node ?: Meta.EMPTY

View File

@ -18,7 +18,7 @@ import kotlinx.io.*
*/
public class TaggedEnvelopeFormat(
public val io: IOPlugin,
public val version: VERSION = VERSION.DF02
public val version: VERSION = VERSION.DF02,
) : EnvelopeFormat {
// private val metaFormat = io.metaFormat(metaFormatKey)
@ -67,11 +67,7 @@ public class TaggedEnvelopeFormat(
val metaFormat = io.resolveMetaFormat(tag.metaFormatKey)
?: error("Meta format with key ${tag.metaFormatKey} not found")
val meta: Meta = input.limit(tag.metaSize.toInt()).run {
metaFormat.run {
readObject(input)
}
}
val meta: Meta = metaFormat.readObject(input.limit(tag.metaSize.toInt()))
val data = input.readBinary(tag.dataSize.toInt())
@ -84,11 +80,8 @@ public class TaggedEnvelopeFormat(
val metaFormat = io.resolveMetaFormat(tag.metaFormatKey)
?: error("Meta format with key ${tag.metaFormatKey} not found")
val meta: Meta = input.limit(tag.metaSize.toInt()).run {
metaFormat.run {
readObject(input)
}
}
val meta: Meta = metaFormat.readObject(input.limit(tag.metaSize.toInt()))
return PartialEnvelope(meta, version.tagSize + tag.metaSize, tag.dataSize)
}
@ -96,7 +89,7 @@ public class TaggedEnvelopeFormat(
private data class Tag(
val metaFormatKey: Short,
val metaSize: UInt,
val dataSize: ULong
val dataSize: ULong,
)
public enum class VERSION(public val tagSize: UInt) {
@ -165,13 +158,13 @@ public class TaggedEnvelopeFormat(
override fun readPartial(input: Input): PartialEnvelope =
default.run { readPartial(input) }
override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta): Unit =
default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
override fun readObject(input: Input): Envelope =
default.run { readObject(input) }
override fun Output.writeEnvelope(
envelope: Envelope,
metaFormatFactory: MetaFormatFactory,
formatMeta: Meta,
): Unit = default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
override fun readObject(input: Input): Envelope = default.readObject(input)
}
}

View File

@ -20,7 +20,7 @@ import kotlin.collections.set
*/
public class TaglessEnvelopeFormat(
public val io: IOPlugin,
public val meta: Meta = Meta.EMPTY
public val meta: Meta = Meta.EMPTY,
) : EnvelopeFormat {
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 metaSize = properties[META_LENGTH_PROPERTY]?.toInt()
meta = if (metaSize != null) {
input.limit(metaSize).run {
metaFormat.run { readObject(input) }
}
metaFormat.readObject(input.limit(metaSize))
} else {
metaFormat.run {
readObject(input)
}
metaFormat.readObject(input)
}
}
@ -150,9 +146,7 @@ public class TaglessEnvelopeFormat(
val metaSize = properties[META_LENGTH_PROPERTY]?.toInt()
meta = if (metaSize != null) {
offset += metaSize.toUInt()
input.limit(metaSize).run {
metaFormat.run { readObject(input) }
}
metaFormat.readObject(input.limit(metaSize))
} else {
error("Can't partially read an envelope with undefined meta size")
}
@ -203,11 +197,13 @@ public class TaglessEnvelopeFormat(
override fun readPartial(input: Input): PartialEnvelope =
default.run { readPartial(input) }
override fun Output.writeEnvelope(envelope: Envelope, metaFormatFactory: MetaFormatFactory, formatMeta: Meta): Unit =
default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
override fun Output.writeEnvelope(
envelope: Envelope,
metaFormatFactory: MetaFormatFactory,
formatMeta: Meta,
): Unit = default.run { writeEnvelope(envelope, metaFormatFactory, formatMeta) }
override fun readObject(input: Input): Envelope =
default.run { readObject(input) }
override fun readObject(input: Input): Envelope = default.readObject(input)
override fun peekFormat(io: IOPlugin, input: Input): EnvelopeFormat? {
return try {

View File

@ -23,9 +23,9 @@ class EnvelopeFormatTest {
@Test
fun testTaggedFormat(){
TaggedEnvelopeFormat.run {
val byteArray = this.toByteArray(envelope)
val byteArray = writeToByteArray(envelope)
//println(byteArray.decodeToString())
val res = readByteArray(byteArray)
val res = readFromByteArray(byteArray)
assertEquals(envelope.meta,res.meta)
val double = res.data?.read {
readDouble()
@ -37,9 +37,9 @@ class EnvelopeFormatTest {
@Test
fun testTaglessFormat(){
TaglessEnvelopeFormat.run {
val byteArray = toByteArray(envelope)
val byteArray = writeToByteArray(envelope)
//println(byteArray.decodeToString())
val res = readByteArray(byteArray)
val res = readFromByteArray(byteArray)
assertEquals(envelope.meta,res.meta)
val double = res.data?.read {
readDouble()

View File

@ -1,13 +1,19 @@
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.toName
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.cbor.Cbor
import kotlinx.serialization.json.Json
import kotlin.test.Test
import kotlin.test.assertEquals
val JSON_PRETTY: Json = Json { prettyPrint = true; useArrayPolymorphism = true }
val JSON_PLAIN: Json = Json { prettyPrint = false; useArrayPolymorphism = true }
class MetaSerializerTest {
val meta = Meta {
"a" put 22

View File

@ -3,5 +3,5 @@ package hep.dataforge.io
import kotlinx.io.ByteArrayInput
import kotlinx.io.use
fun <T : Any> IOFormat<T>.toByteArray(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>.writeToByteArray(obj: T): ByteArray = buildByteArray { writeObject(this, obj) }
fun <T : Any> IOFormat<T>.readFromByteArray(array: ByteArray): T = ByteArrayInput(array).use { readObject(it) }

View File

@ -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.
* 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")
val actualPath: Path = if (Files.isDirectory(path)) {
@ -93,7 +97,7 @@ public fun IOPlugin.writeMetaFile(
path: Path,
meta: Meta,
metaFormat: MetaFormatFactory = JsonMetaFormat,
descriptor: NodeDescriptor? = null
descriptor: NodeDescriptor? = null,
) {
val actualPath = if (Files.isDirectory(path)) {
path.resolve("@" + metaFormat.name.toString())
@ -146,14 +150,15 @@ public val IOPlugin.Companion.DATA_FILE_NAME: String get() = "@data"
public fun IOPlugin.readEnvelopeFile(
path: Path,
readNonEnvelopes: Boolean = false,
formatPeeker: IOPlugin.(Path) -> EnvelopeFormat? = IOPlugin::peekBinaryFormat
formatPeeker: IOPlugin.(Path) -> EnvelopeFormat? = IOPlugin::peekBinaryFormat,
): Envelope? {
if (!Files.exists(path)) return null
//read two-files directory
if (Files.isDirectory(path)) {
val metaFile = Files.list(path).asSequence()
.singleOrNull { it.fileName.toString().startsWith(IOPlugin.META_FILE_NAME) }
val metaFile = Files.list(path).asSequence().singleOrNull {
it.fileName.toString().startsWith(IOPlugin.META_FILE_NAME)
}
val meta = if (metaFile == null) {
Meta.EMPTY
@ -196,7 +201,7 @@ public fun IOPlugin.writeEnvelopeFile(
path: Path,
envelope: Envelope,
envelopeFormat: EnvelopeFormat = TaggedEnvelopeFormat,
metaFormat: MetaFormatFactory? = null
metaFormat: MetaFormatFactory? = null,
) {
path.rewrite {
with(envelopeFormat) {
@ -212,7 +217,7 @@ public fun IOPlugin.writeEnvelopeFile(
fun IOPlugin.writeEnvelopeDirectory(
path: Path,
envelope: Envelope,
metaFormat: MetaFormatFactory = JsonMetaFormat
metaFormat: MetaFormatFactory = JsonMetaFormat,
) {
if (!Files.exists(path)) {
Files.createDirectories(path)

View File

@ -4,7 +4,7 @@ import hep.dataforge.context.Global
import hep.dataforge.io.Envelope
import hep.dataforge.io.Responder
import hep.dataforge.io.TaggedEnvelopeFormat
import hep.dataforge.io.toByteArray
import hep.dataforge.io.writeToByteArray
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.runBlocking
import kotlinx.io.writeDouble
@ -18,7 +18,7 @@ import kotlin.time.ExperimentalTime
@ExperimentalStdlibApi
object EchoResponder : Responder {
override suspend fun respond(request: Envelope): Envelope {
val string = TaggedEnvelopeFormat().run { toByteArray(request).decodeToString() }
val string = TaggedEnvelopeFormat().run { writeToByteArray(request).decodeToString() }
println("ECHO:")
println(string)
return request

View File

@ -4,6 +4,7 @@ package hep.dataforge.meta
import hep.dataforge.meta.JsonMeta.Companion.JSON_ARRAY_KEY
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.ValueDescriptor
import hep.dataforge.names.NameToken
@ -75,7 +76,7 @@ private fun Meta.toJsonWithIndex(descriptor: NodeDescriptor?, indexValue: String
if (indexValue != null) {
val indexKey = descriptor?.indexKey ?: NodeDescriptor.DEFAULT_INDEX_KEY
val indexKey = descriptor?.indexKey ?: DEFAULT_INDEX_KEY
elementMap[indexKey] = JsonPrimitive(indexValue)
}
@ -158,7 +159,7 @@ public class JsonMeta(private val json: JsonObject, private val descriptor: Node
)
map[key] = MetaItem.ValueItem(listValue)
} 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)
?.get(indexKey)?.jsonPrimitive?.contentOrNull
?: index.toString() //In case index is non-string, the backward transformation will be broken.

View File

@ -1,9 +1,12 @@
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.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].
@ -30,21 +33,21 @@ public open class Scheme(
* values if default value is unavailable.
* 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)
private inner class DefaultLayer(val path: Name) : MetaBase() {
override val items: Map<NameToken, MetaItem<*>> =
(descriptor?.get(path) as? NodeDescriptor)?.items?.entries?.associate { (key, descriptor) ->
private inner class DefaultLayer : MetaBase() {
override val items: Map<NameToken, MetaItem<*>> = buildMap {
descriptor?.items?.forEach { (key, itemDescriptor) ->
val token = NameToken(key)
val fullName = path + token
val item: MetaItem<*> = when (descriptor) {
is ValueDescriptor -> getDefaultItem(fullName) ?: descriptor.defaultItem()
is NodeDescriptor -> MetaItem.NodeItem(DefaultLayer(fullName))
val name = token.asName()
val item = defaultProvider.getItem(name) ?: itemDescriptor.defaultItem()
if (item != null) {
put(token, item)
}
}
}
token to item
} ?: emptyMap()
}
}
@ -82,7 +85,7 @@ public open class MetaScheme(
private val meta: Meta,
override val descriptor: NodeDescriptor? = null,
config: Config = Config(),
) : Scheme(config, meta::get) {
) : Scheme(config, meta) {
override val defaultLayer: Meta get() = Laminate(meta, descriptor?.defaultItem().node)
}

View File

@ -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)
/**
* 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
*/
@ -37,7 +31,6 @@ public fun <T : Configurable> Specification<T>.wrap(source: Meta): T {
return wrap(source.asConfig(), default)
}
/**
* Apply specified configuration to configurable
*/

View File

@ -3,11 +3,11 @@ package hep.dataforge.meta.descriptors
/**
* An object which provides its descriptor
*/
interface Described {
val descriptor: ItemDescriptor?
public interface Described {
public val descriptor: ItemDescriptor?
companion object {
const val DESCRIPTOR_NODE = "@descriptor"
public companion object {
//public const val DESCRIPTOR_NODE: String = "@descriptor"
}
}

View File

@ -1,32 +1,48 @@
package hep.dataforge.meta.descriptors
import hep.dataforge.meta.Laminate
import hep.dataforge.meta.Meta
import hep.dataforge.meta.MetaBase
import hep.dataforge.meta.MetaItem
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<*>>
get() = descriptor.items.entries.associate { entry ->
NameToken(entry.key) to entry.value.defaultItem()
get() = buildMap {
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.
*/
fun ItemDescriptor.defaultItem(): MetaItem<*> {
public fun ItemDescriptor.defaultItem(): MetaItem<*>? {
return when (this) {
is ValueDescriptor -> defaultItem()
is NodeDescriptor -> defaultItem()

View File

@ -4,29 +4,26 @@ import hep.dataforge.meta.*
import hep.dataforge.names.*
import hep.dataforge.values.*
/**
* A common parent for [ValueDescriptor] and [NodeDescriptor]. Describes a single [MetaItem] or a group of same-name-siblings.
*/
@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
*
* @return
*/
var multiple: Boolean by config.boolean(false)
public var multiple: Boolean by config.boolean(false)
/**
* The item description
*
* @return
* The item description text
*/
var info: String? by config.string()
public var info: String? by config.string()
/**
* 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
*/
var attributes by config.node()
}
public var attributes: Config? by config.node()
/**
* Configure attributes of the descriptor
/**
* An index field by which this node is identified in case of same name siblings construct
*/
fun ItemDescriptor.attributes(block: Config.() -> Unit) {
(attributes ?: Config().also { this.attributes = it }).apply(block)
}
public var indexKey: String by config.string(DEFAULT_INDEX_KEY)
/**
* Set specific attribute in the descriptor
*/
fun ItemDescriptor.setAttribute(name: Name, value: Any?) {
attributes {
set(name, value)
public companion object{
public const val DEFAULT_INDEX_KEY: String = "@index"
}
}
/**
* Configure attributes of the descriptor, creating an attributes node if needed.
*/
public fun ItemDescriptor.attributes(block: Config.() -> Unit) {
(attributes ?: Config().also { this.attributes = it }).apply(block)
}
/**
* 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
return when (this) {
is ValueDescriptor -> isAllowedValue(item.value ?: return false)
@ -73,7 +70,7 @@ fun ItemDescriptor.validateItem(item: MetaItem<*>?): Boolean {
* @author Alexander Nozik
*/
@DFBuilder
class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
public class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
init {
config[IS_NODE_KEY] = true
}
@ -90,14 +87,12 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
*
* @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)
val items: Map<String, ItemDescriptor>
public val items: Map<String, ItemDescriptor>
get() = config.getIndexed(ITEM_KEY).mapValues { (_, item) ->
val node = item.node ?: error("Node descriptor must be a node")
if (node[IS_NODE_KEY].boolean == true) {
@ -111,7 +106,7 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(config) {
* The map of children node descriptors
*/
@Suppress("UNCHECKED_CAST")
val nodes: Map<String, NodeDescriptor>
public val nodes: Map<String, NodeDescriptor>
get() = config.getIndexed(ITEM_KEY).entries.filter {
it.value.node[IS_NODE_KEY].boolean == true
}.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 {
it.value.node[IS_NODE_KEY].boolean != true
}.associate { (name, item) ->
@ -154,39 +149,43 @@ class NodeDescriptor(config: Config = Config()) : ItemDescriptor(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)
}
fun item(name: String, descriptor: ItemDescriptor) {
public fun item(name: String, descriptor: ItemDescriptor) {
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))
}
fun node(name: String, block: NodeDescriptor.() -> Unit) {
public fun node(name: String, block: NodeDescriptor.() -> Unit) {
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" }
item(name, ValueDescriptor().apply(block))
}
fun value(name: String, block: ValueDescriptor.() -> Unit) {
public fun value(name: String, block: ValueDescriptor.() -> Unit) {
value(name.toName(), block)
}
companion object {
public companion object {
val ITEM_KEY = "item".asName()
val IS_NODE_KEY = "@isNode".asName()
internal val ITEM_KEY: Name = "item".asName()
internal val IS_NODE_KEY: Name = "@isNode".asName()
const val DEFAULT_INDEX_KEY = "@index"
inline operator fun invoke(block: NodeDescriptor.() -> Unit) = NodeDescriptor().apply(block)
public inline operator fun invoke(block: NodeDescriptor.() -> Unit): NodeDescriptor = NodeDescriptor().apply(block)
//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
*/
operator fun ItemDescriptor.get(name: Name): ItemDescriptor? {
public operator fun ItemDescriptor.get(name: Name): ItemDescriptor? {
if (name.isEmpty()) return this
return when (this) {
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
@ -213,7 +212,7 @@ operator fun ItemDescriptor.get(name: String): ItemDescriptor? = get(name.toName
* @author Alexander Nozik
*/
@DFBuilder
class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
public class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
/**
* True if the value is required
@ -227,9 +226,9 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
*
* @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)
}
@ -238,9 +237,9 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
*
* @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)
}
@ -251,7 +250,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
* @param value
* @return
*/
fun isAllowedValue(value: Value): Boolean {
public fun isAllowedValue(value: Value): Boolean {
return (type?.let { it.contains(ValueType.STRING) || it.contains(value.type) } ?: true)
&& (allowedValues.isEmpty() || allowedValues.contains(value))
}
@ -262,7 +261,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
*
* @return
*/
var allowedValues: List<Value> by config.item().convert(
public var allowedValues: List<Value> by config.item().convert(
reader = {
val value = it.value
when {
@ -279,7 +278,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
/**
* 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) }
}
}
@ -287,7 +286,7 @@ class ValueDescriptor(config: Config = Config()) : ItemDescriptor(config) {
/**
* 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 {
config.update(other.config)
config.update(this@plus.config)

View File

@ -36,7 +36,7 @@ class DescriptorTest {
@Test
fun testDefaultMetaNode(){
val meta = descriptor.buildDefaultMeta()
val meta = descriptor.defaultMeta()
assertEquals(false, meta["aNode.otherNode.otherValue"].boolean)
}
}

View File

@ -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 }