Skip to content

Commit a58b374

Browse files
committed
copy params instead of changing
1 parent 1a70a7d commit a58b374

File tree

2 files changed

+74
-12
lines changed

2 files changed

+74
-12
lines changed

src/main/kotlin/com/papsign/ktor/openapigen/validation/ValidationHandler.kt

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ package com.papsign.ktor.openapigen.validation
22

33
import com.papsign.ktor.openapigen.*
44
import com.papsign.ktor.openapigen.classLogger
5+
import org.reflections.ReflectionUtils
56
import kotlin.reflect.*
67
import kotlin.reflect.full.*
7-
import kotlin.reflect.jvm.javaField
8-
import kotlin.reflect.jvm.jvmErasure
8+
import kotlin.reflect.jvm.*
99

1010

1111
/**
@@ -139,7 +139,7 @@ class ValidationHandler private constructor(
139139
} else {
140140
val appropriateConstructor = type.jvmErasure.constructors.find {
141141
it.parameters.size == 1 && it.parameters[0].type.isSubtypeOf(iterableType)
142-
} ?: error("Unsupported Iterable type $type, must have a constructor that takes an iterable");
142+
} ?: error("Unsupported Iterable type $type, must have a constructor that takes an iterable")
143143
when {
144144
handler.isUseful() && shouldTransform -> {
145145
transformFun = { t: Any? ->
@@ -208,8 +208,7 @@ class ValidationHandler private constructor(
208208
}
209209
else -> {
210210
val handled = type.memberProperties.mapNotNull { prop ->
211-
val validator =
212-
build(prop)
211+
val validator = build(prop)
213212
if (validator.isUseful()) {
214213
prop.source.javaField.also {
215214
if (it == null) {
@@ -236,15 +235,23 @@ class ValidationHandler private constructor(
236235
handled.isNotEmpty() -> {
237236
transformFun = { t: Any? ->
238237
if (t != null) {
238+
val copy = t.javaClass.kotlin.memberFunctions.find { it.name == "copy" }
239+
val map = copy?.instanceParameter?.let { mutableMapOf<KParameter, Any?>(it to t) } ?: mutableMapOf()
239240
handled.forEach { (handler, field) ->
240-
// TODO convert this to canAccess and only change status if false
241-
val accessible = field.isAccessible
242-
field.isAccessible = true
243-
field.set(t, handler.handle(field.get(t)))
244-
field.isAccessible = accessible
241+
val getter = field.kotlinProperty?.javaGetter
242+
if (copy != null && getter != null) {
243+
val param = copy.parameters.first { it.name == field.name }
244+
map[param] = handler.handle(getter(t))
245+
} else {
246+
// TODO convert this to canAccess and only change status if false
247+
val accessible = field.isAccessible
248+
field.isAccessible = true
249+
field.set(t, handler.handle(field.get(t)))
250+
field.isAccessible = accessible
251+
}
245252
}
246-
}
247-
t
253+
copy?.callBy(map.toMap()) ?: t
254+
} else t
248255
}
249256
}
250257
shouldTransform -> {

src/test/kotlin/TestServer.kt

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import com.papsign.ktor.openapigen.annotations.type.string.length.Length
3030
import com.papsign.ktor.openapigen.annotations.type.string.length.MaxLength
3131
import com.papsign.ktor.openapigen.annotations.type.string.length.MinLength
3232
import com.papsign.ktor.openapigen.annotations.type.string.pattern.RegularExpression
33+
import com.papsign.ktor.openapigen.annotations.type.string.trim.Trim
3334
import com.papsign.ktor.openapigen.interop.withAPI
3435
import com.papsign.ktor.openapigen.model.Described
3536
import com.papsign.ktor.openapigen.model.server.ServerModel
@@ -319,6 +320,12 @@ object TestServer {
319320
}
320321
}
321322
}
323+
324+
route("employees") {
325+
get<FilterQuery, FilterQuery> { params ->
326+
respond(params)
327+
}
328+
}
322329
}
323330
}.start(true)
324331
}
@@ -412,4 +419,52 @@ object TestServer {
412419
data class InstantResponse(val instant: Instant)
413420
data class LocalTimeResponse(val time: LocalTime?)
414421
data class OffsetTimeResponse(val time: OffsetTime?)
422+
423+
data class FilterQuery(
424+
@QueryParam("Vendor Code") @Trim
425+
val vendorCode: String? = null,
426+
@QueryParam("Organization") @Trim
427+
val organization: String? = null,
428+
@QueryParam("startDate")
429+
val startDate: LocalDate? = null,
430+
@QueryParam("endDate")
431+
val endDate: LocalDate? = null,
432+
@QueryParam("tenant") @Trim
433+
val tenant: String? = null,
434+
@QueryParam("manager") @Trim
435+
val manager: String? = null,
436+
@QueryParam("performer") @Trim
437+
val performer: String? = null,
438+
@QueryParam("condition") @Trim
439+
val condition: String? = null,
440+
@QueryParam("onlyNew")
441+
val onlyNew: Boolean? = null,
442+
@QueryParam("name") @Trim
443+
val name: String? = null,
444+
@QueryParam("minQuantity") @Min(0)
445+
val minQuantity: Int? = null,
446+
@QueryParam("maxQuantity") @Min(0)
447+
val maxQuantity: Int? = null,
448+
@QueryParam("minCost") @Min(0)
449+
val minCost: Int? = null,
450+
@QueryParam("maxCost") @Min(0)
451+
val maxCost: Int? = null,
452+
@QueryParam("inStock")
453+
val inStock: Boolean? = null,
454+
@QueryParam("active")
455+
val active: Boolean? = null,
456+
457+
@QueryParam("employeeName") @Trim
458+
val employeeName: String? = null,
459+
460+
@QueryParam("sortToken")
461+
@StringExample("fullName") @Trim
462+
val sortToken: String? = null,
463+
@QueryParam("pageSize")
464+
@Min(1)
465+
val pageSize: Int? = null,
466+
@QueryParam("page")
467+
@Min(0)
468+
val page: Long? = 0
469+
)
415470
}

0 commit comments

Comments
 (0)