Add encoding and decoding to/from entity by json encoding/decoding
This commit is contained in:
parent
5da1559882
commit
f77f6b7211
@ -52,5 +52,7 @@ include(
|
|||||||
":controls-magix-client",
|
":controls-magix-client",
|
||||||
":motors",
|
":motors",
|
||||||
":controls-xodus",
|
":controls-xodus",
|
||||||
":controls-mongo"
|
":controls-mongo",
|
||||||
|
":xodus-serialization"
|
||||||
)
|
)
|
||||||
|
include("xodus-serialization")
|
||||||
|
20
xodus-serialization/build.gradle.kts
Normal file
20
xodus-serialization/build.gradle.kts
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
plugins {
|
||||||
|
id("ru.mipt.npm.gradle.jvm")
|
||||||
|
`maven-publish`
|
||||||
|
}
|
||||||
|
|
||||||
|
val xodusVersion = "1.3.232"
|
||||||
|
|
||||||
|
kscience {
|
||||||
|
useSerialization {
|
||||||
|
json()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(projects.magix.magixApi)
|
||||||
|
implementation(projects.controlsCore)
|
||||||
|
implementation("org.jetbrains.xodus:xodus-entity-store:$xodusVersion")
|
||||||
|
implementation("org.jetbrains.xodus:xodus-environment:$xodusVersion")
|
||||||
|
implementation("org.jetbrains.xodus:xodus-vfs:$xodusVersion")
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
package ru.mipt.npm.xodus.serialization.json
|
||||||
|
|
||||||
|
import jetbrains.exodus.entitystore.Entity
|
||||||
|
import jetbrains.exodus.entitystore.StoreTransaction
|
||||||
|
import kotlinx.serialization.DeserializationStrategy
|
||||||
|
import kotlinx.serialization.json.*
|
||||||
|
import kotlinx.serialization.serializer
|
||||||
|
|
||||||
|
internal fun StoreTransaction.decodeFromEntity(entity: Entity): JsonElement = buildJsonObject {
|
||||||
|
entity.propertyNames.forEach { property ->
|
||||||
|
entity.getProperty(property).let { value ->
|
||||||
|
when (value) {
|
||||||
|
is Number -> put(property, value)
|
||||||
|
is Boolean -> put(property, value)
|
||||||
|
is String -> put(property, value)
|
||||||
|
else -> throw IllegalStateException("Unsupported type for primitive field")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
entity.linkNames.forEach { link ->
|
||||||
|
entity.getLinks(link).let { entities ->
|
||||||
|
when (entities.size()) {
|
||||||
|
1L -> entities.first?.let { put(link, decodeFromEntity(it)) }
|
||||||
|
else -> {
|
||||||
|
putJsonArray(link) {
|
||||||
|
entities.forEach {
|
||||||
|
add(decodeFromEntity(it))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun <T> StoreTransaction.decodeFromEntity(entity: Entity, deserializer: DeserializationStrategy<T>): T {
|
||||||
|
val jsonElement = decodeFromEntity(entity)
|
||||||
|
return Json.decodeFromJsonElement(deserializer, jsonElement)
|
||||||
|
}
|
||||||
|
|
||||||
|
public inline fun <reified T> StoreTransaction.decodeFromEntity(entity: Entity): T = decodeFromEntity(entity, serializer())
|
@ -0,0 +1,58 @@
|
|||||||
|
package ru.mipt.npm.xodus.serialization.json
|
||||||
|
|
||||||
|
import jetbrains.exodus.entitystore.Entity
|
||||||
|
import jetbrains.exodus.entitystore.StoreTransaction
|
||||||
|
import kotlinx.serialization.SerializationStrategy
|
||||||
|
import kotlinx.serialization.json.*
|
||||||
|
import kotlinx.serialization.serializer
|
||||||
|
|
||||||
|
internal fun StoreTransaction.encodeToEntity(jsonElement: JsonElement, entity: Entity) {
|
||||||
|
when (jsonElement) {
|
||||||
|
is JsonPrimitive -> throw IllegalStateException("Can't serialize primitive value to entity")
|
||||||
|
is JsonArray -> throw IllegalStateException("Can't serialize array value to entity")
|
||||||
|
is JsonObject -> {
|
||||||
|
jsonElement.forEach { entry ->
|
||||||
|
entry.value.let { value ->
|
||||||
|
when(value) {
|
||||||
|
is JsonPrimitive -> {
|
||||||
|
if (value.isString) {
|
||||||
|
entity.setProperty(entry.key, value.content)
|
||||||
|
} else {
|
||||||
|
(value.longOrNull ?: value.doubleOrNull ?: value.booleanOrNull)?.let {
|
||||||
|
entity.setProperty(
|
||||||
|
entry.key,
|
||||||
|
it
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// считаем, что все элементы массива - JsonObject, иначе не можем напрямую сериализовать (надо придывать костыли???)
|
||||||
|
is JsonArray -> {
|
||||||
|
value.forEach { element ->
|
||||||
|
val childEntity = newEntity("${entity.type}.${entry.key}")
|
||||||
|
encodeToEntity(element, childEntity)
|
||||||
|
entity.addLink(entry.key, childEntity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
is JsonObject -> {
|
||||||
|
val childEntity = newEntity("${entity.type}.${entry.key}")
|
||||||
|
encodeToEntity(value, childEntity)
|
||||||
|
entity.setLink(entry.key, childEntity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun <T> StoreTransaction.encodeToEntity(serializer: SerializationStrategy<T>, value: T, entityType: String): Entity {
|
||||||
|
val entity: Entity = newEntity(entityType)
|
||||||
|
encodeToEntity(Json.encodeToJsonElement(serializer, value), entity)
|
||||||
|
return entity
|
||||||
|
}
|
||||||
|
|
||||||
|
public inline fun <reified T> StoreTransaction.encodeToEntity(value: T, entityType: String): Entity =
|
||||||
|
encodeToEntity(serializer(), value, entityType)
|
@ -0,0 +1,39 @@
|
|||||||
|
package ru.mipt.npm.xodus.serialization.json
|
||||||
|
|
||||||
|
import jetbrains.exodus.entitystore.PersistentEntityStores
|
||||||
|
import kotlinx.datetime.Instant
|
||||||
|
import kotlinx.serialization.json.JsonObject
|
||||||
|
import kotlinx.serialization.json.JsonPrimitive
|
||||||
|
import ru.mipt.npm.controls.api.PropertyChangedMessage
|
||||||
|
import ru.mipt.npm.magix.api.MagixMessage
|
||||||
|
import space.kscience.dataforge.meta.Meta
|
||||||
|
import space.kscience.dataforge.names.Name
|
||||||
|
import java.nio.file.Paths
|
||||||
|
|
||||||
|
internal fun main() {
|
||||||
|
val expectedMessage = MagixMessage(
|
||||||
|
"dataforge",
|
||||||
|
"dataforge",
|
||||||
|
PropertyChangedMessage(
|
||||||
|
"acceleration",
|
||||||
|
Meta {
|
||||||
|
"x" put 3.0
|
||||||
|
"y" put 9.0
|
||||||
|
},
|
||||||
|
Name.parse("virtual-car"),
|
||||||
|
Name.parse("magix-virtual-car"),
|
||||||
|
time = Instant.fromEpochMilliseconds(1337)
|
||||||
|
),
|
||||||
|
"magix-virtual-car",
|
||||||
|
user = JsonObject(content = mapOf(Pair("name", JsonPrimitive("SCADA"))))
|
||||||
|
)
|
||||||
|
|
||||||
|
val entityStore = PersistentEntityStores.newInstance(Paths.get("xodus_serialization").toString())
|
||||||
|
entityStore.executeInTransaction { txn ->
|
||||||
|
txn.encodeToEntity(expectedMessage, "MagixMessage")
|
||||||
|
}
|
||||||
|
|
||||||
|
entityStore.executeInTransaction { txn ->
|
||||||
|
txn.getAll("MagixMessage").first?.let { println(txn.decodeFromEntity<MagixMessage<PropertyChangedMessage>>(it) == expectedMessage) }
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user