jvmMain.extensions.MongoDatabase.kt Maven / Gradle / Ivy
package io.fluidsonic.raptor.mongo
import io.fluidsonic.mongo.*
import io.fluidsonic.raptor.bson.*
import kotlin.reflect.*
import org.bson.*
import org.bson.codecs.*
import org.bson.codecs.configuration.*
public inline fun MongoDatabase.getCollectionOfGeneric(name: String): MongoCollection =
getCollectionOfGeneric(name = name, type = typeOf())
@Suppress("UNCHECKED_CAST")
public fun MongoDatabase.getCollectionOfGeneric(name: String, type: KType): MongoCollection {
val documentClass = type.classifier as KClass<*> as KClass
val arguments = type.arguments
return when {
arguments.isEmpty() -> getCollection(name, documentClass = documentClass)
else -> getCollection(name = name, documentClass = GenericBsonCodec::class)
.withCodecRegistry(CodecRegistries.fromRegistries(
CodecRegistries.fromCodecs(GenericBsonCodec(
documentCodec = codecRegistry.get(documentClass.java)
.let { codec ->
codec as? CodecEx ?: error("Codec ${codec::class} does not support decoding generic type $type.")
},
arguments = arguments,
)),
codecRegistry,
))
.let { it as MongoCollection }
}
}
private class GenericBsonCodec(
private val documentCodec: CodecEx,
private val arguments: List,
) : Codec {
override fun encode(writer: BsonWriter, value: TDocument, encoderContext: EncoderContext) {
error("Cannot encode value: ${value::class}")
}
@Suppress("UNCHECKED_CAST")
override fun getEncoderClass(): Class =
GenericBsonCodec::class.java as Class
override fun decode(reader: BsonReader, decoderContext: DecoderContext): TDocument =
documentCodec.decode(reader = reader, decoderContext = decoderContext, arguments = arguments)
}