From a5a4b67c97095558c76d950859c9e2aa2d802bf9 Mon Sep 17 00:00:00 2001 From: Alexander Nozik Date: Sun, 23 Sep 2018 21:09:35 +0300 Subject: [PATCH] custom JSON serialization (no universal serialization yet) --- .gitignore | 2 +- build.gradle | 24 +- dataforge-meta-common/build.gradle | 9 +- .../main/kotlin/hep/dataforge/meta/Meta.kt | 116 ++++++-- .../kotlin/hep/dataforge/meta/MetaBuilder.kt | 11 + .../kotlin/hep/dataforge/meta/MetaUtils.kt | 40 --- .../kotlin/hep/dataforge/meta/Serializers.kt | 263 +++++++++++++----- .../main/kotlin/hep/dataforge/meta/Value.kt | 69 +++-- .../main/kotlin/hep/dataforge/names/Name.kt | 3 +- .../hep/dataforge/meta/SerializationTest.kt | 46 ++- dataforge-meta-js/build.gradle | 3 +- dataforge-meta-jvm/build.gradle | 6 +- 12 files changed, 411 insertions(+), 181 deletions(-) delete mode 100644 dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/MetaUtils.kt diff --git a/.gitignore b/.gitignore index d482c058..d35e96f9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,7 +3,7 @@ *.iws out/ .gradle -/build/ +**/build/ !gradle-wrapper.jar diff --git a/build.gradle b/build.gradle index cd59ea87..ae66ee48 100644 --- a/build.gradle +++ b/build.gradle @@ -1,26 +1,40 @@ buildscript { - ext.kotlin_version = '1.2.70' - ext.serialization_version = '0.6.2' + ext.kotlin_version = '1.3.0-rc-57' + ext.serialization_version = '0.8.0-rc13' repositories { jcenter() - maven { url "https://kotlin.bintray.com/kotlinx" } + maven { + url = "http://dl.bintray.com/kotlin/kotlin-eap" + } } dependencies { classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" - classpath "org.jetbrains.kotlinx:kotlinx-gradle-serialization-plugin:$serialization_version" + classpath "org.jetbrains.kotlin:kotlin-serialization:$kotlin_version" } } +//plugins { +// id 'kotlin-platform-common' version "$kotlin_version" apply false +// id 'kotlin-platform-jvm' version "$kotlin_version" apply false +// id 'kotlin-platform-js' version "$kotlin_version" apply false +// id 'kotlinx-serialization' version "$kotlin_version" apply false +//} + description = "The basic interfaces for DataForge meta-data" group 'hep.dataforge' version '0.1.1-SNAPSHOT' -subprojects{ +allprojects { repositories { jcenter() + maven { url = "http://dl.bintray.com/kotlin/kotlin-eap" } maven { url "https://kotlin.bintray.com/kotlinx" } //maven { url 'https://jitpack.io' } } } + +subprojects { + apply plugin: 'kotlinx-serialization' +} diff --git a/dataforge-meta-common/build.gradle b/dataforge-meta-common/build.gradle index 6292cd0f..a396466f 100644 --- a/dataforge-meta-common/build.gradle +++ b/dataforge-meta-common/build.gradle @@ -1,6 +1,5 @@ -plugins { +plugins{ id 'kotlin-platform-common' - id 'kotlinx-serialization' } dependencies { @@ -8,10 +7,4 @@ dependencies { compile "org.jetbrains.kotlinx:kotlinx-serialization-runtime-common:$serialization_version" testCompile "org.jetbrains.kotlin:kotlin-test-annotations-common" testCompile "org.jetbrains.kotlin:kotlin-test-common" -} - -kotlin { - experimental { - coroutines "enable" - } } \ No newline at end of file diff --git a/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/Meta.kt b/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/Meta.kt index b67fc68b..b84a84e7 100644 --- a/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/Meta.kt +++ b/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/Meta.kt @@ -2,7 +2,6 @@ package hep.dataforge.meta import hep.dataforge.names.Name import hep.dataforge.names.toName -import kotlinx.serialization.Serializable /** * A member of the meta tree. Could be represented as one of following: @@ -11,9 +10,34 @@ import kotlinx.serialization.Serializable * * a list of nodes */ sealed class MetaItem { - class ValueItem(val value: Value) : MetaItem() - class SingleNodeItem(val node: M) : MetaItem() - class MultiNodeItem(val nodes: List) : MetaItem() + class ValueItem(val value: Value) : MetaItem(){ + override fun equals(other: Any?): Boolean { + return this.value == (other as? ValueItem<*>)?.value + } + + override fun hashCode(): Int { + return value.hashCode() + } + } + class SingleNodeItem(val node: M) : MetaItem(){ + override fun equals(other: Any?): Boolean { + return this.node == (other as? SingleNodeItem<*>)?.node + } + + override fun hashCode(): Int { + return node.hashCode() + } + } + + class MultiNodeItem(val nodes: List) : MetaItem(){ + override fun equals(other: Any?): Boolean { + return this.nodes == (other as? MultiNodeItem<*>)?.nodes + } + + override fun hashCode(): Int { + return nodes.hashCode() + } + } } operator fun List.get(query: String): M? { @@ -31,7 +55,6 @@ operator fun List.get(query: String): M? { * * [MetaItem.SingleNodeItem] single node * * [MetaItem.MultiNodeItem] multi-value node */ -@Serializable interface Meta { val items: Map> } @@ -62,6 +85,22 @@ abstract class MetaNode> : Meta { } operator fun get(key: String): MetaItem? = get(key.toName()) + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other !is Meta) return false + + return this.items == other.items + } + + override fun hashCode(): Int { + return items.hashCode() + } + + override fun toString(): String { + return toJSON().toString() + } + } /** @@ -69,17 +108,23 @@ abstract class MetaNode> : Meta { * * If the argument is possibly mutable node, it is copied on creation */ -class SealedMeta(meta: Meta) : MetaNode() { - override val items: Map> = if (meta is SealedMeta) { - meta.items - } else { - meta.items.mapValues { entry -> - val item = entry.value - when (item) { - is MetaItem.ValueItem -> MetaItem.ValueItem(item.value) - is MetaItem.SingleNodeItem -> MetaItem.SingleNodeItem(SealedMeta(item.node)) - is MetaItem.MultiNodeItem -> MetaItem.MultiNodeItem(item.nodes.map { SealedMeta(it) }) +class SealedMeta internal constructor(override val items: Map>) : MetaNode() { + + companion object { + fun seal(meta: Meta): SealedMeta { + val items = if (meta is SealedMeta) { + meta.items + } else { + meta.items.mapValues { entry -> + val item = entry.value + when (item) { + is MetaItem.ValueItem -> MetaItem.ValueItem(item.value) + is MetaItem.SingleNodeItem -> MetaItem.SingleNodeItem(seal(item.node)) + is MetaItem.MultiNodeItem -> MetaItem.MultiNodeItem(item.nodes.map { seal(it) }) + } + } } + return SealedMeta(items) } } } @@ -87,12 +132,51 @@ class SealedMeta(meta: Meta) : MetaNode() { /** * Generate sealed node from [this]. If it is already sealed return it as is */ -fun Meta.seal(): SealedMeta = this as? SealedMeta ?: SealedMeta(this) +fun Meta.seal(): SealedMeta = this as? SealedMeta ?: SealedMeta.seal(this) object EmptyMeta : Meta { override val items: Map> = emptyMap() } +/** + * Unsafe methods to access values and nodes directly from [MetaItem] + */ + +val MetaItem<*>.value + get() = (this as? MetaItem.ValueItem)?.value ?: error("Trying to interpret node meta item as value item") +val MetaItem<*>.string get() = value.string +val MetaItem<*>.boolean get() = value.boolean +val MetaItem<*>.number get() = value.number +val MetaItem<*>.double get() = number.toDouble() +val MetaItem<*>.int get() = number.toInt() +val MetaItem<*>.long get() = number.toLong() + +val MetaItem.node: M + get() = when (this) { + is MetaItem.ValueItem -> error("Trying to interpret value meta item as node item") + is MetaItem.SingleNodeItem -> node + is MetaItem.MultiNodeItem -> nodes.first() + } + +/** + * Utility method to access item content as list of nodes. + * Returns empty list if it is value item. + */ +val MetaItem.nodes: List + get() = when (this) { + is MetaItem.ValueItem -> emptyList()//error("Trying to interpret value meta item as node item") + is MetaItem.SingleNodeItem -> listOf(node) + is MetaItem.MultiNodeItem -> nodes + } + +fun MetaItem.indexOf(meta: M): Int { + return when (this) { + is MetaItem.ValueItem -> -1 + is MetaItem.SingleNodeItem -> if (node == meta) 0 else -1 + is MetaItem.MultiNodeItem -> nodes.indexOf(meta) + } +} + /** * Generic meta-holder object */ diff --git a/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/MetaBuilder.kt b/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/MetaBuilder.kt index 7182c82e..c7f6724d 100644 --- a/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/MetaBuilder.kt +++ b/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/MetaBuilder.kt @@ -10,9 +10,20 @@ class MetaBuilder : MutableMetaNode() { override fun empty(): MetaBuilder = MetaBuilder() infix fun String.to(value: Any) { + if (value is Meta) { + this@MetaBuilder[this] = value + } this@MetaBuilder[this] = Value.of(value) } + infix fun String.to(meta: Meta) { + this@MetaBuilder[this] = meta + } + + infix fun String.to(value: Iterable) { + this@MetaBuilder[this] = value.toList() + } + infix fun String.to(metaBuilder: MetaBuilder.() -> Unit) { this@MetaBuilder[this] = MetaBuilder().apply(metaBuilder) } diff --git a/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/MetaUtils.kt b/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/MetaUtils.kt deleted file mode 100644 index ef8b8880..00000000 --- a/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/MetaUtils.kt +++ /dev/null @@ -1,40 +0,0 @@ -package hep.dataforge.meta - -/** - * Unsafe methods to access values and nodes directly from [MetaItem] - */ - -val MetaItem<*>.value - get() = (this as? MetaItem.ValueItem)?.value ?: error("Trying to interpret node meta item as value item") -val MetaItem<*>.string get() = value.string -val MetaItem<*>.boolean get() = value.boolean -val MetaItem<*>.number get() = value.number -val MetaItem<*>.double get() = number.toDouble() -val MetaItem<*>.int get() = number.toInt() -val MetaItem<*>.long get() = number.toLong() - -val MetaItem.node: M - get() = when (this) { - is MetaItem.ValueItem -> error("Trying to interpret value meta item as node item") - is MetaItem.SingleNodeItem -> node - is MetaItem.MultiNodeItem -> nodes.first() - } - -/** - * Utility method to access item content as list of nodes. - * Returns empty list if it is value item. - */ -val MetaItem.nodes: List - get() = when (this) { - is MetaItem.ValueItem -> emptyList()//error("Trying to interpret value meta item as node item") - is MetaItem.SingleNodeItem -> listOf(node) - is MetaItem.MultiNodeItem -> nodes - } - -fun MetaItem.indexOf(meta: M): Int { - return when (this) { - is MetaItem.ValueItem -> -1 - is MetaItem.SingleNodeItem -> if (node == meta) 0 else -1 - is MetaItem.MultiNodeItem -> nodes.indexOf(meta) - } -} \ No newline at end of file diff --git a/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/Serializers.kt b/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/Serializers.kt index 828056d7..1fd0a316 100644 --- a/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/Serializers.kt +++ b/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/Serializers.kt @@ -1,95 +1,206 @@ package hep.dataforge.meta -import kotlinx.serialization.* -import kotlinx.serialization.internal.SerialClassDescImpl +import kotlinx.serialization.json.* -@Serializer(forClass = Value::class) -object ValueSerializer : KSerializer { - override val serialClassDesc: KSerialClassDesc = SerialClassDescImpl("Value") - override fun load(input: KInput): Value { - val key = input.readByteValue() - return when (key.toChar()) { - 'S' -> StringValue(input.readStringValue()) - 'd' -> NumberValue(input.readDoubleValue()) - 'f' -> NumberValue(input.readFloatValue()) - 'i' -> NumberValue(input.readIntValue()) - 's' -> NumberValue(input.readShortValue()) - 'l' -> NumberValue(input.readLongValue()) - 'b' -> NumberValue(input.readByteValue()) - '+' -> True - '-' -> False - 'N' -> Null - 'L' -> { - val size = input.readIntValue() - val list = (0 until size).map { load(input) } - ListValue(list) - } - else -> error("Unknown value deserialization ket '$key'") +/*Universal serialization*/ + +//sealed class MetaItemProxy { +// +// @Serializable +// class NumberValueProxy(val number: Number) : MetaItemProxy() +// +// @Serializable +// class StringValueProxy(val string: String) : MetaItemProxy() +// +// @Serializable +// class BooleanValueProxy(val boolean: Boolean) : MetaItemProxy() +// +// @Serializable +// object NullValueProxy : MetaItemProxy() +// +// @Serializable +// class MetaProxy(@Serializable val map: Map) : MetaItemProxy() +// +// @Serializable +// class MetaListProxy(@Serializable val nodes: List) : MetaItemProxy() +//} +// +// +//fun Meta.toMap(): Map { +// return this.items.mapValues { (_, value) -> +// when (value) { +// is MetaItem.ValueItem -> when (value.value.type) { +// ValueType.NUMBER -> MetaItemProxy.NumberValueProxy(value.value.number) +// ValueType.STRING -> MetaItemProxy.StringValueProxy(value.value.string) +// ValueType.BOOLEAN -> MetaItemProxy.BooleanValueProxy(value.value.boolean) +// ValueType.NULL -> MetaItemProxy.NullValueProxy +// } +// is MetaItem.SingleNodeItem -> MetaItemProxy.MetaProxy(value.node.toMap()) +// is MetaItem.MultiNodeItem -> MetaItemProxy.MetaListProxy(value.nodes.map { MetaItemProxy.MetaProxy(it.toMap()) }) +// } +// } +//} + + +/*Direct JSON serialization*/ + +fun Value.toJson(): JsonElement = if (isList()) { + JsonArray(list.map { it.toJson() }) +} else { + when (type) { + ValueType.NUMBER -> JsonPrimitive(number) + ValueType.STRING -> JsonPrimitive(string) + ValueType.BOOLEAN -> JsonPrimitive(boolean) + ValueType.NULL -> JsonNull + } +} + +fun Meta.toJSON(): JsonObject { + val map = this.items.mapValues { (_, value) -> + when (value) { + is MetaItem.ValueItem -> value.value.toJson() + is MetaItem.SingleNodeItem -> value.node.toJSON() + is MetaItem.MultiNodeItem -> JsonArray(value.nodes.map { it.toJSON() }) } } + return JsonObject(map) +} - override fun save(output: KOutput, obj: Value) { - when (obj.type) { - ValueType.NUMBER -> { - val number = obj.number - when (number) { - is Float -> { - output.writeByteValue('f'.toByte()) - output.writeFloatValue(number) - } - is Short -> { - output.writeByteValue('s'.toByte()) - output.writeShortValue(number) - } - is Int -> { - output.writeByteValue('i'.toByte()) - output.writeIntValue(number) - } - is Long -> { - output.writeByteValue('l'.toByte()) - output.writeLongValue(number) - } - is Byte -> { - output.writeByteValue('b'.toByte()) - output.writeByteValue(number) - } - is Double -> { - output.writeByteValue('d'.toByte()) - output.writeDoubleValue(number) - } - else -> { - //TODO add warning - output.writeByteValue('d'.toByte()) - output.writeDoubleValue(number.toDouble()) - } +fun JsonPrimitive.toValue(): Value { + return when (this) { + is JsonLiteral -> LazyParsedValue(content) + is JsonNull -> Null + } +} + +fun JsonObject.toMeta(): Meta { + return buildMeta { + this@toMeta.forEach { (key, value) -> + when (value) { + is JsonPrimitive -> set(key, value.toValue()) + is JsonObject -> set(key, value.toMeta()) + is JsonArray -> if (value.all { it is JsonPrimitive }) { + set(key, ListValue(value.map { (it as JsonPrimitive).toValue() })) + } else { + set( + key, + value.map { + if (it is JsonObject) { + it.toMeta() + } else { + buildMeta { "@value" to it.primitive.toValue() } + } + } + ) } } - ValueType.STRING -> { - output.writeByteValue('S'.toByte()) - output.writeStringValue(obj.string) - } - ValueType.BOOLEAN -> if (obj.boolean) { - output.writeByteValue('+'.toByte()) - } else { - output.writeByteValue('-'.toByte()) - } - ValueType.NULL -> output.writeByteValue('N'.toByte()) } } } +/*Direct CBOR serialization*/ -//@Serializer(forClass = Meta::class) -//object MetaSerializer: KSerializer{ -// override val serialClassDesc: KSerialClassDesc = SerialClassDescImpl("Meta") -// -// override fun load(input: KInput): Meta { -// +//fun Meta.toBinary(out: OutputStream) { +// fun CBOR.CBOREncoder.encodeChar(char: Char) { +// encodeNumber(char.toByte().toLong()) // } // -// override fun save(output: KOutput, obj: Meta) { -// NamedValueOutput() +// fun CBOR.CBOREncoder.encodeValue(value: Value) { +// if (value.isList()) { +// encodeChar('L') +// startArray() +// value.list.forEach { +// encodeValue(it) +// } +// end() +// } else when (value.type) { +// ValueType.NUMBER -> when (value.value) { +// is Int, is Short, is Long -> { +// encodeChar('i') +// encodeNumber(value.number.toLong()) +// } +// is Float -> { +// encodeChar('f') +// encodeFloat(value.number.toFloat()) +// } +// else -> { +// encodeChar('d') +// encodeDouble(value.number.toDouble()) +// } +// } +// ValueType.STRING -> { +// encodeChar('S') +// encodeString(value.string) +// } +// ValueType.BOOLEAN -> { +// if (value.boolean) { +// encodeChar('+') +// } else { +// encodeChar('-') +// } +// } +// ValueType.NULL -> { +// encodeChar('N') +// } +// } +// } +// +// fun CBOR.CBOREncoder.encodeMeta(meta: Meta) { +// meta.items.forEach { (key, item) -> +// this.startMap() +// encodeString(key) +// when (item) { +// is MetaItem.ValueItem -> { +// encodeChar('V') +// encodeValue(item.value) +// } +// is MetaItem.SingleNodeItem -> { +// startArray() +// encodeMeta(item.node) +// } +// is MetaItem.MultiNodeItem -> { +// startArray() +// item.nodes.forEach { +// encodeMeta(it) +// } +// end() +// } +// } +// } +// } +// +// +// CBOR.CBOREncoder(out).apply { +// encodeMeta(this@toBinary) +// } +//} +// +//fun InputStream.readBinaryMeta(): Meta { +// fun CBOR.CBORDecoder.nextChar(): Char = nextNumber().toByte().toChar() +// +// fun CBOR.CBORDecoder.nextValue(): Value { +// val key = nextChar() +// return when(key){ +// 'L' -> { +// val size = startArray() +// val res = (0 until size).map { nextValue() } +// end() +// ListValue(res) +// } +// 'S' -> StringValue(nextString()) +// 'N' -> Null +// '+' -> True +// '-' -> False +// 'i' -> NumberValue(nextNumber()) +// 'f' -> NumberValue(nextFloat()) +// 'd' -> NumberValue(nextDouble()) +// else -> error("Unknown binary key: $key") +// } +// } +// +// fun CBOR.CBORDecoder.nextMeta(): Meta{ +// // } // //} \ No newline at end of file diff --git a/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/Value.kt b/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/Value.kt index fb7f62e5..53c5a8f3 100644 --- a/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/Value.kt +++ b/dataforge-meta-common/src/main/kotlin/hep/dataforge/meta/Value.kt @@ -1,7 +1,5 @@ package hep.dataforge.meta -import kotlinx.serialization.Serializable - /** * The list of supported Value types. @@ -18,7 +16,6 @@ enum class ValueType { * * Value can represent a list of value objects. */ -@Serializable(with = ValueSerializer::class) interface Value { /** * Get raw value of this value @@ -69,10 +66,10 @@ interface Value { * A singleton null value */ object Null : Value { - override val value: Any? = null - override val type: ValueType = ValueType.NULL - override val number: Number = Double.NaN - override val string: String = "@null" + override val value: Any? get() = null + override val type: ValueType get() = ValueType.NULL + override val number: Number get() = Double.NaN + override val string: String get() = "@null" } /** @@ -85,40 +82,60 @@ fun Value.isNull(): Boolean = this == Null * Singleton true value */ object True : Value { - override val value: Any? = true - override val type: ValueType = ValueType.BOOLEAN - override val number: Number = 1.0 - override val string: String = "+" + override val value: Any? get() = true + override val type: ValueType get() = ValueType.BOOLEAN + override val number: Number get() = 1.0 + override val string: String get() = "+" } /** * Singleton false value */ object False : Value { - override val value: Any? = false - override val type: ValueType = ValueType.BOOLEAN - override val number: Number = -1.0 - override val string: String = "-" + override val value: Any? get() = false + override val type: ValueType get() = ValueType.BOOLEAN + override val number: Number get() = -1.0 + override val string: String get() = "-" } val Value.boolean get() = this == True || this.list.firstOrNull() == True || (type == ValueType.STRING && string.toBoolean()) class NumberValue(override val number: Number) : Value { override val value: Any? get() = number - override val type: ValueType = ValueType.NUMBER + override val type: ValueType get() = ValueType.NUMBER override val string: String get() = number.toString() + + override fun equals(other: Any?): Boolean { + return this.number == (other as? Value)?.number + } + + override fun hashCode(): Int = number.hashCode() + + } class StringValue(override val string: String) : Value { override val value: Any? get() = string - override val type: ValueType = ValueType.STRING + override val type: ValueType get() = ValueType.STRING override val number: Number get() = string.toDouble() + + override fun equals(other: Any?): Boolean { + return this.string == (other as? Value)?.string + } + + override fun hashCode(): Int = string.hashCode() } class EnumValue>(override val value: E) : Value { - override val type: ValueType = ValueType.STRING - override val number: Number = value.ordinal - override val string: String = value.name + override val type: ValueType get() = ValueType.STRING + override val number: Number get() = value.ordinal + override val string: String get() = value.name + + override fun equals(other: Any?): Boolean { + return string == (other as? Value)?.string + } + + override fun hashCode(): Int = value.hashCode() } class ListValue(override val list: List) : Value { @@ -148,6 +165,7 @@ fun String.asValue(): Value = StringValue(this) fun Collection.asValue(): Value = ListValue(this.toList()) + /** * Create Value from String using closest match conversion */ @@ -181,4 +199,15 @@ fun String.parseValue(): Value { //Give up and return a StringValue return StringValue(this) +} + +class LazyParsedValue(override val string: String): Value{ + private val parsedValue by lazy { string.parseValue() } + + override val value: Any? + get() = parsedValue.value + override val type: ValueType + get() = parsedValue.type + override val number: Number + get() = parsedValue.number } \ No newline at end of file diff --git a/dataforge-meta-common/src/main/kotlin/hep/dataforge/names/Name.kt b/dataforge-meta-common/src/main/kotlin/hep/dataforge/names/Name.kt index 6ac98d8d..71c61379 100644 --- a/dataforge-meta-common/src/main/kotlin/hep/dataforge/names/Name.kt +++ b/dataforge-meta-common/src/main/kotlin/hep/dataforge/names/Name.kt @@ -1,6 +1,5 @@ package hep.dataforge.names -import kotlin.coroutines.experimental.buildSequence /** * The general interface for working with names. @@ -75,7 +74,7 @@ data class NameToken internal constructor(val body: String, val query: String) { } fun String.toName(): Name { - val tokens = buildSequence { + val tokens = sequence { var bodyBuilder = StringBuilder() var queryBuilder = StringBuilder() var bracketCount: Int = 0 diff --git a/dataforge-meta-common/src/test/kotlin/hep/dataforge/meta/SerializationTest.kt b/dataforge-meta-common/src/test/kotlin/hep/dataforge/meta/SerializationTest.kt index f4e87580..b1e28ab7 100644 --- a/dataforge-meta-common/src/test/kotlin/hep/dataforge/meta/SerializationTest.kt +++ b/dataforge-meta-common/src/test/kotlin/hep/dataforge/meta/SerializationTest.kt @@ -1,14 +1,12 @@ -package scientifik.kplot.remote +package hep.dataforge.meta -import hep.dataforge.meta.buildMeta -import hep.dataforge.meta.get -import hep.dataforge.meta.value -import kotlinx.serialization.json.JSON import kotlin.test.Test +import kotlin.test.assertEquals + +class SerializationTest { -class SerializationTest{ @Test - fun testMetaSerialization(){ + fun testJSONSerialization() { val meta = buildMeta { "a" to 2 "b" to { @@ -16,7 +14,39 @@ class SerializationTest{ "d" to 2.2 } } - val json = JSON.stringify(meta["a"]?.value!!) + val json = meta.toJSON() println(json) + val result = json.toMeta() + assertEquals(meta, result) } + +// @Test +// fun testIndirectSerialization() { +// val meta = buildMeta { +// "a" to 2 +// "b" to { +// "c" to "ddd" +// "d" to 2.2 +// } +// } +// val json = JSON.stringify(meta.toMap()) +// println(json) +//// val result = json.toMeta() +//// assertEquals(meta, result) +// } + +// @Test +// fun testWeirdSerialization() { +// val meta = buildMeta { +// "a" to 2 +// "b" to { +// "c" to "ddd" +// "d" to 2.2 +// } +// } +// val json = JSON.stringify(meta.toJSON()) +// println(json) +// val result: JsonObject = JSON.parse(json) +// assertEquals(meta, result.toMeta()) +// } } \ No newline at end of file diff --git a/dataforge-meta-js/build.gradle b/dataforge-meta-js/build.gradle index 72701abb..f884412d 100644 --- a/dataforge-meta-js/build.gradle +++ b/dataforge-meta-js/build.gradle @@ -1,6 +1,5 @@ -plugins { +plugins{ id 'kotlin-platform-js' - //id 'kotlinx-serialization' } dependencies { diff --git a/dataforge-meta-jvm/build.gradle b/dataforge-meta-jvm/build.gradle index 872ba285..f371911a 100644 --- a/dataforge-meta-jvm/build.gradle +++ b/dataforge-meta-jvm/build.gradle @@ -1,15 +1,15 @@ -plugins { +plugins{ id 'kotlin-platform-jvm' - id 'kotlinx-serialization' } dependencies { expectedBy project(":dataforge-meta-common") compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version" + compile "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version" compile "org.jetbrains.kotlinx:kotlinx-serialization-runtime:$serialization_version" testCompile "org.jetbrains.kotlin:kotlin-test" - testCompile "org.jetbrains.kotlin:kotlin-test-junit5" + testCompile "org.jetbrains.kotlin:kotlin-test-junit" } compileKotlin {