Add Connection and refactoring EntityCollection
This commit is contained in:
40
src/main/kotlin/fr/postgresjson/connexion/Connection.kt
Normal file
40
src/main/kotlin/fr/postgresjson/connexion/Connection.kt
Normal file
@@ -0,0 +1,40 @@
|
||||
package fr.postgresjson.connexion
|
||||
|
||||
import com.github.jasync.sql.db.pool.ConnectionPool
|
||||
import com.github.jasync.sql.db.postgresql.PostgreSQLConnection
|
||||
import com.github.jasync.sql.db.postgresql.PostgreSQLConnectionBuilder
|
||||
import fr.postgresjson.entity.EntityI
|
||||
import fr.postgresjson.serializer.Serializer
|
||||
|
||||
|
||||
class Connection(
|
||||
private val host: String = "localhost",
|
||||
private val port: Int = 5432,
|
||||
private val database: String = "dc-project",
|
||||
private val username: String = "dc-project",
|
||||
private val password: String = "dc-project"
|
||||
) {
|
||||
private lateinit var connection: ConnectionPool<PostgreSQLConnection>
|
||||
val serializer = Serializer()
|
||||
|
||||
fun connect(): ConnectionPool<PostgreSQLConnection> {
|
||||
if (!::connection.isInitialized || !connection.isConnected()) {
|
||||
connection = PostgreSQLConnectionBuilder.createConnectionPool(
|
||||
"jdbc:postgresql://$host:$port/$database?user=$username&password=$password"
|
||||
)
|
||||
}
|
||||
return connection
|
||||
}
|
||||
|
||||
inline fun <T, reified R :EntityI<T?>> execute(sql: String, values: List<Any?> = emptyList()): R? {
|
||||
val future = connect().sendPreparedStatement(sql, values)
|
||||
val json = future.get().rows[0].getString(0)
|
||||
if (json === null) {
|
||||
return null
|
||||
} else {
|
||||
val obj = serializer.deserialize<T, R>(json)
|
||||
|
||||
return obj
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,11 @@ package fr.postgresjson.entity
|
||||
import java.util.*
|
||||
|
||||
interface EntityI<T> {
|
||||
var id: T
|
||||
var id: T?
|
||||
}
|
||||
abstract class Entity<T>(override var id: T) : EntityI<T>
|
||||
abstract class UuidEntity(override var id: UUID = UUID.randomUUID()) : Entity<UUID>(id)
|
||||
abstract class IdEntity(override var id: Int) : Entity<Int>(id)
|
||||
abstract class Entity<T>(override var id: T? = null) : EntityI<T?>
|
||||
abstract class UuidEntity(override var id: UUID? = UUID.randomUUID()) : Entity<UUID?>(id)
|
||||
abstract class IdEntity(override var id: Int? = null) : Entity<Int?>(id)
|
||||
|
||||
interface EntityVersioning<T> {
|
||||
var version: T
|
||||
|
||||
@@ -1,13 +1,36 @@
|
||||
package fr.postgresjson.entity
|
||||
|
||||
class EntityCollection<T, E : EntityI<T>> {
|
||||
var collection: MutableMap<T, E> = mutableMapOf()
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
fun get(id: T): E? {
|
||||
return collection[id]
|
||||
class EntityCollection {
|
||||
val collections: MutableMap<KClass<*>, EntityCollection<Any, EntityI<Any?>>> = mutableMapOf()
|
||||
|
||||
inline fun <I, reified R : EntityI<I?>> get(id: I): R? {
|
||||
val collection = collections[R::class]
|
||||
val entity = collection?.get(id!!)
|
||||
return entity as R?
|
||||
}
|
||||
|
||||
fun set(entity: E) {
|
||||
collection.set(entity.id, entity)
|
||||
inline fun <I, reified R : EntityI<I?>> set(entity: R) {
|
||||
if (collections[R::class] == null) {
|
||||
collections[R::class] = EntityCollection()
|
||||
}
|
||||
|
||||
collections[R::class]!!.set(entity as EntityI<Any?>)
|
||||
}
|
||||
|
||||
class EntityCollection<T, E : EntityI<T?>> {
|
||||
private var collection: MutableMap<T, E> = mutableMapOf()
|
||||
|
||||
fun get(id: T): E? {
|
||||
return collection[id]
|
||||
}
|
||||
|
||||
fun set(entity: E) {
|
||||
val id = entity.id
|
||||
if (id !== null) {
|
||||
collection[id] = entity
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +1,23 @@
|
||||
package fr.postgresjson.repository
|
||||
|
||||
import com.github.jasync.sql.db.pool.ConnectionPool
|
||||
import com.github.jasync.sql.db.postgresql.PostgreSQLConnection
|
||||
import fr.postgresjson.entity.EntityCollection
|
||||
import fr.postgresjson.entity.EntityI
|
||||
import fr.postgresjson.serializer.Serializer
|
||||
import kotlin.reflect.KClass
|
||||
|
||||
interface RepositoryI<T, E : EntityI<T>>
|
||||
|
||||
abstract class Repository<T, E : EntityI<T>> : RepositoryI<T, E> {
|
||||
private val collections: MutableMap<KClass<*>, EntityCollection<Any, EntityI<Any>>> = mutableMapOf()
|
||||
abstract var connection: ConnectionPool<PostgreSQLConnection>
|
||||
|
||||
private inline fun <I, reified R : EntityI<I>> get(id: I): R? {
|
||||
val collection = collections[R::class]
|
||||
val entity = collection?.get(id!!)
|
||||
return entity as R?
|
||||
}
|
||||
|
||||
private inline fun <I, reified R : EntityI<I>> set(entity: R) {
|
||||
if (collections[R::class] == null) {
|
||||
collections[R::class] = EntityCollection()
|
||||
}
|
||||
|
||||
collections[R::class]!!.set(entity as EntityI<Any>)
|
||||
}
|
||||
|
||||
fun <T> findById(id: T): EntityI<T>? {
|
||||
return when (val e = get(id)) {
|
||||
fun <T> findById(id: T): EntityI<T?>? {
|
||||
return when (val e = EntityCollection().get(id)) {
|
||||
null -> {
|
||||
// TODO create Request
|
||||
Serializer().deserialize<T, EntityI<T>>("""{"plop", "plip"}""")
|
||||
Serializer().deserialize<T, EntityI<T?>>("""{"plop", "plip"}""")
|
||||
}
|
||||
else -> e
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,86 @@
|
||||
package fr.postgresjson.serializer
|
||||
|
||||
import com.fasterxml.jackson.core.JsonParser
|
||||
import com.fasterxml.jackson.core.JsonProcessingException
|
||||
import com.fasterxml.jackson.databind.DeserializationContext
|
||||
import com.fasterxml.jackson.databind.JsonNode
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
|
||||
import com.fasterxml.jackson.databind.module.SimpleModule
|
||||
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
||||
import com.fasterxml.jackson.module.kotlin.readValue
|
||||
import fr.postgresjson.entity.EntityCollection
|
||||
import fr.postgresjson.entity.EntityI
|
||||
import fr.postgresjson.entity.IdEntity
|
||||
import fr.postgresjson.entity.UuidEntity
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
|
||||
class Serializer(val mapper: ObjectMapper = jacksonObjectMapper()) {
|
||||
|
||||
var collection: EntityCollection = EntityCollection()
|
||||
|
||||
init {
|
||||
val module = SimpleModule()
|
||||
module.addDeserializer(UuidEntity::class.java, EntityUuidDeserializer(collection))
|
||||
module.addDeserializer(IdEntity::class.java, EntityIdDeserializer(collection))
|
||||
mapper.registerModule(module)
|
||||
}
|
||||
|
||||
fun <T> serialize(source: EntityI<T>): String {
|
||||
return mapper.writeValueAsString(source)
|
||||
}
|
||||
|
||||
inline fun <T, reified E : EntityI<T>> deserialize(json: String): E {
|
||||
val unserialized = mapper.readValue<E>(json)
|
||||
return EntityCollection<T, E>().get(unserialized.id) ?: unserialized
|
||||
inline fun <T, reified E : EntityI<T?>> deserialize(json: String): E {
|
||||
val unserialized = this.mapper.readValue<E>(json)
|
||||
return collection.get(unserialized.id) ?: unserialized
|
||||
}
|
||||
|
||||
fun <T, E : EntityI<T>> deserialize(json: String, target: E): E {
|
||||
inline fun <T, reified E : EntityI<T?>> deserialize(json: String, target: E): E {
|
||||
val unserialized = mapper.readerForUpdating(target).readValue<E>(json)
|
||||
return EntityCollection<T, E>().get(unserialized.id) ?: unserialized
|
||||
return collection.get(unserialized.id) ?: unserialized
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> EntityI<T>.serialize() = Serializer().serialize(this)
|
||||
fun <T, E : EntityI<T>> E.deserialize(json: String) = Serializer().deserialize(json, this)
|
||||
fun <T> EntityI<T?>.serialize() = Serializer().serialize(this)
|
||||
inline fun <T, reified E : EntityI<T?>> E.deserialize(json: String) = Serializer().deserialize(json, this)
|
||||
|
||||
|
||||
class EntityUuidDeserializer <T: UuidEntity> @JvmOverloads constructor(vc: Class<*>? = null) : StdDeserializer<T>(vc) {
|
||||
var collection: EntityCollection = EntityCollection()
|
||||
|
||||
constructor(collection: EntityCollection) : this() {
|
||||
this.collection = collection
|
||||
}
|
||||
|
||||
@Throws(IOException::class, JsonProcessingException::class)
|
||||
override fun deserialize(jp: JsonParser, ctxt: DeserializationContext): T {
|
||||
val node = jp.codec.readTree<JsonNode>(jp)
|
||||
val id = node.get("id").asText()
|
||||
val entity = collection.get<UUID, UuidEntity>(UUID.fromString(id))
|
||||
|
||||
return (entity ?: ctxt.readValue(jp, UuidEntity::class.javaObjectType)) as T
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class EntityIdDeserializer <T: IdEntity> @JvmOverloads constructor(vc: Class<*>? = null) : StdDeserializer<T>(vc) {
|
||||
var collection: EntityCollection = EntityCollection()
|
||||
|
||||
constructor(collection: EntityCollection) : this() {
|
||||
this.collection = collection
|
||||
}
|
||||
|
||||
@Throws(IOException::class, JsonProcessingException::class)
|
||||
override fun deserialize(jp: JsonParser, ctxt: DeserializationContext): T {
|
||||
val node = jp.codec.readTree<JsonNode>(jp)
|
||||
val id = node.get("id").asInt()
|
||||
val entity = collection.get<Int?, IdEntity>(id)
|
||||
|
||||
val obj = (entity ?: ctxt.readValue(jp, UuidEntity::class.javaObjectType)) as EntityI<Int?>
|
||||
collection.set(obj)
|
||||
|
||||
return obj as T
|
||||
}
|
||||
}
|
||||
30
src/test/kotlin/fr/postgresjson/serializer/ConnectionTest.kt
Normal file
30
src/test/kotlin/fr/postgresjson/serializer/ConnectionTest.kt
Normal file
@@ -0,0 +1,30 @@
|
||||
package fr.postgresjson.serializer
|
||||
|
||||
import fr.postgresjson.connexion.Connection
|
||||
import fr.postgresjson.entity.IdEntity
|
||||
import org.junit.jupiter.api.Assertions.assertTrue
|
||||
import org.junit.jupiter.api.BeforeEach
|
||||
import org.junit.jupiter.api.Test
|
||||
|
||||
class ConnectionTest() {
|
||||
private lateinit var connection: Connection
|
||||
|
||||
@BeforeEach
|
||||
fun before() {
|
||||
connection = Connection()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun getObject() {
|
||||
val obj: ObjTest? = connection.execute<Int?, ObjTest>("select to_json(a) from test a limit 1")
|
||||
assertTrue(obj is ObjTest)
|
||||
}
|
||||
|
||||
// @Test
|
||||
// fun getExistingObject() {
|
||||
// val obj: ObjTest? = connection.execute<Int?, ObjTest>("select to_json(a) from test a limit 1")
|
||||
// assertTrue(obj is ObjTest)
|
||||
// }
|
||||
}
|
||||
|
||||
class ObjTest(var name: String): IdEntity()
|
||||
Reference in New Issue
Block a user