From c2debf2f722fa90f3d89614cb143325f9a113d77 Mon Sep 17 00:00:00 2001 From: altro3 Date: Fri, 6 Dec 2024 13:17:52 +0700 Subject: [PATCH] Fixed request body enum Fixed #1896 --- .../AbstractMicronautJavaCodegen.java | 63 ++++++++++++++++++- .../AbstractMicronautKotlinCodegen.java | 57 ++++++++++++++++- .../JavaMicronautClientCodegenTest.java | 18 +++++- .../JavaMicronautServerCodegenTest.java | 2 +- .../KotlinMicronautClientCodegenTest.java | 18 +++++- .../KotlinMicronautServerCodegenTest.java | 2 +- .../src/test/resources/3_0/body-enum.yml | 42 +++++++++++++ 7 files changed, 196 insertions(+), 6 deletions(-) create mode 100644 openapi-generator/src/test/resources/3_0/body-enum.yml diff --git a/openapi-generator/src/main/java/io/micronaut/openapi/generator/AbstractMicronautJavaCodegen.java b/openapi-generator/src/main/java/io/micronaut/openapi/generator/AbstractMicronautJavaCodegen.java index 127fd2615..850cc3358 100644 --- a/openapi-generator/src/main/java/io/micronaut/openapi/generator/AbstractMicronautJavaCodegen.java +++ b/openapi-generator/src/main/java/io/micronaut/openapi/generator/AbstractMicronautJavaCodegen.java @@ -26,6 +26,7 @@ import io.swagger.v3.oas.models.media.MediaType; import io.swagger.v3.oas.models.media.Schema; import io.swagger.v3.oas.models.parameters.Parameter; +import io.swagger.v3.oas.models.parameters.RequestBody; import io.swagger.v3.oas.models.responses.ApiResponse; import io.swagger.v3.oas.models.servers.Server; import io.swagger.v3.parser.util.SchemaTypeUtil; @@ -732,6 +733,62 @@ public String toModelTestFilename(String name) { return toModelName(name) + "Test"; } + @Override + public CodegenParameter fromRequestBody(RequestBody body, Set imports, String bodyParameterName) { + var rqBody = super.fromRequestBody(body, imports, bodyParameterName); + + var rqBodySchema = body.getContent() != null && !body.getContent().isEmpty() ? body.getContent().entrySet().iterator().next().getValue().getSchema() : null; + CodegenProperty codegenProperty = fromProperty(bodyParameterName, rqBodySchema, false); + + if (rqBodySchema != null) { + rqBodySchema = unaliasSchema(rqBodySchema); + + if (getUseInlineModelResolver()) { + codegenProperty = fromProperty(bodyParameterName, getReferencedSchemaWhenNotEnum(rqBodySchema), false); + } else { + codegenProperty = fromProperty(bodyParameterName, rqBodySchema, false); + } + rqBody.setSchema(codegenProperty); + } + + if (Boolean.TRUE.equals(codegenProperty.isModel)) { + rqBody.isModel = true; + } + + rqBody.dataFormat = codegenProperty.dataFormat; + if (body.getRequired() != null) { + rqBody.required = body.getRequired(); + } + + // set containerType + rqBody.containerType = codegenProperty.containerType; + rqBody.containerTypeMapped = codegenProperty.containerTypeMapped; + + // enum + updateCodegenPropertyEnum(codegenProperty); + rqBody.isEnum = codegenProperty.isEnum; + rqBody.isEnumRef = codegenProperty.isEnumRef; + rqBody._enum = codegenProperty._enum; + rqBody.allowableValues = codegenProperty.allowableValues; + + if (codegenProperty.isEnum || codegenProperty.isEnumRef) { + rqBody.datatypeWithEnum = codegenProperty.datatypeWithEnum; + rqBody.enumName = codegenProperty.enumName; + if (codegenProperty.defaultValue != null) { + rqBody.enumDefaultValue = codegenProperty.defaultValue.replace(codegenProperty.enumName + ".", ""); + } + } + return rqBody; + } + + private Schema getReferencedSchemaWhenNotEnum(Schema parameterSchema) { + Schema referencedSchema = ModelUtils.getReferencedSchema(openAPI, parameterSchema); + if (referencedSchema.getEnum() != null && !referencedSchema.getEnum().isEmpty()) { + referencedSchema = parameterSchema; + } + return referencedSchema; + } + @Override public CodegenParameter fromParameter(Parameter p, Set imports) { var parameter = super.fromParameter(p, imports); @@ -816,7 +873,11 @@ public CodegenProperty fromProperty(String name, Schema schema, boolean required property.vendorExtensions.put("realName", realName); if (schema != null && schema.get$ref() != null) { - schema = ModelUtils.getSchemaFromRefToSchemaWithProperties(openAPI, schema.get$ref()); + var refSchema = ModelUtils.getSchemaFromRefToSchemaWithProperties(openAPI, schema.get$ref()); + if (refSchema == null) { + refSchema = ModelUtils.getReferencedSchema(openAPI, schema); + } + schema = refSchema; } String defaultValueInit; diff --git a/openapi-generator/src/main/java/io/micronaut/openapi/generator/AbstractMicronautKotlinCodegen.java b/openapi-generator/src/main/java/io/micronaut/openapi/generator/AbstractMicronautKotlinCodegen.java index 25ea98fc5..4c23dee36 100644 --- a/openapi-generator/src/main/java/io/micronaut/openapi/generator/AbstractMicronautKotlinCodegen.java +++ b/openapi-generator/src/main/java/io/micronaut/openapi/generator/AbstractMicronautKotlinCodegen.java @@ -1425,6 +1425,49 @@ public String toModelName(final String name) { @Override public CodegenParameter fromRequestBody(RequestBody body, Set imports, String bodyParameterName) { var rqBody = super.fromRequestBody(body, imports, bodyParameterName); + + var rqBodySchema = body.getContent() != null && !body.getContent().isEmpty() ? body.getContent().entrySet().iterator().next().getValue().getSchema() : null; + CodegenProperty codegenProperty = fromProperty(bodyParameterName, rqBodySchema, false); + + if (rqBodySchema != null) { + rqBodySchema = unaliasSchema(rqBodySchema); + + if (getUseInlineModelResolver()) { + codegenProperty = fromProperty(bodyParameterName, getReferencedSchemaWhenNotEnum(rqBodySchema), false); + } else { + codegenProperty = fromProperty(bodyParameterName, rqBodySchema, false); + } + rqBody.setSchema(codegenProperty); + } + + if (Boolean.TRUE.equals(codegenProperty.isModel)) { + rqBody.isModel = true; + } + + rqBody.dataFormat = codegenProperty.dataFormat; + if (body.getRequired() != null) { + rqBody.required = body.getRequired(); + } + + // set containerType + rqBody.containerType = codegenProperty.containerType; + rqBody.containerTypeMapped = codegenProperty.containerTypeMapped; + + // enum + updateCodegenPropertyEnum(codegenProperty); + rqBody.isEnum = codegenProperty.isEnum; + rqBody.isEnumRef = codegenProperty.isEnumRef; + rqBody._enum = codegenProperty._enum; + rqBody.allowableValues = codegenProperty.allowableValues; + + if (codegenProperty.isEnum || codegenProperty.isEnumRef) { + rqBody.datatypeWithEnum = codegenProperty.datatypeWithEnum; + rqBody.enumName = codegenProperty.enumName; + if (codegenProperty.defaultValue != null) { + rqBody.enumDefaultValue = codegenProperty.defaultValue.replace(codegenProperty.enumName + ".", ""); + } + } + if (!rqBody.required) { rqBody.vendorExtensions.put("defaultValueInit", "null"); } @@ -1432,6 +1475,14 @@ public CodegenParameter fromRequestBody(RequestBody body, Set imports, S return rqBody; } + private Schema getReferencedSchemaWhenNotEnum(Schema parameterSchema) { + Schema referencedSchema = ModelUtils.getReferencedSchema(openAPI, parameterSchema); + if (referencedSchema.getEnum() != null && !referencedSchema.getEnum().isEmpty()) { + referencedSchema = parameterSchema; + } + return referencedSchema; + } + @Override public CodegenParameter fromParameter(Parameter p, Set imports) { var parameter = super.fromParameter(p, imports); @@ -1512,7 +1563,11 @@ public CodegenProperty fromProperty(String name, Schema schema, boolean required property.vendorExtensions.put("realName", realName); if (schema != null && schema.get$ref() != null) { - schema = ModelUtils.getSchemaFromRefToSchemaWithProperties(openAPI, schema.get$ref()); + var refSchema = ModelUtils.getSchemaFromRefToSchemaWithProperties(openAPI, schema.get$ref()); + if (refSchema == null) { + refSchema = ModelUtils.getReferencedSchema(openAPI, schema); + } + schema = refSchema; } String defaultValueInit; diff --git a/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautClientCodegenTest.java b/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautClientCodegenTest.java index c3d765ccb..5f0627521 100644 --- a/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautClientCodegenTest.java +++ b/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautClientCodegenTest.java @@ -17,7 +17,7 @@ class JavaMicronautClientCodegenTest extends AbstractMicronautCodegenTest { @Test - void clientOptsUnicity() { + void clientOptsUniqueness() { var codegen = new JavaMicronautClientCodegen(); codegen.cliOptions() .stream() @@ -1460,4 +1460,20 @@ public int hashCode() { } """); } + + @Test + void testBodyEnum() { + + var codegen = new JavaMicronautClientCodegen(); + String outputPath = generateFiles(codegen, "src/test/resources/3_0/body-enum.yml", CodegenConstants.APIS, CodegenConstants.MODELS); + String path = outputPath + "src/main/java/org/openapitools/"; + + assertFileContains(path + "api/MyCustomApi.java", """ + @Post("/api/v1/colors/{name}") + Mono<@NotNull String> selectColor( + @Body @NotNull Color body + ); + """); + assertFileContains(path + "model/Color.java", "public enum Color {"); + } } diff --git a/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautServerCodegenTest.java b/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautServerCodegenTest.java index 3aa28a4d0..afb9cde18 100644 --- a/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautServerCodegenTest.java +++ b/openapi-generator/src/test/java/io/micronaut/openapi/generator/JavaMicronautServerCodegenTest.java @@ -18,7 +18,7 @@ class JavaMicronautServerCodegenTest extends AbstractMicronautCodegenTest { static String MULTI_TAGS_TEST_PATH = "src/test/resources/3_0/micronaut/multi-tags-test.yaml"; @Test - void clientOptsUnicity() { + void clientOptsUniqueness() { var codegen = new JavaMicronautServerCodegen(); codegen.cliOptions() .stream() diff --git a/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautClientCodegenTest.java b/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautClientCodegenTest.java index 6a6443334..e909f85cf 100644 --- a/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautClientCodegenTest.java +++ b/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautClientCodegenTest.java @@ -17,7 +17,7 @@ class KotlinMicronautClientCodegenTest extends AbstractMicronautCodegenTest { @Test - void clientOptsUnicity() { + void clientOptsUniqueness() { var codegen = new KotlinMicronautClientCodegen(); codegen.cliOptions() .stream() @@ -1468,4 +1468,20 @@ fun sendPrimitives( ): Mono """); } + + @Test + void testBodyEnum() { + + var codegen = new KotlinMicronautClientCodegen(); + String outputPath = generateFiles(codegen, "src/test/resources/3_0/body-enum.yml", CodegenConstants.APIS, CodegenConstants.MODELS); + String path = outputPath + "src/main/kotlin/org/openapitools/"; + + assertFileContains(path + "api/MyCustomApi.kt", """ + @Post("/api/v1/colors/{name}") + fun selectColor( + @Body @NotNull body: Color + ): Mono + """); + assertFileContains(path + "model/Color.kt", "enum class Color("); + } } diff --git a/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautServerCodegenTest.java b/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautServerCodegenTest.java index 077584a5e..161414a41 100644 --- a/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautServerCodegenTest.java +++ b/openapi-generator/src/test/java/io/micronaut/openapi/generator/KotlinMicronautServerCodegenTest.java @@ -17,7 +17,7 @@ class KotlinMicronautServerCodegenTest extends AbstractMicronautCodegenTest { static String MULTI_TAGS_TEST_PATH = "src/test/resources/3_0/micronaut/multi-tags-test.yaml"; @Test - void clientOptsUnicity() { + void clientOptsUniqueness() { var codegen = new KotlinMicronautServerCodegen(); codegen.cliOptions() .stream() diff --git a/openapi-generator/src/test/resources/3_0/body-enum.yml b/openapi-generator/src/test/resources/3_0/body-enum.yml new file mode 100644 index 000000000..311ea024c --- /dev/null +++ b/openapi-generator/src/test/resources/3_0/body-enum.yml @@ -0,0 +1,42 @@ +openapi: 3.1.0 +info: + version: '1.0.0' + title: 'OpenAPI BUG REST API' +servers: + - url: 'localhost:3000' + +paths: + /api/v1/colors/{name}: + post: + tags: [ my-custom ] + operationId: "selectColor" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/Color" + responses: + "200": + description: "OK" + content: + application/json: + schema: + type: string + +components: + schemas: + + Color: + type: string + enum: + - GREEN + - RED + - WHITE + - BLACK + - YELLOW + - BLUE + +tags: + - name: my-custom + description: 'All API operations'