forked from loafle/openapi-generator-original
[REQ] resolve #17544 Add x-field-extra-annotation and x-class-extra-annotation for kotlin generator (#19899)
Co-authored-by: Aliaksandr SEMIANKEVICH <aliaksandrsemian.epam@navan.tech>
This commit is contained in:
parent
071540f55a
commit
e9c3c63732
@ -51,6 +51,14 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|
||||
|useSettingsGradle|Whether the project uses settings.gradle.| |false|
|
||||
|useSpringBoot3|Whether to use the Spring Boot 3 with the jvm-spring-webclient library.| |false|
|
||||
|
||||
## SUPPORTED VENDOR EXTENSIONS
|
||||
|
||||
| Extension name | Description | Applicable for | Default value |
|
||||
| -------------- | ----------- | -------------- | ------------- |
|
||||
|x-class-extra-annotation|List of custom annotations to be added to model|MODEL|null
|
||||
|x-field-extra-annotation|List of custom annotations to be added to property|FIELD, OPERATION_PARAMETER|null
|
||||
|
||||
|
||||
## IMPORT MAPPING
|
||||
|
||||
| Type/Alias | Imports |
|
||||
|
@ -38,6 +38,7 @@ import org.openapitools.codegen.CodegenParameter;
|
||||
import org.openapitools.codegen.CodegenProperty;
|
||||
import org.openapitools.codegen.CodegenType;
|
||||
import org.openapitools.codegen.SupportingFile;
|
||||
import org.openapitools.codegen.VendorExtension;
|
||||
import org.openapitools.codegen.meta.features.ClientModificationFeature;
|
||||
import org.openapitools.codegen.meta.features.DocumentationFeature;
|
||||
import org.openapitools.codegen.meta.features.GlobalFeature;
|
||||
@ -1049,4 +1050,12 @@ public class KotlinClientCodegen extends AbstractKotlinCodegen {
|
||||
System.out.println("# Please support his work directly via https://patreon.com/jimschubert \uD83D\uDE4F #");
|
||||
System.out.println("################################################################################");
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<VendorExtension> getSupportedVendorExtensions() {
|
||||
var extensions = super.getSupportedVendorExtensions();
|
||||
extensions.add(VendorExtension.X_CLASS_EXTRA_ANNOTATION);
|
||||
extensions.add(VendorExtension.X_FIELD_EXTRA_ANNOTATION);
|
||||
return extensions;
|
||||
}
|
||||
}
|
||||
|
@ -74,6 +74,9 @@ import {{packageName}}.infrastructure.ITransformForStorage
|
||||
@Deprecated(message = "This schema is deprecated.")
|
||||
{{/isDeprecated}}
|
||||
{{>additionalModelTypeAnnotations}}
|
||||
{{#vendorExtensions.x-class-extra-annotation}}
|
||||
{{{vendorExtensions.x-class-extra-annotation}}}
|
||||
{{/vendorExtensions.x-class-extra-annotation}}
|
||||
{{#nonPublicApi}}internal {{/nonPublicApi}}{{#discriminator}}interface{{/discriminator}}{{^discriminator}}{{#hasVars}}data {{/hasVars}}class{{/discriminator}} {{classname}}{{^discriminator}} (
|
||||
|
||||
{{#allVars}}
|
||||
@ -194,7 +197,7 @@ import {{packageName}}.infrastructure.ITransformForStorage
|
||||
companion object {
|
||||
var openapiFields = HashSet<String>()
|
||||
var openapiRequiredFields = HashSet<String>()
|
||||
|
||||
|
||||
init {
|
||||
{{#allVars}}
|
||||
{{#-first}}
|
||||
@ -210,7 +213,7 @@ import {{packageName}}.infrastructure.ITransformForStorage
|
||||
openapiRequiredFields.add("{{baseName}}")
|
||||
{{/requiredVars}}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates the JSON Element and throws an exception if issues found
|
||||
*
|
||||
@ -227,7 +230,7 @@ import {{packageName}}.infrastructure.ITransformForStorage
|
||||
{{^hasChildren}}
|
||||
{{#requiredVars}}
|
||||
{{#-first}}
|
||||
|
||||
|
||||
// check to make sure all required properties/fields are present in the JSON string
|
||||
for (requiredField in openapiRequiredFields) {
|
||||
requireNotNull(jsonElement!!.getAsJsonObject()[requiredField]) {
|
||||
@ -249,7 +252,7 @@ import {{packageName}}.infrastructure.ITransformForStorage
|
||||
if (!jsonObj.get("{{{baseName}}}").isJsonArray) {
|
||||
throw IllegalArgumentException(String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj["{{{baseName}}}"].toString()))
|
||||
}
|
||||
|
||||
|
||||
// validate the required field `{{{baseName}}}` (array)
|
||||
for (i in 0 until jsonObj.getAsJsonArray("{{{baseName}}}").size()) {
|
||||
{{{items.dataType}}}.validateJsonElement(jsonObj.getAsJsonArray("{{{baseName}}}").get(i))
|
||||
@ -262,7 +265,7 @@ import {{packageName}}.infrastructure.ITransformForStorage
|
||||
require(jsonObj["{{{baseName}}}"].isJsonArray) {
|
||||
String.format("Expected the field `{{{baseName}}}` to be an array in the JSON string but got `%s`", jsonObj["{{{baseName}}}"].toString())
|
||||
}
|
||||
|
||||
|
||||
// validate the optional field `{{{baseName}}}` (array)
|
||||
for (i in 0 until jsonObj.getAsJsonArray("{{{baseName}}}").size()) {
|
||||
{{{items.dataType}}}.validateJsonElement(jsonObj.getAsJsonArray("{{{baseName}}}").get(i))
|
||||
|
@ -15,6 +15,9 @@
|
||||
{{^isEnum}}{{^isArray}}{{^isPrimitiveType}}{{^isModel}}@Contextual {{/isModel}}{{/isPrimitiveType}}{{/isArray}}{{/isEnum}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}")
|
||||
{{/kotlinx_serialization}}
|
||||
{{/multiplatform}}
|
||||
{{#vendorExtensions.x-field-extra-annotation}}
|
||||
{{{vendorExtensions.x-field-extra-annotation}}}
|
||||
{{/vendorExtensions.x-field-extra-annotation}}
|
||||
{{#deprecated}}
|
||||
@Deprecated(message = "This property is deprecated.")
|
||||
{{/deprecated}}
|
||||
|
@ -15,6 +15,9 @@
|
||||
{{^isEnum}}{{^isArray}}{{^isPrimitiveType}}{{^isModel}}@Contextual {{/isModel}}{{/isPrimitiveType}}{{/isArray}}{{/isEnum}}@SerialName(value = "{{{vendorExtensions.x-base-name-literal}}}")
|
||||
{{/kotlinx_serialization}}
|
||||
{{/multiplatform}}
|
||||
{{#vendorExtensions.x-field-extra-annotation}}
|
||||
{{{vendorExtensions.x-field-extra-annotation}}}
|
||||
{{/vendorExtensions.x-field-extra-annotation}}
|
||||
{{#deprecated}}
|
||||
@Deprecated(message = "This property is deprecated.")
|
||||
{{/deprecated}}
|
||||
|
@ -50,7 +50,7 @@ import java.util.Map;
|
||||
@SuppressWarnings("static-method")
|
||||
public class KotlinClientCodegenModelTest {
|
||||
|
||||
private Schema getArrayTestSchema() {
|
||||
private Schema<?> getArrayTestSchema() {
|
||||
return new ObjectSchema()
|
||||
.description("a sample model")
|
||||
.addProperties("id", new IntegerSchema().format("int64"))
|
||||
@ -58,7 +58,7 @@ public class KotlinClientCodegenModelTest {
|
||||
.addRequiredItem("id");
|
||||
}
|
||||
|
||||
private Schema getSimpleSchema() {
|
||||
private Schema<?> getSimpleSchema() {
|
||||
return new ObjectSchema()
|
||||
.description("a sample model")
|
||||
.addProperties("id", new IntegerSchema().format("int64"))
|
||||
@ -68,14 +68,14 @@ public class KotlinClientCodegenModelTest {
|
||||
.addRequiredItem("name");
|
||||
}
|
||||
|
||||
private Schema getMapSchema() {
|
||||
private Schema<?> getMapSchema() {
|
||||
return new ObjectSchema()
|
||||
.description("a sample model")
|
||||
.addProperties("mapping", new MapSchema()
|
||||
.additionalProperties(new StringSchema()));
|
||||
}
|
||||
|
||||
private Schema getComplexSchema() {
|
||||
private Schema<?> getComplexSchema() {
|
||||
return new ObjectSchema()
|
||||
.description("a sample model")
|
||||
.addProperties("child", new ObjectSchema().$ref("#/components/schemas/Child"));
|
||||
@ -83,7 +83,7 @@ public class KotlinClientCodegenModelTest {
|
||||
|
||||
@Test(description = "convert a simple model")
|
||||
public void simpleModelTest() {
|
||||
final Schema schema = getSimpleSchema();
|
||||
final Schema<?> schema = getSimpleSchema();
|
||||
final DefaultCodegen codegen = new KotlinClientCodegen();
|
||||
codegen.processOpts();
|
||||
|
||||
@ -128,7 +128,7 @@ public class KotlinClientCodegenModelTest {
|
||||
|
||||
@Test(description = "convert a simple model: threetenbp")
|
||||
public void selectDateLibraryAsThreetenbp() {
|
||||
final Schema schema = getSimpleSchema();
|
||||
final Schema<?> schema = getSimpleSchema();
|
||||
final KotlinClientCodegen codegen = new KotlinClientCodegen();
|
||||
codegen.setDateLibrary(KotlinClientCodegen.DateLibrary.THREETENBP.value);
|
||||
codegen.processOpts();
|
||||
@ -149,7 +149,7 @@ public class KotlinClientCodegenModelTest {
|
||||
|
||||
@Test(description = "convert a simple model: threetenbp-localdatetime")
|
||||
public void selectDateLibraryAsThreetenbpLocalDateTime() {
|
||||
final Schema schema = getSimpleSchema();
|
||||
final Schema<?> schema = getSimpleSchema();
|
||||
final KotlinClientCodegen codegen = new KotlinClientCodegen();
|
||||
String value = KotlinClientCodegen.DateLibrary.THREETENBP_LOCALDATETIME.value;
|
||||
Assert.assertEquals(value, "threetenbp-localdatetime");
|
||||
@ -172,7 +172,7 @@ public class KotlinClientCodegenModelTest {
|
||||
|
||||
@Test(description = "convert a simple model: date string")
|
||||
public void selectDateLibraryAsString() {
|
||||
final Schema schema = getSimpleSchema();
|
||||
final Schema<?> schema = getSimpleSchema();
|
||||
final KotlinClientCodegen codegen = new KotlinClientCodegen();
|
||||
codegen.setDateLibrary(KotlinClientCodegen.DateLibrary.STRING.value);
|
||||
codegen.processOpts();
|
||||
@ -193,7 +193,7 @@ public class KotlinClientCodegenModelTest {
|
||||
|
||||
@Test(description = "convert a simple model: date java8")
|
||||
public void selectDateLibraryAsJava8() {
|
||||
final Schema schema = getSimpleSchema();
|
||||
final Schema<?> schema = getSimpleSchema();
|
||||
final KotlinClientCodegen codegen = new KotlinClientCodegen();
|
||||
codegen.setDateLibrary(KotlinClientCodegen.DateLibrary.JAVA8.value);
|
||||
codegen.processOpts();
|
||||
@ -214,7 +214,7 @@ public class KotlinClientCodegenModelTest {
|
||||
|
||||
@Test(description = "convert a simple model: date java8-localdatetime")
|
||||
public void selectDateLibraryAsJava8LocalDateTime() {
|
||||
final Schema schema = getSimpleSchema();
|
||||
final Schema<?> schema = getSimpleSchema();
|
||||
final KotlinClientCodegen codegen = new KotlinClientCodegen();
|
||||
String value = KotlinClientCodegen.DateLibrary.JAVA8_LOCALDATETIME.value;
|
||||
Assert.assertEquals(value, "java8-localdatetime");
|
||||
@ -237,7 +237,7 @@ public class KotlinClientCodegenModelTest {
|
||||
|
||||
@Test(description = "convert a model with array property to default kotlin.Array")
|
||||
public void arrayPropertyTest() {
|
||||
final Schema model = getArrayTestSchema();
|
||||
final Schema<?> model = getArrayTestSchema();
|
||||
|
||||
final DefaultCodegen codegen = new KotlinClientCodegen();
|
||||
OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", model);
|
||||
@ -264,7 +264,7 @@ public class KotlinClientCodegenModelTest {
|
||||
|
||||
@Test(description = "convert a model with array property to a kotlin.collections.List")
|
||||
public void listPropertyTest() {
|
||||
final Schema model = getArrayTestSchema();
|
||||
final Schema<?> model = getArrayTestSchema();
|
||||
|
||||
final KotlinClientCodegen codegen = new KotlinClientCodegen();
|
||||
codegen.setCollectionType(KotlinClientCodegen.CollectionType.LIST.value);
|
||||
@ -293,7 +293,7 @@ public class KotlinClientCodegenModelTest {
|
||||
|
||||
@Test(description = "convert a model with a map property")
|
||||
public void mapPropertyTest() {
|
||||
final Schema schema = getMapSchema();
|
||||
final Schema<?> schema = getMapSchema();
|
||||
final DefaultCodegen codegen = new KotlinClientCodegen();
|
||||
OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", schema);
|
||||
codegen.setOpenAPI(openAPI);
|
||||
@ -317,7 +317,7 @@ public class KotlinClientCodegenModelTest {
|
||||
|
||||
@Test(description = "convert a model with complex property")
|
||||
public void complexPropertyTest() {
|
||||
final Schema schema = getComplexSchema();
|
||||
final Schema<?> schema = getComplexSchema();
|
||||
final DefaultCodegen codegen = new KotlinClientCodegen();
|
||||
OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema("sample", schema);
|
||||
codegen.setOpenAPI(openAPI);
|
||||
@ -351,7 +351,7 @@ public class KotlinClientCodegenModelTest {
|
||||
|
||||
@Test(dataProvider = "modelNames", description = "sanitize model names")
|
||||
public void sanitizeModelNames(final String name, final ModelNameTest testCase) {
|
||||
final Schema schema = getComplexSchema();
|
||||
final Schema<?> schema = getComplexSchema();
|
||||
final DefaultCodegen codegen = new KotlinClientCodegen();
|
||||
OpenAPI openAPI = TestUtils.createOpenAPIWithOneSchema(name, schema);
|
||||
codegen.setOpenAPI(openAPI);
|
||||
@ -448,4 +448,3 @@ public class KotlinClientCodegenModelTest {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -17,9 +17,14 @@ import org.testng.annotations.Test;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assumptions.assumeThat;
|
||||
import static org.openapitools.codegen.TestUtils.assertFileContains;
|
||||
import static org.openapitools.codegen.VendorExtension.X_CLASS_EXTRA_ANNOTATION;
|
||||
import static org.openapitools.codegen.VendorExtension.X_FIELD_EXTRA_ANNOTATION;
|
||||
|
||||
public class KotlinModelCodegenTest {
|
||||
|
||||
@ -110,4 +115,20 @@ public class KotlinModelCodegenTest {
|
||||
assertFileContains(Paths.get(outputPath + "/src/main/kotlin/models/UniqueArray.kt"),
|
||||
"var array: kotlin.collections.MutableSet<kotlin.String>");
|
||||
}
|
||||
|
||||
@Test(dataProvider = "generators")
|
||||
public void xFieldExtraAnnotation(AbstractKotlinCodegen codegen) throws IOException {
|
||||
assumeThat(codegen.getSupportedVendorExtensions().contains(X_FIELD_EXTRA_ANNOTATION)).isTrue();
|
||||
String outputPath = generateModels(codegen, "src/test/resources/3_0/issue_11772.yml", true);
|
||||
Path ktClassPath = Paths.get(outputPath + "/src/main/kotlin/models/Employee.kt");
|
||||
assertThat(ktClassPath).content().contains("@javax.persistence.Id");
|
||||
}
|
||||
|
||||
@Test(dataProvider = "generators")
|
||||
public void xClassExtraAnnotation(AbstractKotlinCodegen codegen) throws IOException {
|
||||
assumeThat(codegen.getSupportedVendorExtensions().contains(X_CLASS_EXTRA_ANNOTATION)).isTrue();
|
||||
String outputPath = generateModels(codegen, "src/test/resources/3_0/issue_11772.yml", true);
|
||||
Path ktClassPath = Paths.get(outputPath + "/src/main/kotlin/models/Employee.kt");
|
||||
assertThat(ktClassPath).content().contains("@javax.persistence.MappedSuperclass");
|
||||
}
|
||||
}
|
||||
|
@ -71,13 +71,13 @@ data class ApiAnnotation (
|
||||
companion object {
|
||||
var openapiFields = HashSet<String>()
|
||||
var openapiRequiredFields = HashSet<String>()
|
||||
|
||||
|
||||
init {
|
||||
// a set of all properties/fields (JSON key names)
|
||||
openapiFields.add("id")
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates the JSON Element and throws an exception if issues found
|
||||
*
|
||||
|
@ -79,7 +79,7 @@ data class ApiApiResponse (
|
||||
companion object {
|
||||
var openapiFields = HashSet<String>()
|
||||
var openapiRequiredFields = HashSet<String>()
|
||||
|
||||
|
||||
init {
|
||||
// a set of all properties/fields (JSON key names)
|
||||
openapiFields.add("code")
|
||||
@ -87,7 +87,7 @@ data class ApiApiResponse (
|
||||
openapiFields.add("message")
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates the JSON Element and throws an exception if issues found
|
||||
*
|
||||
|
@ -75,14 +75,14 @@ data class ApiCategory (
|
||||
companion object {
|
||||
var openapiFields = HashSet<String>()
|
||||
var openapiRequiredFields = HashSet<String>()
|
||||
|
||||
|
||||
init {
|
||||
// a set of all properties/fields (JSON key names)
|
||||
openapiFields.add("id")
|
||||
openapiFields.add("name")
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates the JSON Element and throws an exception if issues found
|
||||
*
|
||||
|
@ -102,7 +102,7 @@ data class ApiOrder (
|
||||
companion object {
|
||||
var openapiFields = HashSet<String>()
|
||||
var openapiRequiredFields = HashSet<String>()
|
||||
|
||||
|
||||
init {
|
||||
// a set of all properties/fields (JSON key names)
|
||||
openapiFields.add("id")
|
||||
@ -113,7 +113,7 @@ data class ApiOrder (
|
||||
openapiFields.add("complete")
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates the JSON Element and throws an exception if issues found
|
||||
*
|
||||
|
@ -105,7 +105,7 @@ data class ApiPet (
|
||||
companion object {
|
||||
var openapiFields = HashSet<String>()
|
||||
var openapiRequiredFields = HashSet<String>()
|
||||
|
||||
|
||||
init {
|
||||
// a set of all properties/fields (JSON key names)
|
||||
openapiFields.add("name")
|
||||
@ -119,7 +119,7 @@ data class ApiPet (
|
||||
openapiRequiredFields.add("name")
|
||||
openapiRequiredFields.add("photoUrls")
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates the JSON Element and throws an exception if issues found
|
||||
*
|
||||
@ -133,7 +133,7 @@ data class ApiPet (
|
||||
String.format("The required field(s) %s in ApiPet is not found in the empty JSON string", ApiPet.openapiRequiredFields.toString())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check to make sure all required properties/fields are present in the JSON string
|
||||
for (requiredField in openapiRequiredFields) {
|
||||
requireNotNull(jsonElement!!.getAsJsonObject()[requiredField]) {
|
||||
@ -161,7 +161,7 @@ data class ApiPet (
|
||||
require(jsonObj["tags"].isJsonArray) {
|
||||
String.format("Expected the field `tags` to be an array in the JSON string but got `%s`", jsonObj["tags"].toString())
|
||||
}
|
||||
|
||||
|
||||
// validate the optional field `tags` (array)
|
||||
for (i in 0 until jsonObj.getAsJsonArray("tags").size()) {
|
||||
ApiTag.validateJsonElement(jsonObj.getAsJsonArray("tags").get(i))
|
||||
|
@ -75,14 +75,14 @@ data class ApiTag (
|
||||
companion object {
|
||||
var openapiFields = HashSet<String>()
|
||||
var openapiRequiredFields = HashSet<String>()
|
||||
|
||||
|
||||
init {
|
||||
// a set of all properties/fields (JSON key names)
|
||||
openapiFields.add("id")
|
||||
openapiFields.add("name")
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates the JSON Element and throws an exception if issues found
|
||||
*
|
||||
|
@ -100,7 +100,7 @@ data class ApiUser (
|
||||
companion object {
|
||||
var openapiFields = HashSet<String>()
|
||||
var openapiRequiredFields = HashSet<String>()
|
||||
|
||||
|
||||
init {
|
||||
// a set of all properties/fields (JSON key names)
|
||||
openapiFields.add("username")
|
||||
@ -115,7 +115,7 @@ data class ApiUser (
|
||||
// a set of required properties/fields (JSON key names)
|
||||
openapiRequiredFields.add("username")
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates the JSON Element and throws an exception if issues found
|
||||
*
|
||||
@ -129,7 +129,7 @@ data class ApiUser (
|
||||
String.format("The required field(s) %s in ApiUser is not found in the empty JSON string", ApiUser.openapiRequiredFields.toString())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// check to make sure all required properties/fields are present in the JSON string
|
||||
for (requiredField in openapiRequiredFields) {
|
||||
requireNotNull(jsonElement!!.getAsJsonObject()[requiredField]) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user