diff --git a/.github/workflows/samples-kotlin-server.yaml b/.github/workflows/samples-kotlin-server.yaml index b98d4c69532a..be8be39d2f57 100644 --- a/.github/workflows/samples-kotlin-server.yaml +++ b/.github/workflows/samples-kotlin-server.yaml @@ -29,6 +29,7 @@ jobs: sample: # server - samples/server/petstore/kotlin-springboot + - samples/server/petstore/kotlin-springboot-multipart-request-model - samples/server/petstore/kotlin-springboot-bigdecimal-default - samples/server/petstore/kotlin-springboot-delegate - samples/server/petstore/kotlin-springboot-modelMutable diff --git a/bin/configs/kotlin-spring-boot-multipart-request-model.yaml b/bin/configs/kotlin-spring-boot-multipart-request-model.yaml new file mode 100644 index 000000000000..63d0b59fd5bb --- /dev/null +++ b/bin/configs/kotlin-spring-boot-multipart-request-model.yaml @@ -0,0 +1,5 @@ +generatorName: kotlin-spring +outputDir: samples/server/petstore/kotlin-springboot-multipart-request-model +library: spring-boot +inputSpec: modules/openapi-generator/src/test/resources/3_0/issue_15251_multipart_request_model.yaml +templateDir: modules/openapi-generator/src/main/resources/kotlin-spring diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/formParams.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/formParams.mustache index 6d725334a165..3d1a5787e382 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-spring/formParams.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/formParams.mustache @@ -1 +1 @@ -{{#isFormParam}}{{^isFile}}{{#swagger2AnnotationLibrary}}@Parameter(description = "{{{description}}}"{{#required}}, required = true{{/required}}{{#allowableValues}}{{#defaultValue}}, schema = Schema(allowableValues = [{{#values}}"{{{.}}}"{{^-last}}, {{/-last}}{{/values}}]{{^isContainer}}, defaultValue = {{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{/isContainer}}){{/defaultValue}}{{/allowableValues}}{{#allowableValues}}{{^defaultValue}}, schema = Schema(allowableValues = [{{#values}}"{{{.}}}"{{^-last}}, {{/-last}}{{/values}}]){{/defaultValue}}{{/allowableValues}}{{^allowableValues}}{{#defaultValue}}{{^isContainer}}, schema = Schema(defaultValue = {{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}){{/isContainer}}{{/defaultValue}}{{/allowableValues}}){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}@ApiParam(value = "{{{description}}}"{{#required}}, required = true{{/required}}{{#allowableValues}}, allowableValues = "{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}"{{/allowableValues}}{{#defaultValue}}, defaultValue = "{{{.}}}"{{/defaultValue}}){{/swagger1AnnotationLibrary}} @RequestParam(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}) {{{paramName}}}: {{>optionalDataType}} {{/isFile}}{{#isFile}}{{#swagger2AnnotationLibrary}}@Parameter(description = "{{{description}}}"){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}@ApiParam(value = "file detail"){{/swagger1AnnotationLibrary}} {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestPart("{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}) {{{paramName}}}: {{>optionalDataType}}{{/isFile}}{{/isFormParam}} \ No newline at end of file +{{#isFormParam}}{{^isFile}}{{#swagger2AnnotationLibrary}}@Parameter(description = "{{{description}}}"{{#required}}, required = true{{/required}}{{#allowableValues}}{{#defaultValue}}, schema = Schema(allowableValues = [{{#values}}"{{{.}}}"{{^-last}}, {{/-last}}{{/values}}]{{^isContainer}}, defaultValue = {{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{/isContainer}}){{/defaultValue}}{{/allowableValues}}{{#allowableValues}}{{^defaultValue}}, schema = Schema(allowableValues = [{{#values}}"{{{.}}}"{{^-last}}, {{/-last}}{{/values}}]){{/defaultValue}}{{/allowableValues}}{{^allowableValues}}{{#defaultValue}}{{^isContainer}}, schema = Schema(defaultValue = {{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}{{{defaultValue}}}{{^isString}}"{{/isString}}{{#isString}}{{#isEnum}}"{{/isEnum}}{{/isString}}){{/isContainer}}{{/defaultValue}}{{/allowableValues}}){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}@ApiParam(value = "{{{description}}}"{{#required}}, required = true{{/required}}{{#allowableValues}}, allowableValues = "{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{/values}}"{{/allowableValues}}{{#defaultValue}}, defaultValue = "{{{.}}}"{{/defaultValue}}){{/swagger1AnnotationLibrary}} {{#isModel}}@RequestPart{{/isModel}}{{^isModel}}@RequestParam{{/isModel}}(value = "{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}) {{{paramName}}}: {{>optionalDataType}} {{/isFile}}{{#isFile}}{{#swagger2AnnotationLibrary}}@Parameter(description = "{{{description}}}"){{/swagger2AnnotationLibrary}}{{#swagger1AnnotationLibrary}}@ApiParam(value = "file detail"){{/swagger1AnnotationLibrary}} {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestPart("{{baseName}}"{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}) {{{paramName}}}: {{>optionalDataType}}{{/isFile}}{{/isFormParam}} \ No newline at end of file diff --git a/modules/openapi-generator/src/test/resources/3_0/issue_15251_multipart_request_model.yaml b/modules/openapi-generator/src/test/resources/3_0/issue_15251_multipart_request_model.yaml new file mode 100644 index 000000000000..5a95b5437182 --- /dev/null +++ b/modules/openapi-generator/src/test/resources/3_0/issue_15251_multipart_request_model.yaml @@ -0,0 +1,45 @@ +openapi: '3.0.1' +info: + version: 1.0.0 + title: MultipartFile test +paths: + /multipart-mixed: + post: + tags: + - multipart + description: Mixed MultipartFile test + operationId: multipartMixed + requestBody: + content: + multipart/form-data: + schema: + type: object + required: + - status + - file + properties: + status: + $ref: '#/components/schemas/MultipartMixedStatus' + marker: + description: "additional object" + type: object + properties: + name: + type: string + file: + description: "a file" + type: string + format: binary + responses: + '204': + description: Successful operation +components: + schemas: + MultipartMixedStatus: + description: "additional field as Enum" + type: string + enum: + - ALLOWED + - IN_PROGRESS + - REJECTED + example: REJECTED \ No newline at end of file diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/.openapi-generator-ignore b/samples/server/petstore/kotlin-springboot-multipart-request-model/.openapi-generator-ignore new file mode 100644 index 000000000000..7484ee590a38 --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/.openapi-generator/FILES b/samples/server/petstore/kotlin-springboot-multipart-request-model/.openapi-generator/FILES new file mode 100644 index 000000000000..0afcf84b1ed1 --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/.openapi-generator/FILES @@ -0,0 +1,14 @@ +README.md +build.gradle.kts +pom.xml +settings.gradle +src/main/kotlin/org/openapitools/Application.kt +src/main/kotlin/org/openapitools/HomeController.kt +src/main/kotlin/org/openapitools/SpringDocConfiguration.kt +src/main/kotlin/org/openapitools/api/ApiUtil.kt +src/main/kotlin/org/openapitools/api/Exceptions.kt +src/main/kotlin/org/openapitools/api/MultipartMixedApiController.kt +src/main/kotlin/org/openapitools/model/MultipartMixedRequestMarker.kt +src/main/kotlin/org/openapitools/model/MultipartMixedStatus.kt +src/main/resources/application.yaml +src/main/resources/openapi.yaml diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/.openapi-generator/VERSION b/samples/server/petstore/kotlin-springboot-multipart-request-model/.openapi-generator/VERSION new file mode 100644 index 000000000000..6116b14d2c59 --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.8.0-SNAPSHOT diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/README.md b/samples/server/petstore/kotlin-springboot-multipart-request-model/README.md new file mode 100644 index 000000000000..15d74ea2ce25 --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/README.md @@ -0,0 +1,21 @@ +# multipartFileTest + +This Kotlin based [Spring Boot](https://spring.io/projects/spring-boot) application has been generated using the [OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator). + +## Getting Started + +This document assumes you have either maven or gradle available, either via the wrapper or otherwise. This does not come with a gradle / maven wrapper checked in. + +By default a [`pom.xml`](pom.xml) file will be generated. If you specified `gradleBuildFile=true` when generating this project, a `build.gradle.kts` will also be generated. Note this uses [Gradle Kotlin DSL](https://github.com/gradle/kotlin-dsl). + +To build the project using maven, run: +```bash +mvn package && java -jar target/openapi-spring-1.0.0.jar +``` + +To build the project using gradle, run: +```bash +gradle build && java -jar build/libs/openapi-spring-1.0.0.jar +``` + +If all builds successfully, the server should run on [http://localhost:8080/](http://localhost:8080/) diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/build.gradle.kts b/samples/server/petstore/kotlin-springboot-multipart-request-model/build.gradle.kts new file mode 100644 index 000000000000..45a8ef30f3ef --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/build.gradle.kts @@ -0,0 +1,50 @@ +import org.jetbrains.kotlin.gradle.tasks.KotlinCompile + +buildscript { + repositories { + mavenCentral() + } + dependencies { + classpath("org.springframework.boot:spring-boot-gradle-plugin:2.6.7") + } +} + +group = "org.openapitools" +version = "1.0.0" + +repositories { + mavenCentral() +} + +tasks.withType { + kotlinOptions.jvmTarget = "1.8" +} + +plugins { + val kotlinVersion = "1.6.21" + id("org.jetbrains.kotlin.jvm") version kotlinVersion + id("org.jetbrains.kotlin.plugin.jpa") version kotlinVersion + id("org.jetbrains.kotlin.plugin.spring") version kotlinVersion + id("org.springframework.boot") version "2.6.7" + id("io.spring.dependency-management") version "1.0.11.RELEASE" +} + +dependencies { + compile("org.jetbrains.kotlin:kotlin-stdlib-jdk8") + compile("org.jetbrains.kotlin:kotlin-reflect") + compile("org.springframework.boot:spring-boot-starter-web") + compile("org.springdoc:springdoc-openapi-ui:1.6.8") + + compile("com.google.code.findbugs:jsr305:3.0.2") + compile("com.fasterxml.jackson.dataformat:jackson-dataformat-yaml") + compile("com.fasterxml.jackson.dataformat:jackson-dataformat-xml") + compile("com.fasterxml.jackson.datatype:jackson-datatype-jsr310") + compile("com.fasterxml.jackson.module:jackson-module-kotlin") + compile("jakarta.validation:jakarta.validation-api") + compile("jakarta.annotation:jakarta.annotation-api:2.1.0") + + testCompile("org.jetbrains.kotlin:kotlin-test-junit5") + testCompile("org.springframework.boot:spring-boot-starter-test") { + exclude(module = "junit") + } +} diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/pom.xml b/samples/server/petstore/kotlin-springboot-multipart-request-model/pom.xml new file mode 100644 index 000000000000..a44254101c24 --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/pom.xml @@ -0,0 +1,136 @@ + + 4.0.0 + org.openapitools + openapi-spring + jar + openapi-spring + 1.0.0 + + 1.6.8 + 3.0.2 + 2.1.0 + 1.6.21 + + 1.6.21 + UTF-8 + + + org.springframework.boot + spring-boot-starter-parent + 2.7.15 + + + ${project.basedir}/src/main/kotlin + ${project.basedir}/src/test/kotlin + + + org.springframework.boot + spring-boot-maven-plugin + + + + repackage + + + + + + kotlin-maven-plugin + org.jetbrains.kotlin + ${kotlin.version} + + + spring + + 1.8 + + + + compile + compile + + compile + + + + test-compile + test-compile + + test-compile + + + + + + org.jetbrains.kotlin + kotlin-maven-allopen + ${kotlin.version} + + + + + + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + ${kotlin.version} + + + org.jetbrains.kotlin + kotlin-reflect + ${kotlin.version} + + + org.springframework.boot + spring-boot-starter-web + + + + + org.springdoc + springdoc-openapi-ui + ${springdoc-openapi.version} + + + + + com.google.code.findbugs + jsr305 + ${findbugs-jsr305.version} + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + + + com.fasterxml.jackson.dataformat + jackson-dataformat-xml + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + com.fasterxml.jackson.module + jackson-module-kotlin + + + + jakarta.validation + jakarta.validation-api + + + jakarta.annotation + jakarta.annotation-api + ${jakarta-annotation.version} + provided + + + org.jetbrains.kotlin + kotlin-test-junit5 + ${kotlin-test-junit5.version} + test + + + diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/settings.gradle b/samples/server/petstore/kotlin-springboot-multipart-request-model/settings.gradle new file mode 100644 index 000000000000..14844905cd40 --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/settings.gradle @@ -0,0 +1,15 @@ +pluginManagement { + repositories { + maven { url = uri("https://repo.spring.io/snapshot") } + maven { url = uri("https://repo.spring.io/milestone") } + gradlePluginPortal() + } + resolutionStrategy { + eachPlugin { + if (requested.id.id == "org.springframework.boot") { + useModule("org.springframework.boot:spring-boot-gradle-plugin:${requested.version}") + } + } + } +} +rootProject.name = "openapi-spring" diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/Application.kt b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/Application.kt new file mode 100644 index 000000000000..2fe6de62479e --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/Application.kt @@ -0,0 +1,13 @@ +package org.openapitools + +import org.springframework.boot.runApplication +import org.springframework.boot.autoconfigure.SpringBootApplication +import org.springframework.context.annotation.ComponentScan + +@SpringBootApplication +@ComponentScan(basePackages = ["org.openapitools", "org.openapitools.api", "org.openapitools.model"]) +class Application + +fun main(args: Array) { + runApplication(*args) +} diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/HomeController.kt b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/HomeController.kt new file mode 100644 index 000000000000..0b75544d7a1e --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/HomeController.kt @@ -0,0 +1,17 @@ +package org.openapitools + +import org.springframework.context.annotation.Bean +import org.springframework.stereotype.Controller +import org.springframework.web.bind.annotation.RequestMapping +import org.springframework.web.bind.annotation.ResponseBody +import org.springframework.web.bind.annotation.GetMapping + +/** + * Home redirection to OpenAPI api documentation + */ +@Controller +class HomeController { + + @RequestMapping("/") + fun index(): String = "redirect:swagger-ui.html" +} diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/SpringDocConfiguration.kt b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/SpringDocConfiguration.kt new file mode 100644 index 000000000000..2e11661edd00 --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/SpringDocConfiguration.kt @@ -0,0 +1,26 @@ +package org.openapitools + +import org.springframework.context.annotation.Bean +import org.springframework.context.annotation.Configuration + +import io.swagger.v3.oas.models.OpenAPI +import io.swagger.v3.oas.models.info.Info +import io.swagger.v3.oas.models.info.Contact +import io.swagger.v3.oas.models.info.License +import io.swagger.v3.oas.models.Components +import io.swagger.v3.oas.models.security.SecurityScheme + +@Configuration +class SpringDocConfiguration { + + @Bean + fun apiInfo(): OpenAPI { + return OpenAPI() + .info( + Info() + .title("MultipartFile test") + .description("No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)") + .version("1.0.0") + ) + } +} diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/api/ApiUtil.kt b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/api/ApiUtil.kt new file mode 100644 index 000000000000..88e892d0f49a --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/api/ApiUtil.kt @@ -0,0 +1,19 @@ +package org.openapitools.api + +import org.springframework.web.context.request.NativeWebRequest + +import javax.servlet.http.HttpServletResponse +import java.io.IOException + +object ApiUtil { + fun setExampleResponse(req: NativeWebRequest, contentType: String, example: String) { + try { + val res = req.getNativeResponse(HttpServletResponse::class.java) + res?.characterEncoding = "UTF-8" + res?.addHeader("Content-Type", contentType) + res?.writer?.print(example) + } catch (e: IOException) { + throw RuntimeException(e) + } + } +} diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/api/Exceptions.kt b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/api/Exceptions.kt new file mode 100644 index 000000000000..44190af7a019 --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/api/Exceptions.kt @@ -0,0 +1,29 @@ +package org.openapitools.api + +import org.springframework.http.HttpStatus +import org.springframework.web.bind.annotation.ControllerAdvice +import org.springframework.web.bind.annotation.ExceptionHandler +import javax.servlet.http.HttpServletResponse +import javax.validation.ConstraintViolationException + +// TODO Extend ApiException for custom exception handling, e.g. the below NotFound exception +sealed class ApiException(msg: String, val code: Int) : Exception(msg) + +class NotFoundException(msg: String, code: Int = HttpStatus.NOT_FOUND.value()) : ApiException(msg, code) + + +@ControllerAdvice +class DefaultExceptionHandler { + + @ExceptionHandler(value = [ApiException::class]) + fun onApiException(ex: ApiException, response: HttpServletResponse): Unit = + response.sendError(ex.code, ex.message) + + @ExceptionHandler(value = [NotImplementedError::class]) + fun onNotImplemented(ex: NotImplementedError, response: HttpServletResponse): Unit = + response.sendError(HttpStatus.NOT_IMPLEMENTED.value()) + + @ExceptionHandler(value = [ConstraintViolationException::class]) + fun onConstraintViolation(ex: ConstraintViolationException, response: HttpServletResponse): Unit = + response.sendError(HttpStatus.BAD_REQUEST.value(), ex.constraintViolations.joinToString(", ") { it.message }) +} diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/api/MultipartMixedApiController.kt b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/api/MultipartMixedApiController.kt new file mode 100644 index 000000000000..a2b304ac2f29 --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/api/MultipartMixedApiController.kt @@ -0,0 +1,52 @@ +package org.openapitools.api + +import org.openapitools.model.MultipartMixedRequestMarker +import org.openapitools.model.MultipartMixedStatus +import io.swagger.v3.oas.annotations.* +import io.swagger.v3.oas.annotations.enums.* +import io.swagger.v3.oas.annotations.media.* +import io.swagger.v3.oas.annotations.responses.* +import io.swagger.v3.oas.annotations.security.* +import org.springframework.http.HttpStatus +import org.springframework.http.MediaType +import org.springframework.http.ResponseEntity + +import org.springframework.web.bind.annotation.* +import org.springframework.validation.annotation.Validated +import org.springframework.web.context.request.NativeWebRequest +import org.springframework.beans.factory.annotation.Autowired + +import javax.validation.Valid +import javax.validation.constraints.DecimalMax +import javax.validation.constraints.DecimalMin +import javax.validation.constraints.Email +import javax.validation.constraints.Max +import javax.validation.constraints.Min +import javax.validation.constraints.NotNull +import javax.validation.constraints.Pattern +import javax.validation.constraints.Size + +import kotlin.collections.List +import kotlin.collections.Map + +@RestController +@Validated +@RequestMapping("\${api.base-path:}") +class MultipartMixedApiController() { + + @Operation( + summary = "", + operationId = "multipartMixed", + description = """Mixed MultipartFile test""", + responses = [ + ApiResponse(responseCode = "204", description = "Successful operation") ] + ) + @RequestMapping( + method = [RequestMethod.POST], + value = ["/multipart-mixed"], + consumes = ["multipart/form-data"] + ) + fun multipartMixed(@Parameter(description = "", required = true, schema = Schema(allowableValues = ["ALLOWED", "IN_PROGRESS", "REJECTED"])) @RequestParam(value = "status", required = true) status: MultipartMixedStatus ,@Parameter(description = "a file") @Valid @RequestPart("file", required = true) file: org.springframework.core.io.Resource,@Parameter(description = "") @RequestPart(value = "marker", required = false) marker: MultipartMixedRequestMarker? ): ResponseEntity { + return ResponseEntity(HttpStatus.NOT_IMPLEMENTED) + } +} diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/model/MultipartMixedRequestMarker.kt b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/model/MultipartMixedRequestMarker.kt new file mode 100644 index 000000000000..1a8f989c9174 --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/model/MultipartMixedRequestMarker.kt @@ -0,0 +1,27 @@ +package org.openapitools.model + +import java.util.Objects +import com.fasterxml.jackson.annotation.JsonProperty +import javax.validation.constraints.DecimalMax +import javax.validation.constraints.DecimalMin +import javax.validation.constraints.Email +import javax.validation.constraints.Max +import javax.validation.constraints.Min +import javax.validation.constraints.NotNull +import javax.validation.constraints.Pattern +import javax.validation.constraints.Size +import javax.validation.Valid +import io.swagger.v3.oas.annotations.media.Schema + +/** + * additional object + * @param name + */ +data class MultipartMixedRequestMarker( + + @Schema(example = "null", description = "") + @get:JsonProperty("name") val name: kotlin.String? = null +) { + +} + diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/model/MultipartMixedStatus.kt b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/model/MultipartMixedStatus.kt new file mode 100644 index 000000000000..ed53fb8b4b48 --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/kotlin/org/openapitools/model/MultipartMixedStatus.kt @@ -0,0 +1,27 @@ +package org.openapitools.model + +import java.util.Objects +import com.fasterxml.jackson.annotation.JsonValue +import com.fasterxml.jackson.annotation.JsonProperty +import javax.validation.constraints.DecimalMax +import javax.validation.constraints.DecimalMin +import javax.validation.constraints.Email +import javax.validation.constraints.Max +import javax.validation.constraints.Min +import javax.validation.constraints.NotNull +import javax.validation.constraints.Pattern +import javax.validation.constraints.Size +import javax.validation.Valid +import io.swagger.v3.oas.annotations.media.Schema + +/** +* additional field as Enum +* Values: ALLOWED,IN_PROGRESS,REJECTED +*/ +enum class MultipartMixedStatus(val value: kotlin.String) { + + @JsonProperty("ALLOWED") ALLOWED("ALLOWED"), + @JsonProperty("IN_PROGRESS") IN_PROGRESS("IN_PROGRESS"), + @JsonProperty("REJECTED") REJECTED("REJECTED") +} + diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/resources/application.yaml b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/resources/application.yaml new file mode 100644 index 000000000000..51bc6d3fb4a4 --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/resources/application.yaml @@ -0,0 +1,10 @@ +spring: + application: + name: multipartFileTest + + jackson: + serialization: + WRITE_DATES_AS_TIMESTAMPS: false + +server: + port: 8080 diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/resources/openapi.yaml b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/resources/openapi.yaml new file mode 100644 index 000000000000..4511aa31f498 --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/main/resources/openapi.yaml @@ -0,0 +1,51 @@ +openapi: 3.0.1 +info: + title: MultipartFile test + version: 1.0.0 +servers: +- url: / +paths: + /multipart-mixed: + post: + description: Mixed MultipartFile test + operationId: multipartMixed + requestBody: + content: + multipart/form-data: + schema: + $ref: '#/components/schemas/multipartMixed_request' + responses: + "204": + description: Successful operation + tags: + - multipart +components: + schemas: + MultipartMixedStatus: + description: additional field as Enum + enum: + - ALLOWED + - IN_PROGRESS + - REJECTED + example: REJECTED + type: string + multipartMixed_request_marker: + description: additional object + properties: + name: + type: string + type: object + multipartMixed_request: + properties: + status: + $ref: '#/components/schemas/MultipartMixedStatus' + marker: + $ref: '#/components/schemas/multipartMixed_request_marker' + file: + description: a file + format: binary + type: string + required: + - file + - status + type: object diff --git a/samples/server/petstore/kotlin-springboot-multipart-request-model/src/test/kotlin/org/openapitools/api/MultipartMixedApiTest.kt b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/test/kotlin/org/openapitools/api/MultipartMixedApiTest.kt new file mode 100644 index 000000000000..6330073d7439 --- /dev/null +++ b/samples/server/petstore/kotlin-springboot-multipart-request-model/src/test/kotlin/org/openapitools/api/MultipartMixedApiTest.kt @@ -0,0 +1,27 @@ +package org.openapitools.api + +import org.openapitools.model.MultipartMixedRequestMarker +import org.openapitools.model.MultipartMixedStatus +import org.junit.jupiter.api.Test +import org.springframework.http.ResponseEntity + +class MultipartMixedApiTest { + + private val api: MultipartMixedApiController = MultipartMixedApiController() + + /** + * To test MultipartMixedApiController.multipartMixed + * + * @throws ApiException + * if the Api call fails + */ + @Test + fun multipartMixedTest() { + val status: MultipartMixedStatus = TODO() + val file: org.springframework.core.io.Resource = TODO() + val marker: MultipartMixedRequestMarker? = TODO() + val response: ResponseEntity = api.multipartMixed(status, file, marker) + + // TODO: test validations + } +}