From 2ce4f5a8bd7b337e0067b2f670f693959b1de9cf Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 16:36:38 +0900 Subject: [PATCH 01/18] =?UTF-8?q?=E3=83=90=E3=83=BC=E3=82=B8=E3=83=A7?= =?UTF-8?q?=E3=83=B3=E3=82=A2=E3=83=83=E3=83=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle.kts b/build.gradle.kts index 166966d..cec3497 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -6,7 +6,7 @@ plugins { } group = "com.mapk" -version = "0.23" +version = "0.24" java { sourceCompatibility = JavaVersion.VERSION_1_8 From 93ee440d33191ff416f3222fd986d42d9db1330c Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 16:42:01 +0900 Subject: [PATCH 02/18] =?UTF-8?q?=E5=86=8D=E5=B8=B0=E7=9A=84=E3=83=9E?= =?UTF-8?q?=E3=83=83=E3=83=94=E3=83=B3=E3=82=B0=E3=81=AE=E3=83=86=E3=82=B9?= =?UTF-8?q?=E3=83=88=E5=9F=BA=E7=9B=A4=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mapk/kmapper/RecursiveMappingTest.kt | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt diff --git a/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt b/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt new file mode 100644 index 0000000..310f257 --- /dev/null +++ b/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt @@ -0,0 +1,30 @@ +package com.mapk.kmapper + +import org.junit.jupiter.api.Assertions.assertEquals +import org.junit.jupiter.api.DisplayName +import org.junit.jupiter.api.Nested +import org.junit.jupiter.api.Test + +@DisplayName("再帰的マッピングのテスト") +class RecursiveMappingTest { + private data class InnerSrc(val hoge: Int, val fuga: Short, val piyo: String) + private data class InnerDst(val hoge: Int, val piyo: String) + + private data class Src(val foo: InnerSrc, val bar: Boolean, val baz: Int) + private data class Dst(val foo: InnerDst, val baz: Int) + + companion object { + private val src: Src = Src(InnerSrc(1, 2, "three"), true, 4) + private val expected: Dst = Dst(InnerDst(1, "three"), 4) + } + + @Nested + @DisplayName("BoundKMapper") + inner class BoundKMapperTest { + @Test + fun test() { + val actual = BoundKMapper(::Dst, Src::class).map(src) + assertEquals(expected, actual) + } + } +} From a65c397ae0f87c108c3e4791dcda1e6caeb2ddf9 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 16:49:15 +0900 Subject: [PATCH 03/18] =?UTF-8?q?=E5=86=8D=E5=B8=B0=E7=9A=84=E3=83=9E?= =?UTF-8?q?=E3=83=83=E3=83=94=E3=83=B3=E3=82=B0=E3=81=AE=E3=81=B2=E3=81=AA?= =?UTF-8?q?=E5=9E=8B=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/mapk/kmapper/BoundParameterForMap.kt | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt b/src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt index 0f954ab..f5cf7f6 100644 --- a/src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt +++ b/src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt @@ -32,6 +32,14 @@ internal sealed class BoundParameterForMap { override fun map(src: S): Any? = converter.call(propertyGetter.invoke(src)) } + private class UseBoundKMapper( + override val param: KParameter, + override val propertyGetter: Method, + private val boundKMapper: BoundKMapper + ) : BoundParameterForMap() { + override fun map(src: S): Any? = boundKMapper.map(propertyGetter.invoke(src) as T) + } + private class ToEnum( override val param: KParameter, override val propertyGetter: Method, @@ -77,7 +85,8 @@ internal sealed class BoundParameterForMap { return when { javaClazz.isEnum && propertyClazz == String::class -> ToEnum(param, propertyGetter, javaClazz) paramClazz == String::class -> ToString(param, propertyGetter) - else -> throw IllegalArgumentException("Can not convert $propertyClazz to $paramClazz") + // TODO: パラメータ名のコンバータ対応、SrcがMapやPairだった場合にKMapperを用いる形への変更 + else -> UseBoundKMapper(param, propertyGetter, BoundKMapper(paramClazz, propertyClazz)) } } } From cefbf62eeb603032fcfcf577d72b66b3abe03e66 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 16:54:44 +0900 Subject: [PATCH 04/18] =?UTF-8?q?=E3=83=91=E3=83=A9=E3=83=A1=E3=83=BC?= =?UTF-8?q?=E3=82=BF=E5=90=8D=E5=A4=89=E6=8F=9B=E3=82=92=E3=83=86=E3=82=B9?= =?UTF-8?q?=E3=83=88=E3=81=99=E3=82=8B=E3=81=9F=E3=82=81=E3=82=AD=E3=83=A3?= =?UTF-8?q?=E3=83=A1=E3=83=AB=E3=82=B1=E3=83=BC=E3=82=B9=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt b/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt index 310f257..814551b 100644 --- a/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt +++ b/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt @@ -7,11 +7,11 @@ import org.junit.jupiter.api.Test @DisplayName("再帰的マッピングのテスト") class RecursiveMappingTest { - private data class InnerSrc(val hoge: Int, val fuga: Short, val piyo: String) - private data class InnerDst(val hoge: Int, val piyo: String) + private data class InnerSrc(val hogeHoge: Int, val fugaFuga: Short, val piyoPiyo: String) + private data class InnerDst(val hogeHoge: Int, val piyoPiyo: String) - private data class Src(val foo: InnerSrc, val bar: Boolean, val baz: Int) - private data class Dst(val foo: InnerDst, val baz: Int) + private data class Src(val fooFoo: InnerSrc, val barBar: Boolean, val bazBaz: Int) + private data class Dst(val fooFoo: InnerDst, val bazBaz: Int) companion object { private val src: Src = Src(InnerSrc(1, 2, "three"), true, 4) From ba49c91051aa036e3f10aa287f15da1c3740862f Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 17:00:31 +0900 Subject: [PATCH 05/18] =?UTF-8?q?=E3=83=8D=E3=82=B9=E3=83=88=E3=81=97?= =?UTF-8?q?=E3=81=A6=E3=83=91=E3=83=A9=E3=83=A1=E3=83=BC=E3=82=BF=E5=90=8D?= =?UTF-8?q?=E5=A4=89=E6=8F=9B=E3=82=92=E9=81=A9=E7=94=A8=E3=81=99=E3=82=8B?= =?UTF-8?q?=E5=A0=B4=E5=90=88=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mapk/kmapper/RecursiveMappingTest.kt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt b/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt index 814551b..7ca9c67 100644 --- a/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt +++ b/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt @@ -1,5 +1,6 @@ package com.mapk.kmapper +import com.google.common.base.CaseFormat import org.junit.jupiter.api.Assertions.assertEquals import org.junit.jupiter.api.DisplayName import org.junit.jupiter.api.Nested @@ -8,13 +9,16 @@ import org.junit.jupiter.api.Test @DisplayName("再帰的マッピングのテスト") class RecursiveMappingTest { private data class InnerSrc(val hogeHoge: Int, val fugaFuga: Short, val piyoPiyo: String) + private data class InnerSnakeSrc(val hoge_hoge: Int, val fuga_fuga: Short, val piyo_piyo: String) private data class InnerDst(val hogeHoge: Int, val piyoPiyo: String) private data class Src(val fooFoo: InnerSrc, val barBar: Boolean, val bazBaz: Int) + private data class SnakeSrc(val foo_foo: InnerSnakeSrc, val bar_bar: Boolean, val baz_baz: Int) private data class Dst(val fooFoo: InnerDst, val bazBaz: Int) companion object { private val src: Src = Src(InnerSrc(1, 2, "three"), true, 4) + private val snakeSrc: SnakeSrc = SnakeSrc(InnerSnakeSrc(1, 2, "three"), true, 4) private val expected: Dst = Dst(InnerDst(1, "three"), 4) } @@ -22,9 +26,19 @@ class RecursiveMappingTest { @DisplayName("BoundKMapper") inner class BoundKMapperTest { @Test + @DisplayName("シンプルなマッピング") fun test() { val actual = BoundKMapper(::Dst, Src::class).map(src) assertEquals(expected, actual) } + + @Test + @DisplayName("スネークケースsrc -> キャメルケースdst") + fun snakeToCamel() { + val actual = BoundKMapper(::Dst, SnakeSrc::class) { + CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, it) + }.map(snakeSrc) + assertEquals(expected, actual) + } } } From 8f8197942fcee15d330dbf68567c347932ff1752 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 17:00:51 +0900 Subject: [PATCH 06/18] =?UTF-8?q?=E5=86=8D=E5=B8=B0=E7=9A=84=E3=81=AB?= =?UTF-8?q?=E3=83=91=E3=83=A9=E3=83=A1=E3=83=BC=E3=82=BF=E5=90=8D=E5=A4=89?= =?UTF-8?q?=E6=8F=9B=E3=82=92=E9=81=A9=E7=94=A8=E3=81=99=E3=82=8B=E3=82=88?= =?UTF-8?q?=E3=81=86=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/mapk/kmapper/BoundParameterForMap.kt | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt b/src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt index f5cf7f6..8ab8419 100644 --- a/src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt +++ b/src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt @@ -56,7 +56,11 @@ internal sealed class BoundParameterForMap { } companion object { - fun newInstance(param: KParameter, property: KProperty1): BoundParameterForMap { + fun newInstance( + param: KParameter, + property: KProperty1, + parameterNameConverter: (String) -> String + ): BoundParameterForMap { // ゲッターが無いならエラー val propertyGetter = property.javaGetter ?: throw IllegalArgumentException("${property.name} does not have getter.") @@ -85,8 +89,10 @@ internal sealed class BoundParameterForMap { return when { javaClazz.isEnum && propertyClazz == String::class -> ToEnum(param, propertyGetter, javaClazz) paramClazz == String::class -> ToString(param, propertyGetter) - // TODO: パラメータ名のコンバータ対応、SrcがMapやPairだった場合にKMapperを用いる形への変更 - else -> UseBoundKMapper(param, propertyGetter, BoundKMapper(paramClazz, propertyClazz)) + // TODO: SrcがMapやPairだった場合にKMapperを用いる形への変更 + else -> UseBoundKMapper( + param, propertyGetter, BoundKMapper(paramClazz, propertyClazz, parameterNameConverter) + ) } } } From 7824bba96fab73472a6725eb426a385fc7133868 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 17:01:09 +0900 Subject: [PATCH 07/18] =?UTF-8?q?=E3=83=97=E3=83=AD=E3=83=91=E3=83=86?= =?UTF-8?q?=E3=82=A3=E5=90=8D=E5=A4=89=E6=8F=9B=E3=82=82=E3=83=91=E3=83=A9?= =?UTF-8?q?=E3=83=A1=E3=83=BC=E3=82=BF=E3=81=AB=E6=B8=A1=E3=81=99=E3=82=88?= =?UTF-8?q?=E3=81=86=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/kmapper/BoundKMapper.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/kotlin/com/mapk/kmapper/BoundKMapper.kt b/src/main/kotlin/com/mapk/kmapper/BoundKMapper.kt index d9b6e7e..287c54f 100644 --- a/src/main/kotlin/com/mapk/kmapper/BoundKMapper.kt +++ b/src/main/kotlin/com/mapk/kmapper/BoundKMapper.kt @@ -45,7 +45,7 @@ class BoundKMapper private constructor( .filter { it.kind != KParameter.Kind.INSTANCE && !it.isUseDefaultArgument() } .mapNotNull { val temp = srcPropertiesMap[parameterNameConverter(it.getAliasOrName()!!)]?.let { property -> - BoundParameterForMap.newInstance(it, property) + BoundParameterForMap.newInstance(it, property, parameterNameConverter) } // 必須引数に対応するプロパティがsrcに定義されていない場合エラー From cbd79de55be2a216340886835fa86f1e3c245c70 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 17:17:29 +0900 Subject: [PATCH 08/18] =?UTF-8?q?=E5=86=85=E9=83=A8=E3=81=ABMap=E3=82=92?= =?UTF-8?q?=E5=85=A5=E3=82=8C=E3=81=9F=E5=A0=B4=E5=90=88=E3=81=AE=E3=83=86?= =?UTF-8?q?=E3=82=B9=E3=83=88=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt b/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt index 7ca9c67..b45ed0c 100644 --- a/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt +++ b/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt @@ -14,11 +14,13 @@ class RecursiveMappingTest { private data class Src(val fooFoo: InnerSrc, val barBar: Boolean, val bazBaz: Int) private data class SnakeSrc(val foo_foo: InnerSnakeSrc, val bar_bar: Boolean, val baz_baz: Int) + private data class MapSrc(val fooFoo: Map, val barBar: Boolean, val bazBaz: Int) private data class Dst(val fooFoo: InnerDst, val bazBaz: Int) companion object { private val src: Src = Src(InnerSrc(1, 2, "three"), true, 4) private val snakeSrc: SnakeSrc = SnakeSrc(InnerSnakeSrc(1, 2, "three"), true, 4) + private val mapSrc: MapSrc = MapSrc(mapOf("hogeHoge" to 1, "piyoPiyo" to "three"), true, 4) private val expected: Dst = Dst(InnerDst(1, "three"), 4) } @@ -40,5 +42,12 @@ class RecursiveMappingTest { }.map(snakeSrc) assertEquals(expected, actual) } + + @Test + @DisplayName("内部フィールドがMapの場合") + fun includesMap() { + val actual = BoundKMapper(::Dst, MapSrc::class).map(mapSrc) + assertEquals(expected, actual) + } } } From 4431602757b72e1de06e3e9ad66409a79708621f Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 17:17:52 +0900 Subject: [PATCH 09/18] =?UTF-8?q?=E5=86=85=E9=83=A8=E3=81=ABMap=E3=82=84Pa?= =?UTF-8?q?ir=E3=82=92=E5=B7=AE=E3=81=97=E8=BE=BC=E3=81=BE=E3=82=8C?= =?UTF-8?q?=E3=81=9F=E6=99=82=E3=81=B8=E3=81=AE=E5=AF=BE=E5=BF=9C=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mapk/kmapper/BoundParameterForMap.kt | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt b/src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt index 8ab8419..ab0a452 100644 --- a/src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt +++ b/src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt @@ -32,6 +32,19 @@ internal sealed class BoundParameterForMap { override fun map(src: S): Any? = converter.call(propertyGetter.invoke(src)) } + private class UseKMapper( + override val param: KParameter, + override val propertyGetter: Method, + private val kMapper: KMapper<*> + ) : BoundParameterForMap() { + // 1引数で呼び出すとMap/Pairが適切に処理されないため、2引数目にダミーを噛ませている + override fun map(src: S): Any? = kMapper.map(propertyGetter.invoke(src), dummy) + + companion object { + private val dummy = "" to null + } + } + private class UseBoundKMapper( override val param: KParameter, override val propertyGetter: Method, @@ -89,7 +102,11 @@ internal sealed class BoundParameterForMap { return when { javaClazz.isEnum && propertyClazz == String::class -> ToEnum(param, propertyGetter, javaClazz) paramClazz == String::class -> ToString(param, propertyGetter) - // TODO: SrcがMapやPairだった場合にKMapperを用いる形への変更 + // SrcがMapやPairならKMapperを使わないとマップできない + propertyClazz.isSubclassOf(Map::class) || propertyClazz.isSubclassOf(Pair::class) -> UseKMapper( + param, propertyGetter, KMapper(paramClazz, parameterNameConverter) + ) + // 何にも当てはまらなければBoundKMapperでマップを試みる else -> UseBoundKMapper( param, propertyGetter, BoundKMapper(paramClazz, propertyClazz, parameterNameConverter) ) From 9bbe4ab71d871e5bfb1a001a7efe8f5cc92d4779 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 17:44:00 +0900 Subject: [PATCH 10/18] =?UTF-8?q?KMapper=E3=81=AB=E9=96=A2=E3=81=99?= =?UTF-8?q?=E3=82=8B=E5=86=8D=E5=B8=B0=E7=9A=84=E3=83=9E=E3=83=83=E3=83=94?= =?UTF-8?q?=E3=83=B3=E3=82=B0=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mapk/kmapper/RecursiveMappingTest.kt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt b/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt index b45ed0c..0db06c9 100644 --- a/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt +++ b/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt @@ -24,6 +24,33 @@ class RecursiveMappingTest { private val expected: Dst = Dst(InnerDst(1, "three"), 4) } + @Nested + @DisplayName("KMapper") + inner class KMapperTest { + @Test + @DisplayName("シンプルなマッピング") + fun test() { + val actual = KMapper(::Dst).map(src) + assertEquals(expected, actual) + } + + @Test + @DisplayName("スネークケースsrc -> キャメルケースdst") + fun snakeToCamel() { + val actual = KMapper(::Dst) { + CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, it) + }.map(snakeSrc) + assertEquals(expected, actual) + } + + @Test + @DisplayName("内部フィールドがMapの場合") + fun includesMap() { + val actual = KMapper(::Dst).map(mapSrc) + assertEquals(expected, actual) + } + } + @Nested @DisplayName("BoundKMapper") inner class BoundKMapperTest { From 4f2a569a29ef2857e51b619a8a10979eadff37ba Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 17:55:13 +0900 Subject: [PATCH 11/18] =?UTF-8?q?=E3=83=80=E3=83=9F=E3=83=BC=E3=81=AF?= =?UTF-8?q?=E5=85=B1=E9=80=9A=E3=81=A7=E4=BD=BF=E3=81=84=E3=81=9F=E3=81=84?= =?UTF-8?q?=E3=81=9F=E3=82=81=E5=88=87=E3=82=8A=E5=87=BA=E3=81=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt | 6 +----- src/main/kotlin/com/mapk/kmapper/ParameterUtils.kt | 3 +++ 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt b/src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt index ab0a452..e3a3701 100644 --- a/src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt +++ b/src/main/kotlin/com/mapk/kmapper/BoundParameterForMap.kt @@ -38,11 +38,7 @@ internal sealed class BoundParameterForMap { private val kMapper: KMapper<*> ) : BoundParameterForMap() { // 1引数で呼び出すとMap/Pairが適切に処理されないため、2引数目にダミーを噛ませている - override fun map(src: S): Any? = kMapper.map(propertyGetter.invoke(src), dummy) - - companion object { - private val dummy = "" to null - } + override fun map(src: S): Any? = kMapper.map(propertyGetter.invoke(src), PARAMETER_DUMMY) } private class UseBoundKMapper( diff --git a/src/main/kotlin/com/mapk/kmapper/ParameterUtils.kt b/src/main/kotlin/com/mapk/kmapper/ParameterUtils.kt index be1e830..4a109d4 100644 --- a/src/main/kotlin/com/mapk/kmapper/ParameterUtils.kt +++ b/src/main/kotlin/com/mapk/kmapper/ParameterUtils.kt @@ -52,3 +52,6 @@ private fun convertersFromCompanionObject(clazz: KClass): Set Set, KFunction>>.getConverter(input: KClass): KFunction? = this.find { (key, _) -> input.isSubclassOf(key) }?.second + +// 再帰的マッピング時にKMapperでマップする場合、引数の数が1つだと正常にマッピングが機能しないため、2引数にするために用いるダミー +internal val PARAMETER_DUMMY = "" to null From f3072db7e4334a3a636d37c9d8babc0f1e18a89a Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 17:56:18 +0900 Subject: [PATCH 12/18] =?UTF-8?q?=E3=83=9E=E3=83=83=E3=83=94=E3=83=B3?= =?UTF-8?q?=E3=82=B0=E7=94=A8=E3=81=AE=E3=82=AF=E3=83=A9=E3=82=B9=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt b/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt index eceec68..e6b3c63 100644 --- a/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt +++ b/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt @@ -62,6 +62,15 @@ private sealed class ParameterProcessor { override fun process(value: Any): Any? = converter.call(value) } + class UseKMapper(private val kMapper: KMapper<*>) : ParameterProcessor() { + override fun process(value: Any): Any? = kMapper.map(value, PARAMETER_DUMMY) + } + + @Suppress("UNCHECKED_CAST") + class UseBoundKMapper(private val boundKMapper: BoundKMapper) : ParameterProcessor() { + override fun process(value: Any): Any? = boundKMapper.map(value as T) + } + class ToEnum(private val javaClazz: Class<*>) : ParameterProcessor() { override fun process(value: Any): Any? = EnumMapper.getEnum(javaClazz, value as String) } From e19d917e0243e52158f9db99342c639079095b62 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 17:56:48 +0900 Subject: [PATCH 13/18] =?UTF-8?q?=E3=83=91=E3=83=A9=E3=83=A1=E3=83=BC?= =?UTF-8?q?=E3=82=BF=E3=81=AE=E6=8C=AF=E3=82=8A=E5=88=86=E3=81=91=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/mapk/kmapper/ParameterForMap.kt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt b/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt index e6b3c63..92dc333 100644 --- a/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt +++ b/src/main/kotlin/com/mapk/kmapper/ParameterForMap.kt @@ -8,7 +8,11 @@ import kotlin.reflect.KFunction import kotlin.reflect.KParameter import kotlin.reflect.full.isSuperclassOf -internal class ParameterForMap private constructor(val param: KParameter, private val clazz: KClass) { +internal class ParameterForMap private constructor( + val param: KParameter, + private val clazz: KClass, + private val parameterNameConverter: (String) -> String +) { private val javaClazz: Class by lazy { clazz.java } @@ -38,15 +42,18 @@ internal class ParameterForMap private constructor(val param: KParamete javaClazz.isEnum && value is String -> ParameterProcessor.ToEnum(javaClazz) // 要求されているパラメータがStringならtoStringする clazz == String::class -> ParameterProcessor.ToString - else -> throw IllegalArgumentException("Can not convert $valueClazz to $clazz") + // 入力がmapもしくはpairなら、KMapperを用いてマッピングを試みる + value is Map<*, *> || value is Pair<*, *> -> + ParameterProcessor.UseKMapper(KMapper(clazz, parameterNameConverter)) + else -> ParameterProcessor.UseBoundKMapper(BoundKMapper(clazz, valueClazz, parameterNameConverter)) } convertCache.putIfAbsent(valueClazz, processor) return processor.process(value) } companion object { - fun newInstance(param: KParameter): ParameterForMap<*> { - return ParameterForMap(param, param.type.classifier as KClass<*>) + fun newInstance(param: KParameter, parameterNameConverter: (String) -> String): ParameterForMap<*> { + return ParameterForMap(param, param.type.classifier as KClass<*>, parameterNameConverter) } } } From 4e08acabcf0549d2bf1d7804e41f0b20f7fefd09 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 17:56:58 +0900 Subject: [PATCH 14/18] =?UTF-8?q?=E5=BC=95=E6=95=B0=E3=81=AE=E5=A4=89?= =?UTF-8?q?=E6=9B=B4=E3=81=AB=E5=AF=BE=E5=BF=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/kmapper/KMapper.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com/mapk/kmapper/KMapper.kt b/src/main/kotlin/com/mapk/kmapper/KMapper.kt index 4faff9a..037f8a2 100644 --- a/src/main/kotlin/com/mapk/kmapper/KMapper.kt +++ b/src/main/kotlin/com/mapk/kmapper/KMapper.kt @@ -31,7 +31,9 @@ class KMapper private constructor( private val parameterMap: Map> = function.parameters .filter { it.kind != KParameter.Kind.INSTANCE && !it.isUseDefaultArgument() } - .associate { (parameterNameConverter(it.getAliasOrName()!!)) to ParameterForMap.newInstance(it) } + .associate { + (parameterNameConverter(it.getAliasOrName()!!)) to ParameterForMap.newInstance(it, parameterNameConverter) + } private val getCache: ConcurrentMap, List> = ConcurrentHashMap() From f854eba3c4023b2cbfd00b2c565be3c9d2330d8f Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 18:04:44 +0900 Subject: [PATCH 15/18] =?UTF-8?q?pair=E3=82=92=E7=94=A8=E3=81=84=E3=81=A6?= =?UTF-8?q?=E3=83=8D=E3=82=B9=E3=83=88=E3=81=97=E3=81=9F=E3=83=9E=E3=83=83?= =?UTF-8?q?=E3=83=94=E3=83=B3=E3=82=B0=E3=82=92=E3=81=97=E3=81=9F=E9=9A=9B?= =?UTF-8?q?=E3=81=AB=E3=82=82=E6=AD=A3=E5=B8=B8=E3=81=AB=E5=8B=95=E3=81=8F?= =?UTF-8?q?=E3=81=93=E3=81=A8=E3=82=92=E7=A2=BA=E8=AA=8D=E3=81=99=E3=82=8B?= =?UTF-8?q?=E3=81=9F=E3=82=81=E3=81=AE=E3=83=95=E3=82=A3=E3=83=BC=E3=83=AB?= =?UTF-8?q?=E3=83=89=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mapk/kmapper/RecursiveMappingTest.kt | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt b/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt index 0db06c9..9ea509a 100644 --- a/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt +++ b/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt @@ -8,9 +8,21 @@ import org.junit.jupiter.api.Test @DisplayName("再帰的マッピングのテスト") class RecursiveMappingTest { - private data class InnerSrc(val hogeHoge: Int, val fugaFuga: Short, val piyoPiyo: String) - private data class InnerSnakeSrc(val hoge_hoge: Int, val fuga_fuga: Short, val piyo_piyo: String) - private data class InnerDst(val hogeHoge: Int, val piyoPiyo: String) + private data class InnerSrc( + val hogeHoge: Int, + val fugaFuga: Short, + val piyoPiyo: String, + val mogeMoge: Pair + ) + private data class InnerSnakeSrc( + val hoge_hoge: Int, + val fuga_fuga: Short, + val piyo_piyo: String, + val moge_moge: Pair + ) + + private data class InnerInnerDst(val poiPoi: Int?) + private data class InnerDst(val hogeHoge: Int, val piyoPiyo: String, val mogeMoge: InnerInnerDst) private data class Src(val fooFoo: InnerSrc, val barBar: Boolean, val bazBaz: Int) private data class SnakeSrc(val foo_foo: InnerSnakeSrc, val bar_bar: Boolean, val baz_baz: Int) @@ -18,10 +30,10 @@ class RecursiveMappingTest { private data class Dst(val fooFoo: InnerDst, val bazBaz: Int) companion object { - private val src: Src = Src(InnerSrc(1, 2, "three"), true, 4) - private val snakeSrc: SnakeSrc = SnakeSrc(InnerSnakeSrc(1, 2, "three"), true, 4) - private val mapSrc: MapSrc = MapSrc(mapOf("hogeHoge" to 1, "piyoPiyo" to "three"), true, 4) - private val expected: Dst = Dst(InnerDst(1, "three"), 4) + private val src = Src(InnerSrc(1, 2, "three", "poiPoi" to 5), true, 4) + private val snakeSrc = SnakeSrc(InnerSnakeSrc(1, 2, "three", "poi_poi" to 5), true, 4) + private val mapSrc = MapSrc(mapOf("hogeHoge" to 1, "piyoPiyo" to "three", "mogeMoge" to ("poiPoi" to 5)), true, 4) + private val expected = Dst(InnerDst(1, "three", InnerInnerDst(5)), 4) } @Nested From da277f8afedc504c4d51ff40081189f479e294b5 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 18:14:59 +0900 Subject: [PATCH 16/18] =?UTF-8?q?PlainKMapper=E3=81=AB=E9=96=A2=E3=81=99?= =?UTF-8?q?=E3=82=8B=E5=86=8D=E5=B8=B0=E7=9A=84=E3=83=9E=E3=83=83=E3=83=94?= =?UTF-8?q?=E3=83=B3=E3=82=B0=E3=81=AE=E3=83=86=E3=82=B9=E3=83=88=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/mapk/kmapper/RecursiveMappingTest.kt | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt b/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt index 9ea509a..11166ce 100644 --- a/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt +++ b/src/test/kotlin/com/mapk/kmapper/RecursiveMappingTest.kt @@ -63,6 +63,33 @@ class RecursiveMappingTest { } } + @Nested + @DisplayName("PlainKMapper") + inner class PlainKMapperTest { + @Test + @DisplayName("シンプルなマッピング") + fun test() { + val actual = PlainKMapper(::Dst).map(src) + assertEquals(expected, actual) + } + + @Test + @DisplayName("スネークケースsrc -> キャメルケースdst") + fun snakeToCamel() { + val actual = PlainKMapper(::Dst) { + CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, it) + }.map(snakeSrc) + assertEquals(expected, actual) + } + + @Test + @DisplayName("内部フィールドがMapの場合") + fun includesMap() { + val actual = PlainKMapper(::Dst).map(mapSrc) + assertEquals(expected, actual) + } + } + @Nested @DisplayName("BoundKMapper") inner class BoundKMapperTest { From df695c9f88c2c3c34e87d5db8ad1e978c7a7e027 Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 18:16:55 +0900 Subject: [PATCH 17/18] =?UTF-8?q?=E6=8C=AF=E3=82=8A=E5=88=86=E3=81=91?= =?UTF-8?q?=E3=82=92=E8=BF=BD=E5=8A=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/com/mapk/kmapper/PlainParameterForMap.kt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/com/mapk/kmapper/PlainParameterForMap.kt b/src/main/kotlin/com/mapk/kmapper/PlainParameterForMap.kt index 1c9a880..6273870 100644 --- a/src/main/kotlin/com/mapk/kmapper/PlainParameterForMap.kt +++ b/src/main/kotlin/com/mapk/kmapper/PlainParameterForMap.kt @@ -6,7 +6,11 @@ import kotlin.reflect.KFunction import kotlin.reflect.KParameter import kotlin.reflect.full.isSuperclassOf -internal class PlainParameterForMap private constructor(val param: KParameter, private val clazz: KClass) { +internal class PlainParameterForMap private constructor( + val param: KParameter, + private val clazz: KClass, + private val parameterNameConverter: (String) -> String +) { private val javaClazz: Class by lazy { clazz.java } @@ -28,13 +32,14 @@ internal class PlainParameterForMap private constructor(val param: KPar javaClazz.isEnum && value is String -> EnumMapper.getEnum(javaClazz, value) // 要求されているパラメータがStringならtoStringする clazz == String::class -> value.toString() - else -> throw IllegalArgumentException("Can not convert $valueClazz to $clazz") + // それ以外の場合PlainKMapperを作り再帰的なマッピングを試みる + else -> PlainKMapper(clazz, parameterNameConverter).map(value, PARAMETER_DUMMY) } } companion object { - fun newInstance(param: KParameter): PlainParameterForMap<*> { - return PlainParameterForMap(param, param.type.classifier as KClass<*>) + fun newInstance(param: KParameter, parameterNameConverter: (String) -> String): PlainParameterForMap<*> { + return PlainParameterForMap(param, param.type.classifier as KClass<*>, parameterNameConverter) } } } From 0c580b7a052adf98fd75c2cc7ff29345c878969f Mon Sep 17 00:00:00 2001 From: wrongwrong Date: Sun, 19 Apr 2020 18:17:05 +0900 Subject: [PATCH 18/18] =?UTF-8?q?=E5=BC=95=E6=95=B0=E3=82=92=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/kotlin/com/mapk/kmapper/PlainKMapper.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/kotlin/com/mapk/kmapper/PlainKMapper.kt b/src/main/kotlin/com/mapk/kmapper/PlainKMapper.kt index 17bb1d9..871990d 100644 --- a/src/main/kotlin/com/mapk/kmapper/PlainKMapper.kt +++ b/src/main/kotlin/com/mapk/kmapper/PlainKMapper.kt @@ -29,7 +29,10 @@ class PlainKMapper private constructor( private val parameterMap: Map> = function.parameters .filter { it.kind != KParameter.Kind.INSTANCE && !it.isUseDefaultArgument() } - .associate { (parameterNameConverter(it.getAliasOrName()!!)) to PlainParameterForMap.newInstance(it) } + .associate { + (parameterNameConverter(it.getAliasOrName()!!)) to + PlainParameterForMap.newInstance(it, parameterNameConverter) + } private fun bindArguments(argumentBucket: ArgumentBucket, src: Any) { src::class.memberProperties.forEach outer@{ property ->