From a58b374aed2a496bd7b949d22e8a101184baa6c7 Mon Sep 17 00:00:00 2001 From: Sergey Shumov Date: Sun, 7 Mar 2021 17:18:18 +0300 Subject: [PATCH 1/3] copy params instead of changing --- .../validation/ValidationHandler.kt | 31 +++++++---- src/test/kotlin/TestServer.kt | 55 +++++++++++++++++++ 2 files changed, 74 insertions(+), 12 deletions(-) diff --git a/src/main/kotlin/com/papsign/ktor/openapigen/validation/ValidationHandler.kt b/src/main/kotlin/com/papsign/ktor/openapigen/validation/ValidationHandler.kt index cdb19f36a..58d07ecd7 100644 --- a/src/main/kotlin/com/papsign/ktor/openapigen/validation/ValidationHandler.kt +++ b/src/main/kotlin/com/papsign/ktor/openapigen/validation/ValidationHandler.kt @@ -2,10 +2,10 @@ package com.papsign.ktor.openapigen.validation import com.papsign.ktor.openapigen.* import com.papsign.ktor.openapigen.classLogger +import org.reflections.ReflectionUtils import kotlin.reflect.* import kotlin.reflect.full.* -import kotlin.reflect.jvm.javaField -import kotlin.reflect.jvm.jvmErasure +import kotlin.reflect.jvm.* /** @@ -139,7 +139,7 @@ class ValidationHandler private constructor( } else { val appropriateConstructor = type.jvmErasure.constructors.find { it.parameters.size == 1 && it.parameters[0].type.isSubtypeOf(iterableType) - } ?: error("Unsupported Iterable type $type, must have a constructor that takes an iterable"); + } ?: error("Unsupported Iterable type $type, must have a constructor that takes an iterable") when { handler.isUseful() && shouldTransform -> { transformFun = { t: Any? -> @@ -208,8 +208,7 @@ class ValidationHandler private constructor( } else -> { val handled = type.memberProperties.mapNotNull { prop -> - val validator = - build(prop) + val validator = build(prop) if (validator.isUseful()) { prop.source.javaField.also { if (it == null) { @@ -236,15 +235,23 @@ class ValidationHandler private constructor( handled.isNotEmpty() -> { transformFun = { t: Any? -> if (t != null) { + val copy = t.javaClass.kotlin.memberFunctions.find { it.name == "copy" } + val map = copy?.instanceParameter?.let { mutableMapOf(it to t) } ?: mutableMapOf() handled.forEach { (handler, field) -> - // TODO convert this to canAccess and only change status if false - val accessible = field.isAccessible - field.isAccessible = true - field.set(t, handler.handle(field.get(t))) - field.isAccessible = accessible + val getter = field.kotlinProperty?.javaGetter + if (copy != null && getter != null) { + val param = copy.parameters.first { it.name == field.name } + map[param] = handler.handle(getter(t)) + } else { + // TODO convert this to canAccess and only change status if false + val accessible = field.isAccessible + field.isAccessible = true + field.set(t, handler.handle(field.get(t))) + field.isAccessible = accessible + } } - } - t + copy?.callBy(map.toMap()) ?: t + } else t } } shouldTransform -> { diff --git a/src/test/kotlin/TestServer.kt b/src/test/kotlin/TestServer.kt index 703580676..0355f40e8 100644 --- a/src/test/kotlin/TestServer.kt +++ b/src/test/kotlin/TestServer.kt @@ -30,6 +30,7 @@ import com.papsign.ktor.openapigen.annotations.type.string.length.Length import com.papsign.ktor.openapigen.annotations.type.string.length.MaxLength import com.papsign.ktor.openapigen.annotations.type.string.length.MinLength import com.papsign.ktor.openapigen.annotations.type.string.pattern.RegularExpression +import com.papsign.ktor.openapigen.annotations.type.string.trim.Trim import com.papsign.ktor.openapigen.interop.withAPI import com.papsign.ktor.openapigen.model.Described import com.papsign.ktor.openapigen.model.server.ServerModel @@ -319,6 +320,12 @@ object TestServer { } } } + + route("employees") { + get { params -> + respond(params) + } + } } }.start(true) } @@ -412,4 +419,52 @@ object TestServer { data class InstantResponse(val instant: Instant) data class LocalTimeResponse(val time: LocalTime?) data class OffsetTimeResponse(val time: OffsetTime?) + + data class FilterQuery( + @QueryParam("Vendor Code") @Trim + val vendorCode: String? = null, + @QueryParam("Organization") @Trim + val organization: String? = null, + @QueryParam("startDate") + val startDate: LocalDate? = null, + @QueryParam("endDate") + val endDate: LocalDate? = null, + @QueryParam("tenant") @Trim + val tenant: String? = null, + @QueryParam("manager") @Trim + val manager: String? = null, + @QueryParam("performer") @Trim + val performer: String? = null, + @QueryParam("condition") @Trim + val condition: String? = null, + @QueryParam("onlyNew") + val onlyNew: Boolean? = null, + @QueryParam("name") @Trim + val name: String? = null, + @QueryParam("minQuantity") @Min(0) + val minQuantity: Int? = null, + @QueryParam("maxQuantity") @Min(0) + val maxQuantity: Int? = null, + @QueryParam("minCost") @Min(0) + val minCost: Int? = null, + @QueryParam("maxCost") @Min(0) + val maxCost: Int? = null, + @QueryParam("inStock") + val inStock: Boolean? = null, + @QueryParam("active") + val active: Boolean? = null, + + @QueryParam("employeeName") @Trim + val employeeName: String? = null, + + @QueryParam("sortToken") + @StringExample("fullName") @Trim + val sortToken: String? = null, + @QueryParam("pageSize") + @Min(1) + val pageSize: Int? = null, + @QueryParam("page") + @Min(0) + val page: Long? = 0 + ) } From 5e9b549a07a70fb685d9a5e3d94a94ef12a07379 Mon Sep 17 00:00:00 2001 From: Sergey Shumov Date: Sun, 7 Mar 2021 17:47:33 +0300 Subject: [PATCH 2/3] better naming --- .../ktor/openapigen/validation/ValidationHandler.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/com/papsign/ktor/openapigen/validation/ValidationHandler.kt b/src/main/kotlin/com/papsign/ktor/openapigen/validation/ValidationHandler.kt index 58d07ecd7..91dd032bd 100644 --- a/src/main/kotlin/com/papsign/ktor/openapigen/validation/ValidationHandler.kt +++ b/src/main/kotlin/com/papsign/ktor/openapigen/validation/ValidationHandler.kt @@ -2,7 +2,6 @@ package com.papsign.ktor.openapigen.validation import com.papsign.ktor.openapigen.* import com.papsign.ktor.openapigen.classLogger -import org.reflections.ReflectionUtils import kotlin.reflect.* import kotlin.reflect.full.* import kotlin.reflect.jvm.* @@ -236,12 +235,12 @@ class ValidationHandler private constructor( transformFun = { t: Any? -> if (t != null) { val copy = t.javaClass.kotlin.memberFunctions.find { it.name == "copy" } - val map = copy?.instanceParameter?.let { mutableMapOf(it to t) } ?: mutableMapOf() + val copyParams = copy?.instanceParameter?.let { mutableMapOf(it to t) } ?: mutableMapOf() handled.forEach { (handler, field) -> val getter = field.kotlinProperty?.javaGetter if (copy != null && getter != null) { val param = copy.parameters.first { it.name == field.name } - map[param] = handler.handle(getter(t)) + copyParams[param] = handler.handle(getter(t)) } else { // TODO convert this to canAccess and only change status if false val accessible = field.isAccessible @@ -250,7 +249,7 @@ class ValidationHandler private constructor( field.isAccessible = accessible } } - copy?.callBy(map.toMap()) ?: t + copy?.callBy(copyParams.toMap()) ?: t } else t } } From 989d783236f61c6f1e1a1f184c957080bfeaa2b1 Mon Sep 17 00:00:00 2001 From: Sergey Shumov Date: Mon, 8 Mar 2021 17:28:10 +0300 Subject: [PATCH 3/3] using copy only if instanceParameter is not null --- .../ktor/openapigen/validation/ValidationHandler.kt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/kotlin/com/papsign/ktor/openapigen/validation/ValidationHandler.kt b/src/main/kotlin/com/papsign/ktor/openapigen/validation/ValidationHandler.kt index 91dd032bd..350312010 100644 --- a/src/main/kotlin/com/papsign/ktor/openapigen/validation/ValidationHandler.kt +++ b/src/main/kotlin/com/papsign/ktor/openapigen/validation/ValidationHandler.kt @@ -235,10 +235,10 @@ class ValidationHandler private constructor( transformFun = { t: Any? -> if (t != null) { val copy = t.javaClass.kotlin.memberFunctions.find { it.name == "copy" } - val copyParams = copy?.instanceParameter?.let { mutableMapOf(it to t) } ?: mutableMapOf() + val copyParams = copy?.instanceParameter?.let { mutableMapOf(it to t) } handled.forEach { (handler, field) -> val getter = field.kotlinProperty?.javaGetter - if (copy != null && getter != null) { + if (copy != null && copyParams != null && getter != null) { val param = copy.parameters.first { it.name == field.name } copyParams[param] = handler.handle(getter(t)) } else { @@ -249,7 +249,9 @@ class ValidationHandler private constructor( field.isAccessible = accessible } } - copy?.callBy(copyParams.toMap()) ?: t + if (copy != null && copyParams != null) { + copy.callBy(copyParams) + } else t } else t } }