Skip to content

Commit 59cf5b6

Browse files
authored
Merge pull request #92 from DarkXanteR/feature/copy_params
Using copy method of data class for params instead of changing java field
2 parents f94a2f6 + 989d783 commit 59cf5b6

File tree

2 files changed

+75
-12
lines changed

2 files changed

+75
-12
lines changed

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

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@ import com.papsign.ktor.openapigen.*
44
import com.papsign.ktor.openapigen.classLogger
55
import kotlin.reflect.*
66
import kotlin.reflect.full.*
7-
import kotlin.reflect.jvm.javaField
8-
import kotlin.reflect.jvm.jvmErasure
7+
import kotlin.reflect.jvm.*
98

109

1110
/**
@@ -139,7 +138,7 @@ class ValidationHandler private constructor(
139138
} else {
140139
val appropriateConstructor = type.jvmErasure.constructors.find {
141140
it.parameters.size == 1 && it.parameters[0].type.isSubtypeOf(iterableType)
142-
} ?: error("Unsupported Iterable type $type, must have a constructor that takes an iterable");
141+
} ?: error("Unsupported Iterable type $type, must have a constructor that takes an iterable")
143142
when {
144143
handler.isUseful() && shouldTransform -> {
145144
transformFun = { t: Any? ->
@@ -208,8 +207,7 @@ class ValidationHandler private constructor(
208207
}
209208
else -> {
210209
val handled = type.memberProperties.mapNotNull { prop ->
211-
val validator =
212-
build(prop)
210+
val validator = build(prop)
213211
if (validator.isUseful()) {
214212
prop.source.javaField.also {
215213
if (it == null) {
@@ -236,15 +234,25 @@ class ValidationHandler private constructor(
236234
handled.isNotEmpty() -> {
237235
transformFun = { t: Any? ->
238236
if (t != null) {
237+
val copy = t.javaClass.kotlin.memberFunctions.find { it.name == "copy" }
238+
val copyParams = copy?.instanceParameter?.let { mutableMapOf<KParameter, Any?>(it to t) }
239239
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
240+
val getter = field.kotlinProperty?.javaGetter
241+
if (copy != null && copyParams != null && getter != null) {
242+
val param = copy.parameters.first { it.name == field.name }
243+
copyParams[param] = handler.handle(getter(t))
244+
} else {
245+
// TODO convert this to canAccess and only change status if false
246+
val accessible = field.isAccessible
247+
field.isAccessible = true
248+
field.set(t, handler.handle(field.get(t)))
249+
field.isAccessible = accessible
250+
}
245251
}
246-
}
247-
t
252+
if (copy != null && copyParams != null) {
253+
copy.callBy(copyParams)
254+
} else t
255+
} else t
248256
}
249257
}
250258
shouldTransform -> {

src/test/kotlin/TestServer.kt

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import com.papsign.ktor.openapigen.annotations.type.string.length.Length
2525
import com.papsign.ktor.openapigen.annotations.type.string.length.MaxLength
2626
import com.papsign.ktor.openapigen.annotations.type.string.length.MinLength
2727
import com.papsign.ktor.openapigen.annotations.type.string.pattern.RegularExpression
28+
import com.papsign.ktor.openapigen.annotations.type.string.trim.Trim
2829
import com.papsign.ktor.openapigen.interop.withAPI
2930
import com.papsign.ktor.openapigen.model.Described
3031
import com.papsign.ktor.openapigen.model.server.ServerModel
@@ -235,6 +236,12 @@ object TestServer {
235236
respond(InstantResponse(params.date))
236237
}
237238
}
239+
240+
route("employees") {
241+
get<FilterQuery, FilterQuery> { params ->
242+
respond(params)
243+
}
244+
}
238245
}
239246
}
240247
}
@@ -404,4 +411,52 @@ object TestServer {
404411
data class InstantResponse(val instant: Instant)
405412
data class LocalTimeResponse(val time: LocalTime?)
406413
data class OffsetTimeResponse(val time: OffsetTime?)
414+
415+
data class FilterQuery(
416+
@QueryParam("Vendor Code") @Trim
417+
val vendorCode: String? = null,
418+
@QueryParam("Organization") @Trim
419+
val organization: String? = null,
420+
@QueryParam("startDate")
421+
val startDate: LocalDate? = null,
422+
@QueryParam("endDate")
423+
val endDate: LocalDate? = null,
424+
@QueryParam("tenant") @Trim
425+
val tenant: String? = null,
426+
@QueryParam("manager") @Trim
427+
val manager: String? = null,
428+
@QueryParam("performer") @Trim
429+
val performer: String? = null,
430+
@QueryParam("condition") @Trim
431+
val condition: String? = null,
432+
@QueryParam("onlyNew")
433+
val onlyNew: Boolean? = null,
434+
@QueryParam("name") @Trim
435+
val name: String? = null,
436+
@QueryParam("minQuantity") @Min(0)
437+
val minQuantity: Int? = null,
438+
@QueryParam("maxQuantity") @Min(0)
439+
val maxQuantity: Int? = null,
440+
@QueryParam("minCost") @Min(0)
441+
val minCost: Int? = null,
442+
@QueryParam("maxCost") @Min(0)
443+
val maxCost: Int? = null,
444+
@QueryParam("inStock")
445+
val inStock: Boolean? = null,
446+
@QueryParam("active")
447+
val active: Boolean? = null,
448+
449+
@QueryParam("employeeName") @Trim
450+
val employeeName: String? = null,
451+
452+
@QueryParam("sortToken")
453+
@StringExample("fullName") @Trim
454+
val sortToken: String? = null,
455+
@QueryParam("pageSize")
456+
@Min(1)
457+
val pageSize: Int? = null,
458+
@QueryParam("page")
459+
@Min(0)
460+
val page: Long? = 0
461+
)
407462
}

0 commit comments

Comments
 (0)