diff --git a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java index d106870887fe..8536e099ca4a 100644 --- a/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java +++ b/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/KotlinSpringServerCodegen.java @@ -44,7 +44,7 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen LoggerFactory.getLogger(KotlinSpringServerCodegen.class); private static final HashSet VARIABLE_RESERVED_WORDS = - new HashSet(Arrays.asList( + new HashSet<>(Arrays.asList( "ApiClient", "ApiException", "ApiResponse" @@ -109,6 +109,10 @@ public KotlinSpringServerCodegen() { importMapping.put("Date", "java.time.LocalDate"); importMapping.put("DateTime", "java.time.OffsetDateTime"); + // use resource for file handling + typeMapping.put("file", "org.springframework.core.io.Resource"); + + languageSpecificPrimitives.addAll(Arrays.asList( "Any", "Byte", @@ -562,4 +566,33 @@ public CodegenModel fromModel(String name, Schema schema) { return m; } + + /** + * Output the proper model name (capitalized). + * In case the name belongs to the TypeSystem it won't be renamed. + * + * @param name the name of the model + * @return capitalized model name + */ + @Override + public String toModelName(final String name) { + // Allow for explicitly configured spring.* + if (name.startsWith("org.springframework.") ) { + return name; + } + return super.toModelName(name); + } + + /** + * Check the type to see if it needs import the library/module/package + * + * @param type name of the type + * @return true if the library/module/package of the corresponding type needs to be imported + */ + @Override + protected boolean needToImport(String type) { + // provides extra protection against improperly trying to import language primitives and java types + boolean imports = !type.startsWith("org.springframework.") && super.needToImport(type); + return imports; + } } diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache index d8e69eb72f63..65f1f78b0659 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/api.mustache @@ -20,7 +20,6 @@ import org.springframework.web.bind.annotation.RequestMapping import org.springframework.validation.annotation.Validated {{/useBeanValidation}} import org.springframework.web.context.request.NativeWebRequest -import org.springframework.web.multipart.MultipartFile import org.springframework.beans.factory.annotation.Autowired {{#useBeanValidation}} 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 f7b992616a21..f66ddb631ee1 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}}{{#swaggerAnnotations}}@ApiParam(value = "{{{description}}}"{{#required}}, required=true{{/required}}{{#allowableValues}}, allowableValues="{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}){{/swaggerAnnotations}} @RequestParam(value="{{baseName}}"{{#required}}, required=true{{/required}}{{^required}}, required=false{{/required}}) {{paramName}}: {{>optionalDataType}} {{/isFile}}{{#isFile}}{{#swaggerAnnotations}}@ApiParam(value = "file detail"){{/swaggerAnnotations}} {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestPart("file") {{baseName}}: MultipartFile{{/isFile}}{{/isFormParam}} \ No newline at end of file +{{#isFormParam}}{{^isFile}}{{#swaggerAnnotations}}@ApiParam(value = "{{{description}}}"{{#required}}, required=true{{/required}}{{#allowableValues}}, allowableValues="{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/allowableValues}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}){{/swaggerAnnotations}} @RequestParam(value="{{baseName}}"{{#required}}, required=true{{/required}}{{^required}}, required=false{{/required}}) {{paramName}}: {{>optionalDataType}} {{/isFile}}{{#isFile}}{{#swaggerAnnotations}}@ApiParam(value = "file detail"){{/swaggerAnnotations}} {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestPart("file") {{baseName}}: {{>optionalDataType}}{{/isFile}}{{/isFormParam}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/service.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/service.mustache index 32bb190ea6b4..37892a1f5347 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-spring/service.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/service.mustache @@ -7,7 +7,7 @@ package {{package}} interface {{classname}}Service { {{#operation}} - fun {{operationId}}({{#allParams}}{{paramName}}: {{^isFile}}{{>optionalDataType}}{{/isFile}}{{#isFile}}org.springframework.web.multipart.MultipartFile{{/isFile}}{{#hasMore}},{{/hasMore}}{{/allParams}}): {{>returnTypes}} + fun {{operationId}}({{#allParams}}{{paramName}}: {{{dataType}}}{{#hasMore}},{{/hasMore}}{{/allParams}}): {{>returnTypes}} {{/operation}} } {{/operations}} diff --git a/modules/openapi-generator/src/main/resources/kotlin-spring/serviceImpl.mustache b/modules/openapi-generator/src/main/resources/kotlin-spring/serviceImpl.mustache index d3dcedb061e2..134600ecfc09 100644 --- a/modules/openapi-generator/src/main/resources/kotlin-spring/serviceImpl.mustache +++ b/modules/openapi-generator/src/main/resources/kotlin-spring/serviceImpl.mustache @@ -3,13 +3,12 @@ package {{package}} {{#imports}}import {{import}} {{/imports}} import org.springframework.stereotype.Service - @Service {{#operations}} class {{classname}}ServiceImpl : {{classname}}Service { {{#operation}} - override fun {{operationId}}({{#allParams}}{{paramName}}: {{^isFile}}{{>optionalDataType}}{{/isFile}}{{#isFile}}org.springframework.web.multipart.MultipartFile{{/isFile}}{{#hasMore}},{{/hasMore}}{{/allParams}}): {{>returnTypes}} { + override fun {{operationId}}({{#allParams}}{{paramName}}: {{{dataType}}}{{#hasMore}},{{/hasMore}}{{/allParams}}): {{>returnTypes}} { TODO("Implement me") } {{/operation}} diff --git a/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/PetApi.kt b/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/PetApi.kt index ba2288eab267..12fa10fb8131 100644 --- a/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/PetApi.kt +++ b/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/PetApi.kt @@ -16,7 +16,6 @@ import org.springframework.web.bind.annotation.RequestMethod import org.springframework.web.bind.annotation.RequestMapping import org.springframework.validation.annotation.Validated import org.springframework.web.context.request.NativeWebRequest -import org.springframework.web.multipart.MultipartFile import org.springframework.beans.factory.annotation.Autowired import javax.validation.Valid @@ -71,7 +70,7 @@ class PetApiController(@Autowired(required = true) val service: PetApiService) { value = [ApiResponse(code = 200, message = "successful operation", response = Pet::class, responseContainer = "List"),ApiResponse(code = 400, message = "Invalid status value")]) @RequestMapping( value = ["/pet/findByStatus"], - produces = ["application/xml", "application/json"], + produces = ["application/xml", "application/json"], method = [RequestMethod.GET]) fun findPetsByStatus(@NotNull @ApiParam(value = "Status values that need to be considered for filter", required = true, allowableValues = "available, pending, sold") @Valid @RequestParam(value = "status", required = true) status: List): ResponseEntity> { return ResponseEntity(service.findPetsByStatus(status), HttpStatus.OK) @@ -88,7 +87,7 @@ class PetApiController(@Autowired(required = true) val service: PetApiService) { value = [ApiResponse(code = 200, message = "successful operation", response = Pet::class, responseContainer = "List"),ApiResponse(code = 400, message = "Invalid tag value")]) @RequestMapping( value = ["/pet/findByTags"], - produces = ["application/xml", "application/json"], + produces = ["application/xml", "application/json"], method = [RequestMethod.GET]) fun findPetsByTags(@NotNull @ApiParam(value = "Tags to filter by", required = true) @Valid @RequestParam(value = "tags", required = true) tags: List): ResponseEntity> { return ResponseEntity(service.findPetsByTags(tags), HttpStatus.OK) @@ -104,7 +103,7 @@ class PetApiController(@Autowired(required = true) val service: PetApiService) { value = [ApiResponse(code = 200, message = "successful operation", response = Pet::class),ApiResponse(code = 400, message = "Invalid ID supplied"),ApiResponse(code = 404, message = "Pet not found")]) @RequestMapping( value = ["/pet/{petId}"], - produces = ["application/xml", "application/json"], + produces = ["application/xml", "application/json"], method = [RequestMethod.GET]) fun getPetById(@ApiParam(value = "ID of pet to return", required=true) @PathVariable("petId") petId: Long): ResponseEntity { return ResponseEntity(service.getPetById(petId), HttpStatus.OK) @@ -136,7 +135,7 @@ class PetApiController(@Autowired(required = true) val service: PetApiService) { value = ["/pet/{petId}"], consumes = ["application/x-www-form-urlencoded"], method = [RequestMethod.POST]) - fun updatePetWithForm(@ApiParam(value = "ID of pet that needs to be updated", required=true) @PathVariable("petId") petId: Long,@ApiParam(value = "Updated name of the pet") @RequestParam(value="name", required=false) name: String? ,@ApiParam(value = "Updated status of the pet") @RequestParam(value="status", required=false) status: String? ): ResponseEntity { + fun updatePetWithForm(@ApiParam(value = "ID of pet that needs to be updated", required=true, defaultValue="null") @PathVariable("petId") petId: Long,@ApiParam(value = "Updated name of the pet", defaultValue="null") @RequestParam(value="name", required=false) name: String,@ApiParam(value = "Updated status of the pet", defaultValue="null") @RequestParam(value="status", required=false) status: String): ResponseEntity { return ResponseEntity(service.updatePetWithForm(petId, name, status), HttpStatus.OK) } @@ -150,10 +149,10 @@ class PetApiController(@Autowired(required = true) val service: PetApiService) { value = [ApiResponse(code = 200, message = "successful operation", response = ModelApiResponse::class)]) @RequestMapping( value = ["/pet/{petId}/uploadImage"], - produces = ["application/json"], + produces = ["application/json"], consumes = ["multipart/form-data"], method = [RequestMethod.POST]) - fun uploadFile(@ApiParam(value = "ID of pet to update", required=true) @PathVariable("petId") petId: Long,@ApiParam(value = "Additional data to pass to server") @RequestParam(value="additionalMetadata", required=false) additionalMetadata: String? ,@ApiParam(value = "file detail") @Valid @RequestPart("file") file: MultipartFile): ResponseEntity { + fun uploadFile(@ApiParam(value = "ID of pet to update", required=true, defaultValue="null") @PathVariable("petId") petId: Long,@ApiParam(value = "Additional data to pass to server", defaultValue="null") @RequestParam(value="additionalMetadata", required=false) additionalMetadata: String,@ApiParam(value = "file detail") @Valid @RequestPart("file") file: org.springframework.core.io.Resource): ResponseEntity { return ResponseEntity(service.uploadFile(petId, additionalMetadata, file), HttpStatus.OK) } } diff --git a/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/PetApiService.kt b/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/PetApiService.kt index 0739400906a3..0bfa0e37170b 100644 --- a/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/PetApiService.kt +++ b/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/PetApiService.kt @@ -19,5 +19,5 @@ interface PetApiService { fun updatePetWithForm(petId: Long,name: String?,status: String?): Unit - fun uploadFile(petId: Long,additionalMetadata: String?,file: org.springframework.web.multipart.MultipartFile): ModelApiResponse + fun uploadFile(petId: Long,additionalMetadata: String,file: org.springframework.core.io.Resource): ModelApiResponse } diff --git a/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/PetApiServiceImpl.kt b/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/PetApiServiceImpl.kt index a08aa01cf1c8..e481c6b86b15 100644 --- a/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/PetApiServiceImpl.kt +++ b/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/PetApiServiceImpl.kt @@ -3,7 +3,6 @@ package org.openapitools.api import org.openapitools.model.ModelApiResponse import org.openapitools.model.Pet import org.springframework.stereotype.Service - @Service class PetApiServiceImpl : PetApiService { @@ -35,7 +34,7 @@ class PetApiServiceImpl : PetApiService { TODO("Implement me") } - override fun uploadFile(petId: Long,additionalMetadata: String?,file: org.springframework.web.multipart.MultipartFile): ModelApiResponse { + override fun uploadFile(petId: Long,additionalMetadata: String,file: org.springframework.core.io.Resource): ModelApiResponse { TODO("Implement me") } } diff --git a/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/StoreApi.kt b/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/StoreApi.kt index a2584ddcfd50..19e94e499bcc 100644 --- a/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/StoreApi.kt +++ b/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/StoreApi.kt @@ -15,7 +15,6 @@ import org.springframework.web.bind.annotation.RequestMethod import org.springframework.web.bind.annotation.RequestMapping import org.springframework.validation.annotation.Validated import org.springframework.web.context.request.NativeWebRequest -import org.springframework.web.multipart.MultipartFile import org.springframework.beans.factory.annotation.Autowired import javax.validation.Valid @@ -54,7 +53,7 @@ class StoreApiController(@Autowired(required = true) val service: StoreApiServic value = [ApiResponse(code = 200, message = "successful operation", response = Map::class, responseContainer = "Map")]) @RequestMapping( value = ["/store/inventory"], - produces = ["application/json"], + produces = ["application/json"], method = [RequestMethod.GET]) fun getInventory(): ResponseEntity> { return ResponseEntity(service.getInventory(), HttpStatus.OK) @@ -69,7 +68,7 @@ class StoreApiController(@Autowired(required = true) val service: StoreApiServic value = [ApiResponse(code = 200, message = "successful operation", response = Order::class),ApiResponse(code = 400, message = "Invalid ID supplied"),ApiResponse(code = 404, message = "Order not found")]) @RequestMapping( value = ["/store/order/{orderId}"], - produces = ["application/xml", "application/json"], + produces = ["application/xml", "application/json"], method = [RequestMethod.GET]) fun getOrderById(@Min(1L) @Max(5L) @ApiParam(value = "ID of pet that needs to be fetched", required=true) @PathVariable("orderId") orderId: Long): ResponseEntity { return ResponseEntity(service.getOrderById(orderId), HttpStatus.OK) @@ -84,7 +83,7 @@ class StoreApiController(@Autowired(required = true) val service: StoreApiServic value = [ApiResponse(code = 200, message = "successful operation", response = Order::class),ApiResponse(code = 400, message = "Invalid Order")]) @RequestMapping( value = ["/store/order"], - produces = ["application/xml", "application/json"], + produces = ["application/xml", "application/json"], method = [RequestMethod.POST]) fun placeOrder(@ApiParam(value = "order placed for purchasing the pet" ,required=true ) @Valid @RequestBody body: Order): ResponseEntity { return ResponseEntity(service.placeOrder(body), HttpStatus.OK) diff --git a/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/StoreApiServiceImpl.kt b/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/StoreApiServiceImpl.kt index ec26e074ac6f..f38e0eca525e 100644 --- a/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/StoreApiServiceImpl.kt +++ b/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/StoreApiServiceImpl.kt @@ -2,7 +2,6 @@ package org.openapitools.api import org.openapitools.model.Order import org.springframework.stereotype.Service - @Service class StoreApiServiceImpl : StoreApiService { diff --git a/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/UserApi.kt b/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/UserApi.kt index cefc4e4f25bf..05a6dce1efa3 100644 --- a/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/UserApi.kt +++ b/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/UserApi.kt @@ -15,7 +15,6 @@ import org.springframework.web.bind.annotation.RequestMethod import org.springframework.web.bind.annotation.RequestMapping import org.springframework.validation.annotation.Validated import org.springframework.web.context.request.NativeWebRequest -import org.springframework.web.multipart.MultipartFile import org.springframework.beans.factory.annotation.Autowired import javax.validation.Valid @@ -91,7 +90,7 @@ class UserApiController(@Autowired(required = true) val service: UserApiService) value = [ApiResponse(code = 200, message = "successful operation", response = User::class),ApiResponse(code = 400, message = "Invalid username supplied"),ApiResponse(code = 404, message = "User not found")]) @RequestMapping( value = ["/user/{username}"], - produces = ["application/xml", "application/json"], + produces = ["application/xml", "application/json"], method = [RequestMethod.GET]) fun getUserByName(@ApiParam(value = "The name that needs to be fetched. Use user1 for testing.", required=true) @PathVariable("username") username: String): ResponseEntity { return ResponseEntity(service.getUserByName(username), HttpStatus.OK) @@ -106,7 +105,7 @@ class UserApiController(@Autowired(required = true) val service: UserApiService) value = [ApiResponse(code = 200, message = "successful operation", response = String::class),ApiResponse(code = 400, message = "Invalid username/password supplied")]) @RequestMapping( value = ["/user/login"], - produces = ["application/xml", "application/json"], + produces = ["application/xml", "application/json"], method = [RequestMethod.GET]) fun loginUser(@NotNull @ApiParam(value = "The user name for login", required = true) @Valid @RequestParam(value = "username", required = true) username: String,@NotNull @ApiParam(value = "The password for login in clear text", required = true) @Valid @RequestParam(value = "password", required = true) password: String): ResponseEntity { return ResponseEntity(service.loginUser(username, password), HttpStatus.OK) diff --git a/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/UserApiServiceImpl.kt b/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/UserApiServiceImpl.kt index cb579c2c16f2..da6787b8838d 100644 --- a/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/UserApiServiceImpl.kt +++ b/samples/server/petstore/kotlin-springboot/src/main/kotlin/org/openapitools/api/UserApiServiceImpl.kt @@ -2,7 +2,6 @@ package org.openapitools.api import org.openapitools.model.User import org.springframework.stereotype.Service - @Service class UserApiServiceImpl : UserApiService {