io.javalin.plugin.openapi.external.KotlinOpenApiDsl.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of javalin Show documentation
Show all versions of javalin Show documentation
Javalin: Simple REST APIs for Java and Kotlin
package io.javalin.plugin.openapi.external
import io.swagger.v3.core.converter.ModelConverters
import io.swagger.v3.oas.models.Components
import io.swagger.v3.oas.models.examples.Example
import io.swagger.v3.oas.models.media.ArraySchema
import io.swagger.v3.oas.models.media.BooleanSchema
import io.swagger.v3.oas.models.media.Content
import io.swagger.v3.oas.models.media.DateSchema
import io.swagger.v3.oas.models.media.DateTimeSchema
import io.swagger.v3.oas.models.media.IntegerSchema
import io.swagger.v3.oas.models.media.MapSchema
import io.swagger.v3.oas.models.media.MediaType
import io.swagger.v3.oas.models.media.Schema
import io.swagger.v3.oas.models.media.StringSchema
import io.swagger.v3.oas.models.parameters.Parameter
import java.math.BigDecimal
import java.time.LocalDate
import java.time.LocalDateTime
import java.util.*
// The original functions are in https://github.com/derveloper/kotlin-openapi3-dsl/blob/master/src/main/kotlin/cc/vileda/openapi/dsl/OpenApiDsl.kt
// I needed to create a copy of all the inline functions, as it is not possible to call kotlin inline function from java code
internal fun Components.schema(clazz: Class) {
schema(clazz) {}
}
internal fun Components.schema(clazz: Class, init: Schema<*>.() -> Unit) {
if (schemas == null) {
schemas = mutableMapOf()
}
val schema = findSchema(clazz)
schema?.main?.init()
schema?.all?.forEach { (key, schema) ->
schemas[key] = schema
}
}
internal fun Parameter.schema(clazz: Class, init: Schema<*>.() -> Unit) {
schema = findSchema(clazz)?.main
schema.init()
}
internal fun Parameter.schema(clazz: Class) {
schema = findSchema(clazz)?.main
}
internal fun mediaType(clazz: Class): MediaType {
val mediaType = MediaType()
val modelSchema = findSchema(clazz)?.main
mediaType.schema = modelSchema
return mediaType
}
/**
* This helper is not in the original library.
* Because it is not possible to create a list instance of an unknown type we need a separate method for that.
*/
internal fun mediaTypeOfList(): MediaType {
val mediaType = MediaType()
val modelSchema = ArraySchema()
mediaType.schema = modelSchema
return mediaType
}
internal fun mediaTypeRef(clazz: Class): MediaType {
val mediaType = MediaType()
mediaType.schema = Schema()
mediaType.schema.`$ref` = clazz.simpleName
return mediaType
}
internal fun Content.mediaTypeRef(clazz: Class, name: String) {
val mediaType = mediaTypeRef(clazz)
addMediaType(name, mediaType)
}
internal fun Content.mediaType(clazz: Class, name: String) {
val mediaType = mediaType(clazz)
addMediaType(name, mediaType)
}
internal fun Content.mediaTypeArrayOfRef(clazz: Class, name: String) {
val mediaTypeArray = mediaTypeOfList()
val mediaTypeObj = mediaTypeRef(clazz)
(mediaTypeArray.schema as ArraySchema).items(mediaTypeObj.schema)
addMediaType(name, mediaTypeArray)
}
internal fun Content.mediaTypeArrayOf(clazz: Class, name: String) {
val mediaTypeArray = mediaTypeOfList()
val mediaTypeObj = mediaType(clazz)
(mediaTypeArray.schema as ArraySchema).items(mediaTypeObj.schema)
addMediaType(name, mediaTypeArray)
}
internal data class FindSchemaResponse(
/** The main schema that is requested */
val main: Schema<*>,
/** All schemas that are used by the main schema */
val all: Map> = mapOf()
)
internal fun findSchema(clazz: Class): FindSchemaResponse? {
getEnumSchema(clazz)?.let {
return FindSchemaResponse(it)
}
return when (clazz) {
String::class.java -> FindSchemaResponse(StringSchema())
Boolean::class.java -> FindSchemaResponse(BooleanSchema())
java.lang.Boolean::class.java -> FindSchemaResponse(BooleanSchema())
Int::class.java -> FindSchemaResponse(IntegerSchema())
Integer::class.java -> FindSchemaResponse(IntegerSchema())
List::class.java -> FindSchemaResponse(ArraySchema())
Map::class.java -> FindSchemaResponse(MapSchema())
Long::class.java -> FindSchemaResponse(IntegerSchema().format("int64"))
BigDecimal::class.java -> FindSchemaResponse(IntegerSchema().format(""))
Date::class.java -> FindSchemaResponse(DateSchema())
LocalDate::class.java -> FindSchemaResponse(DateSchema())
LocalDateTime::class.java -> FindSchemaResponse(DateTimeSchema())
/* BEGIN Custom classes */
ByteArray::class.java -> FindSchemaResponse(StringSchema().format("binary"))
/* END Custom classes */
else -> {
val schemas = ModelConverters.getInstance().readAll(clazz)
schemas[clazz.simpleName]?.let { FindSchemaResponse(it, schemas) }
}
}
}
internal fun getEnumSchema(clazz: Class): Schema<*>? {
val values = clazz.enumConstants ?: return null
val schema = StringSchema()
for (enumVal in values) {
schema.addEnumItem(enumVal.toString())
}
return schema
}
internal fun MediaType.example(clazz: Class, value: T, init: Example.() -> Unit) {
if (examples == null) {
examples = mutableMapOf()
}
val example = Example()
example.value = value
example.init()
examples[clazz.simpleName] = example
}