Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ object DeepBuilderFactory : BuilderSelectorFactory<Builder<QueryParamStyle>, Que
ListDeepBuilder,
ArrayDeepBuilder,
MapDeepBuilder,
OptionalDeepBuilder,
ObjectDeepBuilder
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package com.papsign.ktor.openapigen.parameters.parsers.builders.query.deepobject

import com.papsign.ktor.openapigen.parameters.parsers.builders.BuilderSelector
import com.papsign.ktor.openapigen.parameters.parsers.converters.Converter
import com.papsign.ktor.openapigen.parameters.parsers.converters.ConverterFactory
import java.util.*
import kotlin.reflect.KType
import kotlin.reflect.full.isSubclassOf
import kotlin.reflect.jvm.jvmErasure

class OptionalDeepBuilder(type: KType) : DeepBuilder {
private val converter: Converter = ConverterFactory.buildConverterForced(type.arguments[0].type!!)

override fun build(key: String, parameters: Map<String, List<String>>): Any? {
return parameters[key]?.let { it[0] }?.let { value ->
when (value) {
"" -> Optional.empty()
"null" -> Optional.empty()
else -> Optional.ofNullable(converter.convert(value))
}
}
}


companion object : BuilderSelector<OptionalDeepBuilder> {
override fun canHandle(type: KType, explode: Boolean): Boolean {
return type.jvmErasure.isSubclassOf(Optional::class)
}

override fun create(type: KType, explode: Boolean): OptionalDeepBuilder {
return OptionalDeepBuilder(type)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.papsign.ktor.openapigen.parameters.parsers.converters

import com.papsign.ktor.openapigen.parameters.parsers.converters.`object`.MapConverter
import com.papsign.ktor.openapigen.parameters.parsers.converters.`object`.ObjectConverter
import com.papsign.ktor.openapigen.parameters.parsers.converters.`object`.OptionalConverter
import com.papsign.ktor.openapigen.parameters.parsers.converters.collection.ArrayConverter
import com.papsign.ktor.openapigen.parameters.parsers.converters.collection.ListConverter
import com.papsign.ktor.openapigen.parameters.parsers.converters.primitive.EnumConverter
Expand All @@ -18,6 +19,7 @@ interface ConverterFactory {
ListConverter,
ArrayConverter,
MapConverter,
OptionalConverter,
ObjectConverter
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.papsign.ktor.openapigen.parameters.parsers.converters.`object`

import com.papsign.ktor.openapigen.parameters.parsers.converters.Converter
import com.papsign.ktor.openapigen.parameters.parsers.converters.ConverterFactory
import com.papsign.ktor.openapigen.parameters.parsers.converters.ConverterSelector
import java.util.*
import kotlin.reflect.KType
import kotlin.reflect.full.isSubclassOf
import kotlin.reflect.jvm.jvmErasure

class OptionalConverter(type: KType) : Converter {
private val converter: Converter = ConverterFactory.buildConverterForced(type.arguments[0].type!!)

override fun convert(value: String): Any? {
return when (value) {
"" -> Optional.empty()
"null" -> Optional.empty()
else -> Optional.ofNullable(converter.convert(value))
}
}


companion object : ConverterSelector {
override fun canHandle(type: KType): Boolean {
return type.jvmErasure.isSubclassOf(Optional::class)
}

override fun create(type: KType): OptionalConverter {
return OptionalConverter(type)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import java.util.*
import kotlin.Comparator
import kotlin.reflect.KType
import kotlin.reflect.full.findAnnotation
import kotlin.reflect.full.isSubclassOf
import kotlin.reflect.full.isSubtypeOf
import kotlin.reflect.full.withNullability
import kotlin.reflect.jvm.jvmErasure

object FinalSchemaBuilderProvider: FinalSchemaBuilderProviderModule, OpenAPIGenModuleExtension {
Expand Down Expand Up @@ -63,10 +65,17 @@ object FinalSchemaBuilderProvider: FinalSchemaBuilderProviderModule, OpenAPIGenM
}

override fun build(type: KType, annotations: List<Annotation>): SchemaModel<*> {
return map.getOrPut(type) {
map.entries.firstOrNull { type.isSubtypeOf(it.key) }?.value
?: error("Schema builder could not find declared builder for type $type, make sure it has a provider registered on the route")
}.build(type, this) { it.applyAnnotations(type, type.jvmErasure.annotations).applyAnnotations(type, type.annotations).applyAnnotations(type, annotations) }
type.let {
when {
type.jvmErasure.isSubclassOf(Optional::class) -> type.arguments[0].type!!.withNullability(true)
else -> type
}
}.let { type ->
return map.getOrPut(type) {
map.entries.firstOrNull { type.isSubtypeOf(it.key) }?.value
?: error("Schema builder could not find declared builder for type $type, make sure it has a provider registered on the route")
}.build(type, this) { it.applyAnnotations(type, type.jvmErasure.annotations).applyAnnotations(type, type.annotations).applyAnnotations(type, annotations) }
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package com.papsign.ktor.openapigen.parameters.parsers.builder.query.form

import com.papsign.ktor.openapigen.parameters.parsers.builders.query.form.FormBuilderFactory
import com.papsign.ktor.openapigen.parameters.parsers.testSelector
import org.junit.Test
import java.util.*

class OptionalBuilderTest {

@Test
fun testFilledValue() {
val key = "key"
val expected = Optional.of(1)
val parse = mapOf(
key to listOf("1")
)
FormBuilderFactory.testSelector(expected, key, parse, true)
}

@Test
fun testEmptyValue() {
val key = "key"
val expected = Optional.empty<Int>()
val parse = mapOf(
key to listOf("")
)
FormBuilderFactory.testSelector(expected, key, parse, true)
}

@Test
fun testExplicitNullValue() {
val key = "key"
val expected = Optional.empty<Int>()
val parse = mapOf(
key to listOf("null")
)
FormBuilderFactory.testSelector(expected, key, parse, true)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.papsign.ktor.openapigen.parameters.parsers.builders.query.deepobject

import com.papsign.ktor.openapigen.parameters.parsers.testSelector
import org.junit.Test
import java.util.*

class OptionalBuilderTest {

@Test
fun testFilledValue() {
val key = "key"
val expected = Optional.of(1)
val parse = mapOf(
key to listOf("1")
)
DeepBuilderFactory.testSelector(expected, key, parse, true)
}

@Test
fun testEmptyValue() {
val key = "key"
val expected = Optional.empty<Int>()
val parse = mapOf(
key to listOf("")
)
DeepBuilderFactory.testSelector(expected, key, parse, true)
}

@Test
fun testExplicitNullValue() {
val key = "key"
val expected = Optional.empty<Int>()
val parse = mapOf(
key to listOf("null")
)
DeepBuilderFactory.testSelector(expected, key, parse, true)
}
}