com.lightningkite.lightningdb.helpers.kt Maven / Gradle / Ivy
package com.lightningkite.lightningdb
import com.mongodb.client.model.changestream.UpdateDescription
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.KSerializer
import kotlinx.serialization.internal.GeneratedSerializer
import org.bson.*
import org.bson.codecs.Codec
import org.bson.codecs.DecoderContext
import org.bson.codecs.EncoderContext
import org.bson.codecs.configuration.CodecRegistry
import java.util.*
import kotlin.reflect.KProperty1
import kotlin.reflect.typeOf
fun BsonValue.setPath(path: String, value: BsonValue) {
val pathParts = path.split('.')
var current: BsonValue = this
for (partIndex in 0 until pathParts.lastIndex) {
when (current) {
is BsonDocument -> current = current[pathParts[partIndex]] ?: return
is BsonArray -> current = current[pathParts[partIndex].toInt()] ?: return
}
}
when (current) {
is BsonDocument -> current[pathParts.last()] = value
is BsonArray -> {
val index = pathParts.last().toInt()
if (index > current.lastIndex)
current.add(value)
else
current[index] = value
}
}
}
fun BsonValue.removePath(path: String) {
val pathParts = path.split('.')
var current: BsonValue = this
for (partIndex in 0 until pathParts.lastIndex) {
when (current) {
is BsonDocument -> current = current[pathParts[partIndex]] ?: return
is BsonArray -> current = current[pathParts[partIndex].toInt()] ?: return
}
}
when (current) {
is BsonDocument -> current.remove(pathParts.last())
is BsonArray -> current.removeAt(pathParts.last().toInt())
}
}
fun Codec.fromUpdateDescription(on: T, updateDescription: UpdateDescription): T {
val doc = BsonDocument()
val writer = BsonDocumentWriter(doc)
this.encode(writer, on, EncoderContext.builder().build())
updateDescription.removedFields?.forEach { removal ->
doc.removePath(removal)
}
updateDescription.updatedFields?.forEach { update ->
doc.setPath(update.key, update.value)
}
return this.decode(BsonDocumentReader(doc), DecoderContext.builder().build())
}
fun Codec.fromDocument(doc: Document, registry: CodecRegistry): T {
return this.decode(BsonDocumentReader(BsonDocumentWrapper.asBsonDocument(doc, registry)), DecoderContext.builder().build())
}
val DataClassPathPartial<*>.mongo: String get() = properties.joinToString(".") { it.name }
@Suppress("UNCHECKED_CAST")
@OptIn(InternalSerializationApi::class)
fun KSerializer.fieldSerializer(path: DataClassPath): KSerializer {
var current:KSerializer<*> = this
path.properties.forEach {
current = ((current.nullElement() ?: current) as KSerializer).fieldSerializer(it as KProperty1) as KSerializer<*>
}
return current as KSerializer
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy