Skip to content
This repository was archived by the owner on Jan 20, 2023. It is now read-only.

Commit 45e775e

Browse files
authored
Merge pull request #6 from k163377/feature
Add deserializer support.
2 parents 7c8d213 + 1ed4284 commit 45e775e

File tree

5 files changed

+106
-12
lines changed

5 files changed

+106
-12
lines changed

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.mapk.deserialization
2+
3+
import kotlin.reflect.KClass
4+
5+
@Target(AnnotationTarget.ANNOTATION_CLASS)
6+
@Retention(AnnotationRetention.RUNTIME)
7+
@MustBeDocumented
8+
annotation class KColumnDeserializeBy(val deserializer: KClass<out KColumnDeserializer<*, *, *>>)
9+
10+
abstract class KColumnDeserializer<A : Annotation, S : Any, D : Any>(protected val annotation: A) {
11+
abstract val srcClass: Class<S>
12+
abstract fun deserialize(source: S?): D?
13+
}

src/main/kotlin/com/mapk/krowmapper/ParameterForMap.kt

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@ import com.mapk.annotations.KColumnDeserializer
44
import com.mapk.core.EnumMapper
55
import com.mapk.core.KFunctionWithInstance
66
import com.mapk.core.getAliasOrName
7+
import com.mapk.deserialization.KColumnDeserializeBy
78
import java.lang.IllegalArgumentException
89
import java.sql.ResultSet
910
import kotlin.reflect.KClass
1011
import kotlin.reflect.KFunction
1112
import kotlin.reflect.KParameter
1213
import kotlin.reflect.full.companionObjectInstance
14+
import kotlin.reflect.full.findAnnotation
1315
import kotlin.reflect.full.functions
16+
import kotlin.reflect.full.primaryConstructor
1417
import kotlin.reflect.full.staticFunctions
1518
import kotlin.reflect.jvm.isAccessible
1619
import kotlin.reflect.jvm.jvmName
@@ -23,24 +26,33 @@ class ParameterForMap private constructor(
2326
private val objectGetter: (ResultSet) -> Any?
2427

2528
init {
26-
val deserializer = parameterKClazz.getDeserializer()
27-
28-
if (deserializer != null) {
29-
val targetClass = deserializer.parameters.single().type.classifier as KClass<*>
29+
val deserializerFromParameter = param.getDeserializer()
30+
if (deserializerFromParameter != null) {
31+
val deserialize = deserializerFromParameter::deserialize
3032

3133
objectGetter = {
32-
deserializer.call(it.getObject(name, targetClass.javaObjectType))
34+
deserialize.call(it.getObject(name, deserializerFromParameter.srcClass))
3335
}
3436
} else {
35-
val clazz = parameterKClazz.javaObjectType
37+
val deserializer = parameterKClazz.getDeserializer()
38+
39+
if (deserializer != null) {
40+
val targetClass = deserializer.parameters.single().type.classifier as KClass<*>
3641

37-
objectGetter = if (clazz.isEnum) {
38-
{
39-
EnumMapper.getEnum(clazz, it.getString(name))
42+
objectGetter = {
43+
deserializer.call(it.getObject(name, targetClass.javaObjectType))
4044
}
4145
} else {
42-
{
43-
it.getObject(name, clazz)
46+
val clazz = parameterKClazz.javaObjectType
47+
48+
objectGetter = if (clazz.isEnum) {
49+
{
50+
EnumMapper.getEnum(clazz, it.getString(name))
51+
}
52+
} else {
53+
{
54+
it.getObject(name, clazz)
55+
}
4456
}
4557
}
4658
}
@@ -59,6 +71,19 @@ class ParameterForMap private constructor(
5971
}
6072
}
6173

74+
private fun KParameter.getDeserializer(): com.mapk.deserialization.KColumnDeserializer<*, *, *>? {
75+
val deserializers = this.annotations.mapNotNull { paramAnnotation ->
76+
paramAnnotation.annotationClass
77+
.findAnnotation<KColumnDeserializeBy>()
78+
?.let { it.deserializer.primaryConstructor!!.call(paramAnnotation) }
79+
}
80+
81+
if (1 < deserializers.size)
82+
throw IllegalArgumentException("Find multiple deserializer from ${(this.type.classifier as KClass<*>).jvmName}")
83+
84+
return deserializers.singleOrNull()
85+
}
86+
6287
private fun <T : Any> KClass<T>.getDeserializer(): KFunction<T>? {
6388
val deserializers = deserializerFromConstructors(this) +
6489
deserializerFromStaticMethods(this) +
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package com.mapk.krowmapper
2+
3+
import com.mapk.deserialization.KColumnDeserializeBy
4+
import com.mapk.deserialization.KColumnDeserializer
5+
import io.mockk.every
6+
import io.mockk.mockk
7+
import java.sql.ResultSet
8+
import java.time.LocalDateTime
9+
import java.time.format.DateTimeFormatter
10+
import org.junit.jupiter.api.Assertions.assertEquals
11+
import org.junit.jupiter.api.DisplayName
12+
import org.junit.jupiter.api.Test
13+
14+
@DisplayName("アノテーションによるデシリアライザー指定のテスト")
15+
class DeserializerTest {
16+
@Target(AnnotationTarget.VALUE_PARAMETER)
17+
@Retention(AnnotationRetention.RUNTIME)
18+
@MustBeDocumented
19+
@KColumnDeserializeBy(LocalDateTimeDeserializerImpl::class)
20+
annotation class LocalDateTimeDeserializer(val pattern: String = "yyyy-MM-dd'T'HH:mm:ss")
21+
22+
class LocalDateTimeDeserializerImpl(
23+
annotation: LocalDateTimeDeserializer
24+
) : KColumnDeserializer<LocalDateTimeDeserializer, String, LocalDateTime>(annotation) {
25+
private val formatter: DateTimeFormatter = DateTimeFormatter.ofPattern(annotation.pattern)
26+
27+
override val srcClass: Class<String> = String::class.javaObjectType
28+
29+
override fun deserialize(source: String?): LocalDateTime? {
30+
return source?.let {
31+
LocalDateTime.parse(it, formatter)
32+
}
33+
}
34+
}
35+
36+
data class Dst(@LocalDateTimeDeserializer val dateTime: LocalDateTime)
37+
38+
@Test
39+
fun test() {
40+
val resultSet = mockk<ResultSet>()
41+
every { resultSet.getObject("dateTime", any<Class<*>>()) } returns "2020-02-01T01:23:45"
42+
43+
val result = KRowMapper(::Dst).mapRow(resultSet, 0)
44+
45+
assertEquals(
46+
LocalDateTime.parse("2020-02-01T01:23:45", DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss")),
47+
result.dateTime
48+
)
49+
}
50+
}

src/test/kotlin/com/mapk/krowmapper/UseDBMappingTest.kt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package com.mapk.krowmapper
33
import com.google.common.base.CaseFormat
44
import javax.sql.DataSource
55
import org.h2.jdbcx.JdbcDataSource
6+
import org.junit.jupiter.api.AfterAll
67
import org.junit.jupiter.api.Assertions.assertEquals
78
import org.junit.jupiter.api.BeforeAll
89
import org.junit.jupiter.api.Test
@@ -85,4 +86,9 @@ class UseDBMappingTest {
8586
result
8687
)
8788
}
89+
90+
@AfterAll
91+
fun afterAll() {
92+
jdbcTemplate.dataSource!!.connection.close()
93+
}
8894
}

0 commit comments

Comments
 (0)