mirror of
https://github.com/valitydev/openapi-generator.git
synced 2024-11-06 18:45:23 +00:00
Issue 1025: Kotlin generator doesn't support inheritance (#1026)
* allVars is duplicating child preoperties when models are inherited. Filter out these duplicates in the KotlinSpringServerCodegen * isInherited property was not being populated in the CodegenModel, re-parse the models in the KotlinSpringServerCodegen class and populate the property here * Add template support for Kotlin models which require inheritance from a base class to support oneOf declarations in the api yaml * Change optional for parameters to use Kotlins nullable * Update petstore api with Optional -> Nullable
This commit is contained in:
parent
78fae0ea49
commit
b7edad5cd0
@ -20,6 +20,7 @@ import com.google.common.collect.ImmutableMap;
|
||||
import com.samskivert.mustache.Mustache;
|
||||
import com.samskivert.mustache.Template;
|
||||
import io.swagger.v3.oas.models.OpenAPI;
|
||||
import io.swagger.v3.oas.models.media.Schema;
|
||||
import org.openapitools.codegen.*;
|
||||
import org.openapitools.codegen.languages.features.BeanValidationFeatures;
|
||||
import org.openapitools.codegen.utils.URLPathUtils;
|
||||
@ -32,6 +33,7 @@ import java.io.Writer;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
||||
public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
|
||||
@ -386,7 +388,6 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
|
||||
if (Boolean.TRUE.equals(model.hasEnums)) {
|
||||
model.imports.add("JsonValue");
|
||||
}
|
||||
|
||||
} else {
|
||||
//Needed imports for Jackson's JsonCreator
|
||||
if (additionalProperties.containsKey("jackson")) {
|
||||
@ -394,6 +395,9 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
|
||||
}
|
||||
}
|
||||
|
||||
if (model.discriminator != null && additionalProperties.containsKey("jackson")) {
|
||||
model.imports.addAll(Arrays.asList("JsonSubTypes", "JsonTypeInfo"));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -513,4 +517,16 @@ public class KotlinSpringServerCodegen extends AbstractKotlinCodegen
|
||||
writer.write(fragment.execute().replaceAll(from, to));
|
||||
}
|
||||
}
|
||||
|
||||
// Can't figure out the logic in DefaultCodegen but optional vars are getting duplicated when there's
|
||||
// inheritance involved. Also, isInherited doesn't seem to be getting set properly ¯\_(ツ)_/¯
|
||||
@Override
|
||||
public CodegenModel fromModel(String name, Schema schema, Map<String, Schema> allDefinitions) {
|
||||
CodegenModel m = super.fromModel(name, schema, allDefinitions);
|
||||
|
||||
m.optionalVars = m.optionalVars.stream().distinct().collect(Collectors.toList());
|
||||
m.allVars.stream().filter(p -> !m.vars.contains(p)).forEach(p -> p.isInherited = true);
|
||||
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
@ -3,14 +3,23 @@
|
||||
{{#vars}}
|
||||
* @param {{name}} {{{description}}}
|
||||
{{/vars}}
|
||||
*/
|
||||
data class {{classname}} (
|
||||
*/{{#discriminator}}
|
||||
{{>typeInfoAnnotation}}{{/discriminator}}
|
||||
{{#discriminator}}interface {{classname}}{{/discriminator}}{{^discriminator}}data class {{classname}} (
|
||||
{{#requiredVars}}
|
||||
{{>dataClassReqVar}}{{^-last}},
|
||||
{{/-last}}{{/requiredVars}}{{#hasRequired}}{{#hasOptional}},
|
||||
{{/hasOptional}}{{/hasRequired}}{{#optionalVars}}{{>dataClassOptVar}}{{^-last}},
|
||||
{{/-last}}{{/optionalVars}}
|
||||
) {
|
||||
) {{/discriminator}}{{#parent}}: {{{parent}}}{{/parent}}{
|
||||
{{#discriminator}}
|
||||
{{#requiredVars}}
|
||||
{{>interfaceReqVar}}
|
||||
{{/requiredVars}}
|
||||
{{#optionalVars}}
|
||||
{{>interfaceOptVar}}
|
||||
{{/optionalVars}}
|
||||
{{/discriminator}}
|
||||
{{#hasEnums}}{{#vars}}{{#isEnum}}
|
||||
/**
|
||||
* {{{description}}}
|
||||
|
@ -1,4 +1,4 @@
|
||||
{{#useBeanValidation}}{{#required}}
|
||||
@get:NotNull {{/required}}{{>beanValidationModel}}{{/useBeanValidation}}{{#swaggerAnnotations}}
|
||||
@ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}"){{/swaggerAnnotations}}
|
||||
@JsonProperty("{{{baseName}}}") val {{{name}}}: {{#isEnum}}{{classname}}.{{nameInCamelCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{#defaultvalue}}{{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}null{{/defaultvalue}}
|
||||
@JsonProperty("{{{baseName}}}"){{#isInherited}} override{{/isInherited}} val {{{name}}}: {{#isEnum}}{{classname}}.{{nameInCamelCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? = {{#defaultvalue}}{{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}null{{/defaultvalue}}
|
@ -1,4 +1,4 @@
|
||||
{{#useBeanValidation}}{{#required}}
|
||||
@get:NotNull {{/required}}{{>beanValidationModel}}{{/useBeanValidation}}{{#swaggerAnnotations}}
|
||||
@ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}"){{/swaggerAnnotations}}
|
||||
@JsonProperty("{{{baseName}}}") val {{{name}}}: {{#isEnum}}{{classname}}.{{nameInCamelCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}
|
||||
@JsonProperty("{{{baseName}}}"){{#isInherited}} override{{/isInherited}} val {{{name}}}: {{#isEnum}}{{classname}}.{{nameInCamelCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}
|
@ -0,0 +1,3 @@
|
||||
{{#swaggerAnnotations}}
|
||||
@ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}"){{/swaggerAnnotations}}
|
||||
val {{{name}}}: {{#isEnum}}{{classname}}.{{nameInCamelCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}? {{^discriminator}}= {{#defaultvalue}}{{defaultvalue}}{{/defaultvalue}}{{^defaultvalue}}null{{/defaultvalue}}{{/discriminator}}
|
@ -0,0 +1,3 @@
|
||||
{{#swaggerAnnotations}}
|
||||
@ApiModelProperty({{#example}}example = "{{{example}}}", {{/example}}{{#required}}required = {{required}}, {{/required}}{{#isReadOnly}}readOnly = {{{isReadOnly}}}, {{/isReadOnly}}value = "{{{description}}}"){{/swaggerAnnotations}}
|
||||
val {{{name}}}: {{#isEnum}}{{classname}}.{{nameInCamelCase}}{{/isEnum}}{{^isEnum}}{{{dataType}}}{{/isEnum}}
|
@ -1 +1 @@
|
||||
{{#useOptional}}{{#required}}{{{dataType}}}{{/required}}{{^required}}Optional<{{{dataType}}}>{{/required}}{{/useOptional}}{{^useOptional}}{{{dataType}}}{{/useOptional}}
|
||||
{{#required}}{{{dataType}}}{{/required}}{{^required}}{{{dataType}}}?{{/required}}
|
@ -0,0 +1,8 @@
|
||||
{{#jackson}}
|
||||
|
||||
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "{{{discriminatorName}}}", visible = true)
|
||||
@JsonSubTypes(
|
||||
{{#discriminator.mappedModels}}
|
||||
JsonSubTypes.Type(value = {{modelName}}::class, name = "{{^vendorExtensions.x-discriminator-value}}{{mappingName}}{{/vendorExtensions.x-discriminator-value}}{{#vendorExtensions.x-discriminator-value}}{{{vendorExtensions.x-discriminator-value}}}{{/vendorExtensions.x-discriminator-value}}"){{^-last}},{{/-last}}
|
||||
{{/discriminator.mappedModels}}
|
||||
){{/jackson}}
|
@ -56,7 +56,7 @@ class PetApiController(@Autowired(required = true) val service: PetApiService) {
|
||||
@RequestMapping(
|
||||
value = ["/pet/{petId}"],
|
||||
method = [RequestMethod.DELETE])
|
||||
fun deletePet(@ApiParam(value = "Pet id to delete", required=true) @PathVariable("petId") petId: kotlin.Long,@ApiParam(value = "" ) @RequestHeader(value="api_key", required=false) apiKey: kotlin.String): ResponseEntity<Unit> {
|
||||
fun deletePet(@ApiParam(value = "Pet id to delete", required=true) @PathVariable("petId") petId: kotlin.Long,@ApiParam(value = "" ) @RequestHeader(value="api_key", required=false) apiKey: kotlin.String?): ResponseEntity<Unit> {
|
||||
return ResponseEntity(service.deletePet(petId, apiKey), HttpStatus.OK)
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ interface PetApiService {
|
||||
|
||||
fun addPet(pet: Pet): Unit
|
||||
|
||||
fun deletePet(petId: kotlin.Long,apiKey: kotlin.String): Unit
|
||||
fun deletePet(petId: kotlin.Long,apiKey: kotlin.String?): Unit
|
||||
|
||||
fun findPetsByStatus(status: kotlin.Array<kotlin.String>): List<Pet>
|
||||
|
||||
@ -17,7 +17,7 @@ interface PetApiService {
|
||||
|
||||
fun updatePet(pet: Pet): Unit
|
||||
|
||||
fun updatePetWithForm(petId: kotlin.Long,name: kotlin.String,status: kotlin.String): Unit
|
||||
fun updatePetWithForm(petId: kotlin.Long,name: kotlin.String?,status: kotlin.String?): Unit
|
||||
|
||||
fun uploadFile(petId: kotlin.Long,additionalMetadata: kotlin.String,file: org.springframework.web.multipart.MultipartFile): ModelApiResponse
|
||||
fun uploadFile(petId: kotlin.Long,additionalMetadata: kotlin.String?,file: org.springframework.web.multipart.MultipartFile): ModelApiResponse
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ class PetApiServiceImpl : PetApiService {
|
||||
TODO("Implement me")
|
||||
}
|
||||
|
||||
override fun deletePet(petId: kotlin.Long,apiKey: kotlin.String): Unit {
|
||||
override fun deletePet(petId: kotlin.Long,apiKey: kotlin.String?): Unit {
|
||||
TODO("Implement me")
|
||||
}
|
||||
|
||||
@ -31,11 +31,11 @@ class PetApiServiceImpl : PetApiService {
|
||||
TODO("Implement me")
|
||||
}
|
||||
|
||||
override fun updatePetWithForm(petId: kotlin.Long,name: kotlin.String,status: kotlin.String): Unit {
|
||||
override fun updatePetWithForm(petId: kotlin.Long,name: kotlin.String?,status: kotlin.String?): Unit {
|
||||
TODO("Implement me")
|
||||
}
|
||||
|
||||
override fun uploadFile(petId: kotlin.Long,additionalMetadata: kotlin.String,file: org.springframework.web.multipart.MultipartFile): ModelApiResponse {
|
||||
override fun uploadFile(petId: kotlin.Long,additionalMetadata: kotlin.String?,file: org.springframework.web.multipart.MultipartFile): ModelApiResponse {
|
||||
TODO("Implement me")
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ class PetApiController(@Autowired(required = true) val service: PetApiService) {
|
||||
@RequestMapping(
|
||||
value = ["/pet/{petId}"],
|
||||
method = [RequestMethod.DELETE])
|
||||
fun deletePet(@ApiParam(value = "Pet id to delete", required=true) @PathVariable("petId") petId: kotlin.Long,@ApiParam(value = "" ) @RequestHeader(value="api_key", required=false) apiKey: kotlin.String): ResponseEntity<Unit> {
|
||||
fun deletePet(@ApiParam(value = "Pet id to delete", required=true) @PathVariable("petId") petId: kotlin.Long,@ApiParam(value = "" ) @RequestHeader(value="api_key", required=false) apiKey: kotlin.String?): ResponseEntity<Unit> {
|
||||
return ResponseEntity(service.deletePet(petId, apiKey), HttpStatus.OK)
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@ interface PetApiService {
|
||||
|
||||
fun addPet(pet: Pet): Unit
|
||||
|
||||
fun deletePet(petId: kotlin.Long,apiKey: kotlin.String): Unit
|
||||
fun deletePet(petId: kotlin.Long,apiKey: kotlin.String?): Unit
|
||||
|
||||
fun findPetsByStatus(status: kotlin.Array<kotlin.String>): List<Pet>
|
||||
|
||||
@ -17,7 +17,7 @@ interface PetApiService {
|
||||
|
||||
fun updatePet(pet: Pet): Unit
|
||||
|
||||
fun updatePetWithForm(petId: kotlin.Long,name: kotlin.String,status: kotlin.String): Unit
|
||||
fun updatePetWithForm(petId: kotlin.Long,name: kotlin.String?,status: kotlin.String?): Unit
|
||||
|
||||
fun uploadFile(petId: kotlin.Long,additionalMetadata: kotlin.String,file: org.springframework.web.multipart.MultipartFile): ModelApiResponse
|
||||
fun uploadFile(petId: kotlin.Long,additionalMetadata: kotlin.String?,file: org.springframework.web.multipart.MultipartFile): ModelApiResponse
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ class PetApiServiceImpl : PetApiService {
|
||||
TODO("Implement me")
|
||||
}
|
||||
|
||||
override fun deletePet(petId: kotlin.Long,apiKey: kotlin.String): Unit {
|
||||
override fun deletePet(petId: kotlin.Long,apiKey: kotlin.String?): Unit {
|
||||
TODO("Implement me")
|
||||
}
|
||||
|
||||
@ -31,11 +31,11 @@ class PetApiServiceImpl : PetApiService {
|
||||
TODO("Implement me")
|
||||
}
|
||||
|
||||
override fun updatePetWithForm(petId: kotlin.Long,name: kotlin.String,status: kotlin.String): Unit {
|
||||
override fun updatePetWithForm(petId: kotlin.Long,name: kotlin.String?,status: kotlin.String?): Unit {
|
||||
TODO("Implement me")
|
||||
}
|
||||
|
||||
override fun uploadFile(petId: kotlin.Long,additionalMetadata: kotlin.String,file: org.springframework.web.multipart.MultipartFile): ModelApiResponse {
|
||||
override fun uploadFile(petId: kotlin.Long,additionalMetadata: kotlin.String?,file: org.springframework.web.multipart.MultipartFile): ModelApiResponse {
|
||||
TODO("Implement me")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user