Fix attachment of children on Vision deserialization

This commit is contained in:
Alexander Nozik 2020-12-06 20:00:34 +03:00
parent a85cd828e6
commit face7bfd0c
8 changed files with 49 additions and 16 deletions

View File

@ -0,0 +1,17 @@
package ru.mipt.npm.sat
import hep.dataforge.context.Global
import hep.dataforge.vision.solid.SolidManager
import kotlin.test.Test
import kotlin.test.assertEquals
class GeometrySerializationTest {
@Test
fun testSerialization(){
val geometry = visionOfSatellite()
val manager = Global.plugins.fetch(SolidManager)
val string = manager.visionManager.encodeToString(geometry)
val reconstructed = manager.visionManager.decodeFromString(string)
assertEquals(geometry.config,reconstructed.config)
}
}

View File

@ -10,7 +10,6 @@ import hep.dataforge.provider.Type
import hep.dataforge.values.asValue
import hep.dataforge.vision.Vision.Companion.TYPE
import hep.dataforge.vision.Vision.Companion.VISIBLE_KEY
import kotlinx.serialization.PolymorphicSerializer
import kotlinx.serialization.Transient
/**
@ -75,8 +74,6 @@ public interface Vision : Configurable, Described {
public const val TYPE: String = "vision"
public val STYLE_KEY: Name = "@style".asName()
public fun serializer(): PolymorphicSerializer<Vision> = PolymorphicSerializer(Vision::class)
public val VISIBLE_KEY: Name = "visible".asName()
}
}

View File

@ -3,6 +3,7 @@ package hep.dataforge.vision
import hep.dataforge.context.*
import hep.dataforge.meta.*
import hep.dataforge.meta.descriptors.NodeDescriptor
import kotlinx.serialization.PolymorphicSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.modules.SerializersModule
@ -24,17 +25,24 @@ public class VisionManager(meta: Meta) : AbstractPlugin(meta) {
}
}
public val jsonFormat: Json
private val jsonFormat: Json
get() = Json(defaultJson) {
serializersModule = this@VisionManager.serializersModule
}
public fun decodeFromString(string: String): Vision = jsonFormat.decodeFromString(Vision.serializer(), string)
public fun encodeToString(vision: Vision): String = jsonFormat.encodeToString(Vision.serializer(), vision)
public fun decodeFromString(string: String): Vision = jsonFormat.decodeFromString(visionSerializer, string).also {
(it as? VisionGroup)?.attachChildren()
}
public fun encodeToString(vision: Vision): String = jsonFormat.encodeToString(visionSerializer, vision)
public fun decodeFromJson(json: JsonElement): Vision =
jsonFormat.decodeFromJsonElement(visionSerializer, json).also {
(it as? VisionGroup)?.attachChildren()
}
public fun decodeFromJson(json: JsonElement): Vision = jsonFormat.decodeFromJsonElement(Vision.serializer(), json)
public fun encodeToJsonElement(vision: Vision): JsonElement =
jsonFormat.encodeToJsonElement(Vision.serializer(), vision)
jsonFormat.encodeToJsonElement(visionSerializer, vision)
//TODO remove double transformation with dedicated Meta serial format
public fun decodeFromMeta(meta: Meta, descriptor: NodeDescriptor? = null): Vision =
@ -67,5 +75,7 @@ public class VisionManager(meta: Meta) : AbstractPlugin(meta) {
encodeDefaults = false
ignoreUnknownKeys = true
}
internal val visionSerializer: PolymorphicSerializer<Vision> = PolymorphicSerializer(Vision::class)
}
}

View File

@ -5,6 +5,7 @@ import hep.dataforge.meta.descriptors.NodeDescriptor
import hep.dataforge.names.Name
import hep.dataforge.names.isEmpty
import hep.dataforge.names.plus
import hep.dataforge.vision.VisionManager.Companion.visionSerializer
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
@ -54,10 +55,13 @@ public abstract class EmptyVision : Vision {
@SerialName("vision.null")
public object NullVision : EmptyVision()
/**
* Serialization proxy is used to create immutable reference for a given vision
*/
@Serializable(VisionSerializationProxy.Companion::class)
private class VisionSerializationProxy(val ref: Vision) : EmptyVision() {
companion object : KSerializer<VisionSerializationProxy> {
override val descriptor: SerialDescriptor = Vision.serializer().descriptor
override val descriptor: SerialDescriptor = visionSerializer.descriptor
@OptIn(ExperimentalSerializationApi::class)
override fun serialize(encoder: Encoder, value: VisionSerializationProxy) {
@ -67,7 +71,7 @@ private class VisionSerializationProxy(val ref: Vision) : EmptyVision() {
}
override fun deserialize(decoder: Decoder): VisionSerializationProxy =
VisionSerializationProxy(Vision.serializer().deserialize(decoder))
VisionSerializationProxy(visionSerializer.deserialize(decoder))
}
}

View File

@ -47,14 +47,17 @@ public class VisionClient : AbstractPlugin() {
if (!element.classList.contains(HtmlOutputScope.OUTPUT_CLASS)) error("The element $element is not an output element")
val endpoint = resolveEndpoint(element)
console.info("Vision server is resolved to $endpoint")
val fetchUrl = URL(endpoint).apply {
searchParams.append("name", name)
pathname += "/vision"
}
console.info("Fetching vision data from $fetchUrl")
window.fetch(fetchUrl).then { response ->
if (response.ok) {
response.text().then { text ->
val vision = visionManager.jsonFormat.decodeFromString(Vision.serializer(), text)
val vision = visionManager.decodeFromString(text)
val renderer = findRendererFor(vision) ?: error("Could nof find renderer for $vision")
renderer.render(element, vision)
@ -68,7 +71,7 @@ public class VisionClient : AbstractPlugin() {
onmessage = { messageEvent ->
val stringData: String? = messageEvent.data as? String
if (stringData != null) {
val update = visionManager.jsonFormat.decodeFromString(Vision.serializer(), text)
val update = visionManager.decodeFromString(text)
vision.update(update)
} else {
console.error("WebSocket message data is not a string")

View File

@ -130,7 +130,7 @@ public class VisionServer internal constructor(
outgoing.send(Frame.Text(json))
}
} catch (ex: Exception) {
application.log.debug("Closed server socket for $name")
application.log.debug("Closed server socket for $name with exception $ex")
}
}
//Plots in their json representation

View File

@ -6,6 +6,7 @@ import hep.dataforge.names.Name
import hep.dataforge.names.NameToken
import hep.dataforge.vision.*
import kotlinx.serialization.KSerializer
import kotlinx.serialization.PolymorphicSerializer
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.builtins.MapSerializer
@ -126,7 +127,7 @@ internal class Prototypes(
private val mapSerializer: KSerializer<Map<NameToken, Vision>> =
MapSerializer(
NameToken.serializer(),
Vision.serializer()
PolymorphicSerializer(Vision::class)
)
override val descriptor: SerialDescriptor get() = mapSerializer.descriptor

View File

@ -9,6 +9,7 @@ import hep.dataforge.names.Name
import hep.dataforge.names.toName
import hep.dataforge.vision.*
import hep.dataforge.vision.VisionManager.Companion.VISION_SERIALIZER_MODULE_TARGET
import kotlinx.serialization.PolymorphicSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.modules.PolymorphicModuleBuilder
import kotlinx.serialization.modules.SerializersModule
@ -64,9 +65,9 @@ public class SolidManager(meta: Meta) : AbstractPlugin(meta) {
serializersModule = serializersModuleForSolids
}
public fun encodeToString(solid: Solid): String = jsonForSolids.encodeToString(Vision.serializer(), solid)
internal fun encodeToString(solid: Solid): String = jsonForSolids.encodeToString(PolymorphicSerializer(Vision::class), solid)
public fun decodeFromString(str: String): Vision = jsonForSolids.decodeFromString(Vision.serializer(), str).also {
internal fun decodeFromString(str: String): Vision = jsonForSolids.decodeFromString(PolymorphicSerializer(Vision::class), str).also {
if(it is VisionGroup){
it.attachChildren()
}